'바이너리'와 '텍스트'파일을 어떻게 구별합니까?
비공식적으로 우리 대부분은 '바이너리'파일 (객체 파일, 이미지, 영화, 실행 파일, 독점 문서 형식 등)과 '텍스트'파일 (소스 코드, XML 파일, HTML 파일, 이메일 등)이 있음을 이해합니다.
일반적으로 유용한 일을 할 수 있으려면 파일의 내용을 알아야하며 인코딩이 '이진'또는 '텍스트'인 경우 그 관점을 형성해야합니다. 그리고 물론 파일은 데이터 바이트를 저장하기 때문에 모두 '이진'이고 '텍스트'는 인코딩을 알지 못하면 아무 의미가 없습니다. 그럼에도 불구하고 '바이너리'와 '텍스트'파일에 대해 이야기하는 것은 여전히 유용하지만,이 부정확 한 정의를 가진 사람을 화나게하지 않으려면 계속해서 '무서운'인용문을 사용할 것입니다.
그러나 광범위한 파일에서 작동하는 다양한 도구가 있으며 실제적으로 파일이 '텍스트'인지 '이진'인지에 따라 다른 작업을 수행하고 싶습니다. 이에 대한 예는 콘솔에 데이터를 출력하는 도구입니다. 일반 '텍스트'는 괜찮아 보이고 유용합니다. '바이너리'데이터는 터미널을 엉망으로 만들고 일반적으로보기에는 유용하지 않습니다. GNU grep은 적어도 콘솔에 일치를 출력해야하는지 결정할 때이 구별을 사용합니다.
그래서 문제는 파일이 '텍스트'인지 '바이너리'인지 어떻게 알 수 있습니까? 그리고 제한하는 것은 파일 시스템과 같은 Linux에서 어떻게 말합니까? 파일의 '유형'을 나타내는 파일 시스템 메타 데이터를 알지 못하므로 파일의 내용을 검사하여 '텍스트'인지 '이진'인지 어떻게 알 수 있습니까? 그리고 간단하게 '텍스트'를 사용자 콘솔에서 인쇄 할 수있는 문자를 의미하도록 제한 할 수 있습니다. 특히 이것을 어떻게 구현 하시겠습니까? (나는 이것이이 사이트에 함축 된 것이라고 생각했지만, 일반적으로 이것을 수행하는 기존 코드를 지적하는 것이 도움이 될 것 같습니다. 지정 했어야했습니다), 나는 기존 프로그램을 사용하여 할 수있는 일을 정말로 추구하지 않습니다. 이.
우리 회사에서 만드는 스프레드 시트 소프트웨어는 텍스트 파일뿐만 아니라 다양한 바이너리 파일 형식을 읽습니다.
먼저 우리가 인식 하는 매직 넘버에 대해 처음 몇 바이트를 살펴 봅니다 . 우리가 읽은 바이너리 유형의 매직 넘버를 인식하지 못하는 경우 파일의 처음 2K 바이트까지 파일이 UTF-8 , UTF-16 또는 인코딩 된 텍스트 파일인지 확인합니다. 호스트 운영 체제 의 현재 코드 페이지 에서. 이러한 테스트 중 어느 것도 통과하지 않으면 처리 할 수있는 파일이 아니라고 가정하고 적절한 예외를 throw합니다.
file
명령을 사용할 수 있습니다 . man file
바이너리인지 텍스트인지 결정하기 위해 파일 ( ) 에 대한 여러 테스트를 수행 합니다. C에서해야하는 경우 소스 코드를 보거나 빌릴 수 있습니다.
file README
README: ASCII English text, with very long lines
file /bin/bash
/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
다음 을 사용하여 파일 의 MIME 유형 을 확인할 수 있습니다.
file --mime FILENAME
속기는 file -i
Linux에서, file -I
macOS에서는 (대문자 i)입니다 (댓글 참조).
로 시작하면 text/
텍스트이고, 그렇지 않으면 바이너리입니다. 유일한 예외는 XML 응용 프로그램입니다. +xml
파일 유형의 끝을 찾아서 일치시킬 수 있습니다 .
글쎄, 전체 파일을 검사하는 경우 모든 문자가 isprint(c)
. 유니 코드에서는 조금 더 복잡해집니다.
유니 코드 텍스트 파일을 구별하기 위해 MSDN은 수행 할 작업에 대한 몇 가지 훌륭한 조언을 제공합니다 .
요점은 먼저 처음 4 바이트까지 검사하는 것입니다.
EF BB BF UTF-8
FF FE UTF-16, little endian
FE FF UTF-16, big endian
FF FE 00 00 UTF-32, little endian
00 00 FE FF UTF-32, big-endian
그것은 당신에게 인코딩을 알려줄 것입니다. 그런 다음 iswprint(c)
텍스트 파일의 나머지 문자에 사용할 수 있습니다. UTF-8 및 UTF-16의 경우 단일 문자를 가변 바이트 수로 나타낼 수 있으므로 데이터를 수동으로 구문 분석해야합니다. 또한 당신이 정말 항문 인 iswprint
이라면 플랫폼에서 사용 가능한 로케일 변형을 사용하고 싶을 것입니다.
Perl은 괜찮은 휴리스틱을 가지고 있습니다. -B
이진을 테스트 하려면 연산자를 사용합니다 ( -T
텍스트를 테스트하려면 그 반대 ). 다음은 텍스트 파일을 나열하는 한 줄짜리 셸입니다.
$ find . -type f -print0 | perl -0nE 'say if -f and -s _ and -T _'
(앞에 달러가없는 밑줄은 정확합니다 (RTFM).)
오래된 주제이지만 누군가가 유용하다고 생각할 것입니다. 파일인지 스크립트에서 결정해야한다면 다음과 같이 간단하게 할 수 있습니다.
if file -i $1 | grep -q text;
then
.
.
fi
이것은 파일 유형을 가져오고 자동 grep을 사용하여 텍스트인지 결정할 수 있습니다.
차이를 알려주는 대부분의 프로그램 은 파일 의 처음 n 바이트 를 검사하고 해당 바이트가 모두 '텍스트'로 한정 되는지 여부를 확인하는 것과 같은 휴리스틱을 사용합니다 (즉, 모두 인쇄 가능한 ASCII 문자 범위에 속하는지 여부). . 좀 더 세밀하게 설명하기 위해 UNIX 계열 시스템에는 항상 'file'명령이 있습니다.
현재 dir / subdir에있는 텍스트 파일 이름을 나열하려면 :
$ grep -rIl ''
바이너리 :
$ grep -rIL ''
특정 파일을 확인하려면 명령을 약간 수정하십시오.
$ grep -qI '' FILE
그러면 종료 상태 '0'은 파일이 텍스트임을 의미합니다. '1'-바이너리. 확인할 수 있습니다 :
$ 에코 $?
libmagic
Unix file
명령 줄 의 라이브러리 버전을 사용할 수 있습니다 .
여러 언어에 대한 래퍼가 있습니다.
One simple check is if it has \0
characters. Text files don't have them.
As previously stated *nix operating systems have this ability within the file command. This command uses a configuration file that defines magic numbers contained within many popular file structures.
This file, called magic was historically stored in /etc, although this may be in /usr/share on some distributions. The magic file defines offsets of values known to exist within the file and can then examine these locations to determine the type of the file.
The structure and description of the magic file can be found by consulting the relevant manual page (man magic)
As for an implementation, well that can be found within file.c itself, however the relevant portion of the file command that determines whether it is readable text or not is the following
/* Make sure we are dealing with ascii text before looking for tokens */
for (i = 0; i < nbytes - 1; i++) {
if (!isascii(buf[i]) ||
(iscntrl(buf[i]) && !isspace(buf[i]) &&
buf[i] != '\b' && buf[i] != '\032' && buf[i] != '\033'
)
)
return 0; /* not all ASCII */
}
참고URL : https://stackoverflow.com/questions/567757/how-do-i-distinguish-between-binary-and-text-files
'Nice programing' 카테고리의 다른 글
grep "\\"XXFile을 사용하면 "Trailing Backslash"가 표시됩니다. (0) | 2020.12.04 |
---|---|
현재 시간에시, 분, 초 추가 (0) | 2020.12.04 |
OSX에서 GCC 업데이트 (0) | 2020.12.04 |
C # TextBox의 맨 아래로 스크롤 (0) | 2020.12.04 |
VC ++ 프로젝트에서 유니 코드를 끄려면 어떻게합니까? (0) | 2020.12.04 |