2015-01-05 3 views
1

나는 boost :: filesystem을 사용하여 디렉터리의 파일을 검색하고 처리합니다. 그러나 boost :: filesystem :: is_regular_file()을 사용하여 확인한 모든 파일을 처리하는 대신 텍스트 파일 만 처리하거나 적어도 이진 파일을 무시합니다.C++ : 확장명없이 파일 형식을 확인하는 방법

파일 이 없어도 달성 할 수있는 방법이 있습니까?

저는 플랫폼에 독립적 인 솔루션을 매우 높이 평가할 것입니다.

+4

을 통해 이동합니다. 모든 이진 파일에는 일부 파일이 있습니다. 또는 처리하는 동안 수표의 일부로 만들고 바이너리 바이트가 발생하면 파일을 포기하십시오. –

+0

@RobertHarvey 네, 많은 텍스트 파일도 마찬가지입니다. 예 : 유니 코드 BOM 또는 UTF-8 또는 ISO-8859의 임의의 비 ASCII 문자 또는 기타 인코딩 최소한 문턱 값, 예를 들어 "텍스트"(<127?) 바이트의 90 %가 필요합니다. – Thomas

+0

글쎄, 다른 방법은 텍스트 파일이 아닌 모든 가능한 파일 형식을 확인하는 것입니다. 대부분의 바이너리 파일 및 문서 형식에는 일종의 마법 문자열 또는 기타 서명이 있습니다. 개인적으로 파일을 텍스트 또는 다른 것으로 식별하는 것이 더 쉽다고 생각합니다. –

답변

4

libmagic.

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 
+0

유망 해 보인다. 나는 그것을 시도해 보겠다. – Paddre

+1

이것이 내가 정확히 찾고있는 것이라고 생각한다 :-) 고마워! 'magic_open()'에'MAGIC_NO_CHECK_ASCII' 플래그를 추가하고'data'와 같은지 확인하기 위해'type' 변수를 검사하는 방식으로 수정했습니다. – Paddre

+0

필자는이 방법이 성능 측면에서 매우 비싸다고 덧붙여 야합니다. 'callgrind'를 실행하여 프로그램 비용의 60 %가'magic_file '에 의해 발생한다는 것을 알아 냈습니다. 매우 많은 파일을 비교해야하기 때문에 각 파일의 몇 줄을 파싱하고 더 빠르게 실행되는지 확인하여 "추측"방식을 시도 할 것입니다 (그러나 더 빠를 것이라고는 기대하지 않습니다 ;-)) – Paddre

2

완벽한 솔루션이 없습니다.

파일의 내용을 조사하여 교육용 추측을 할 수 있습니다. 텍스트 파일에는 인쇄 가능한 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 명령의 원본을 자세히 살펴볼 것을 제안합니다.

+0

"명령 파일?" –

+0

질문에 대한 답변에서 "그게 sh 스크립트, C 소스 코드 또는 f77 소스 코드입니까?"... 가장 확실하게 * 텍스트입니다. * –

+0

Robert, 귀하는 귀하의 의견, 특히 명령 파일 모든 사람들이 명령 파일에 사용될 자신의 언어를 만들 수 있기 때문에 분류하기가 매우 어렵습니다. –

1

less에서 도용 할 수 있습니다. less은 파일을 이진 파일로 간주합니다. 첫 번째 256 바이트의 5 자 이상이 현재 로켈의 !isprint(c) && !iscntrl(c) 인 경우

도이 (less 항상 말한다 이유를 "이 이진 파일 될 수있다"입니다) 휴리스틱이지만, 일반적으로 작동하는 공통의 하나이며, 당신이 발생하는 경우는 임계 값을 조정할 수 있습니다 일부 파일 문제.

0

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); 
` 
관련 문제