나는 boost :: filesystem을 사용하여 디렉터리의 파일을 검색하고 처리합니다. 그러나 boost :: filesystem :: is_regular_file()을 사용하여 확인한 모든 파일을 처리하는 대신 텍스트 파일 만 처리하거나 적어도 이진 파일을 무시합니다.C++ : 확장명없이 파일 형식을 확인하는 방법
파일 에이 없어도 달성 할 수있는 방법이 있습니까?
저는 플랫폼에 독립적 인 솔루션을 매우 높이 평가할 것입니다.
나는 boost :: filesystem을 사용하여 디렉터리의 파일을 검색하고 처리합니다. 그러나 boost :: filesystem :: is_regular_file()을 사용하여 확인한 모든 파일을 처리하는 대신 텍스트 파일 만 처리하거나 적어도 이진 파일을 무시합니다.C++ : 확장명없이 파일 형식을 확인하는 방법
파일 에이 없어도 달성 할 수있는 방법이 있습니까?
저는 플랫폼에 독립적 인 솔루션을 매우 높이 평가할 것입니다.
Libmagic은 모든 주요 플랫폼 (및 많은 미성년자)에서 사용할 수 있습니다.
#include <boost/filesystem.hpp>
#include <boost/range.hpp>
#include <iostream>
#include <magic.h>
using namespace boost;
namespace fs = filesystem;
int main() {
auto handle = ::magic_open(MAGIC_NONE|MAGIC_COMPRESS);
::magic_load(handle, NULL);
for (fs::directory_entry const& x : make_iterator_range(fs::directory_iterator("."), {})) {
auto type = ::magic_file(handle, x.path().native().c_str());
std::cout << x.path() << "\t" << (type? type : "UNKOWN") << "\n";
}
::magic_close(handle);
}
인쇄물
[email protected]:~/custom/boost/status$ /tmp/test
"./Jamfile.v2" ASCII text
"./explicit-failures.xsd" XML document text
"./expected_results.xml" XML document text
"./explicit-failures-markup.xml" XML document text
플래그를 사용하여 분류 세부 정보를 제어 할 수 있습니다. MAGIC_MIME :
[email protected]:~/custom/boost/status$ /tmp/test
"./Jamfile.v2" text/plain; charset=us-ascii
"./explicit-failures.xsd" application/xml; charset=us-ascii
"./expected_results.xml" application/xml; charset=us-ascii
"./explicit-failures-markup.xml" application/xml; charset=utf-8
또는로드는 /etc/magic
:
[email protected]:~/custom/boost/status$ /tmp/test
"./Jamfile.v2" ASCII text
"./explicit-failures.xsd" ASCII text
"./expected_results.xml" ASCII text, with very long lines
"./explicit-failures-markup.xml" UTF-8 Unicode text
유망 해 보인다. 나는 그것을 시도해 보겠다. – Paddre
이것이 내가 정확히 찾고있는 것이라고 생각한다 :-) 고마워! 'magic_open()'에'MAGIC_NO_CHECK_ASCII' 플래그를 추가하고'data'와 같은지 확인하기 위해'type' 변수를 검사하는 방식으로 수정했습니다. – Paddre
필자는이 방법이 성능 측면에서 매우 비싸다고 덧붙여 야합니다. 'callgrind'를 실행하여 프로그램 비용의 60 %가'magic_file '에 의해 발생한다는 것을 알아 냈습니다. 매우 많은 파일을 비교해야하기 때문에 각 파일의 몇 줄을 파싱하고 더 빠르게 실행되는지 확인하여 "추측"방식을 시도 할 것입니다 (그러나 더 빠를 것이라고는 기대하지 않습니다 ;-)) – Paddre
완벽한 솔루션이 없습니다.
파일의 내용을 조사하여 교육용 추측을 할 수 있습니다. 텍스트 파일에는 인쇄 가능한 ASCII 텍스트가 포함되어있어 힌트를 제공하지만 예를 들어 텍스트가 상형 문자로 쓰여지는 경우 오해의 소지가있는 UTF8 시퀀스가 포함될 수 있습니다. 많은 파일 형식은 헤더에 마법의 단어를 포함하지만 마법의 단어를 찾을 수있는 일반적인 규칙이 없으므로 5 가지 형식의 마법의 단어가 들어있는 파일을 모두 올바른 위치에 쉽게 만들 수 있습니다.
cat =13 /*/ >/dev/null 2>&1; echo "Hello, world!"; exit
*
* This program works under cc, f77, and /bin/sh.
*
*/; main() {
write(
cat-~-cat
/*,'(
*/
,"Hello, world!"
,
cat); putchar(~-~-~-cat); } /*
,)')
end
*/
는 SH-스크립트, C 소스 코드 나 F77 소스 코드 that인가 :
는 때때로 정말 열심히 당신이 볼 수있는 파일의 유형을 결정입니까?
내가하려는 일을하기 위해 최선을 다하는 file
명령의 원본을 자세히 살펴볼 것을 제안합니다.
"명령 파일?" –
질문에 대한 답변에서 "그게 sh 스크립트, C 소스 코드 또는 f77 소스 코드입니까?"... 가장 확실하게 * 텍스트입니다. * –
Robert, 귀하는 귀하의 의견, 특히 명령 파일 모든 사람들이 명령 파일에 사용될 자신의 언어를 만들 수 있기 때문에 분류하기가 매우 어렵습니다. –
less
에서 도용 할 수 있습니다. less
은 파일을 이진 파일로 간주합니다. 첫 번째 256 바이트의 5 자 이상이 현재 로켈의 !isprint(c) && !iscntrl(c)
인 경우
도이 (less
항상 말한다 이유를 "이 이 이진 파일 될 수있다"입니다) 휴리스틱이지만, 일반적으로 작동하는 공통의 하나이며, 당신이 발생하는 경우는 임계 값을 조정할 수 있습니다 일부 파일 문제.
libmagic를 사용하면 파일의 종류를 찾을 수 있습니다. 남자 libmagic 자세한 정보를 제공합니다.
는 처음 100 바이트를 확인하거나 텍스트가 아닌 바이트 각 파일의 있도록 예를
` magic_t myt = magic_open(MAGIC_NONE);
sprintf(fullfilename, "%s/%s", dir_name,filename);
magic_load(myt,NULL);
printf("file type is %s", magic_file(myt,fullfilename));
magic_close(myt);
`
을 통해 이동합니다. 모든 이진 파일에는 일부 파일이 있습니다. 또는 처리하는 동안 수표의 일부로 만들고 바이너리 바이트가 발생하면 파일을 포기하십시오. –
@RobertHarvey 네, 많은 텍스트 파일도 마찬가지입니다. 예 : 유니 코드 BOM 또는 UTF-8 또는 ISO-8859의 임의의 비 ASCII 문자 또는 기타 인코딩 최소한 문턱 값, 예를 들어 "텍스트"(<127?) 바이트의 90 %가 필요합니다. – Thomas
글쎄, 다른 방법은 텍스트 파일이 아닌 모든 가능한 파일 형식을 확인하는 것입니다. 대부분의 바이너리 파일 및 문서 형식에는 일종의 마법 문자열 또는 기타 서명이 있습니다. 개인적으로 파일을 텍스트 또는 다른 것으로 식별하는 것이 더 쉽다고 생각합니다. –