Java에서 바이너리/텍스트 파일 유형을 결정합니까?
문제
즉, 아카이브(jar/rar/etc.) 파일과 텍스트(xml/txt, 인코딩 독립적) 파일을 어떻게 구분할 수 있습니까?
해결책
보장 된 방법은 없지만 몇 가지 가능성이 있습니다.
1) 파일에서 헤더를 찾으십시오. 불행히도, 헤더는 파일 별이므로 RAR 파일이라는 것을 알 수 있지만 텍스트인지 바이너리인지에 대한 일반적인 대답을 얻지 못할 수도 있습니다.
2) 문자 수와 비 특가자 유형을 계산하십시오. 텍스트 파일은 주로 알파벳순 문자이며 이진 파일, 특히 RAR, Zip 등과 같은 압축 파일은 바이트가 더 균등하게 표현되는 경향이 있습니다.
3) 정기적으로 반복되는 신형 패턴을 찾으십시오.
다른 팁
운영 file -bi {filename}
. 반환하는 것이 'Text/'로 시작하면 이진적이지 않으며 그렇지 않으면 그렇지 않습니다. ;-)
나는 이것을 만들었다. 조금 간단하지만 라틴어 기반 언어의 경우 비율 조정과 함께 잘 작동해야합니다.
/**
* Guess whether given file is binary. Just checks for anything under 0x09.
*/
public static boolean isBinaryFile(File f) throws FileNotFoundException, IOException {
FileInputStream in = new FileInputStream(f);
int size = in.available();
if(size > 1024) size = 1024;
byte[] data = new byte[size];
in.read(data);
in.close();
int ascii = 0;
int other = 0;
for(int i = 0; i < data.length; i++) {
byte b = data[i];
if( b < 0x09 ) return true;
if( b == 0x09 || b == 0x0A || b == 0x0C || b == 0x0D ) ascii++;
else if( b >= 0x20 && b <= 0x7E ) ascii++;
else other++;
}
if( other == 0 ) return false;
return 100 * other / (ascii + other) > 95;
}
살펴보십시오 jmimemagic 도서관.
Jmimemagic은 마임 유형의 파일 또는 스트림을 결정하기위한 Java 라이브러리입니다.
Java 7 파일 클래스 사용 http://docs.oracle.com/javase/7/docs/api/java/nio/file/files.html#probecontenttype(java.nio.file.path)
boolean isBinaryFile(File f) throws IOException {
String type = Files.probeContentType(f.toPath());
if (type == null) {
//type couldn't be determined, assume binary
return true;
} else if (type.startsWith("text")) {
return false;
} else {
//type isn't text
return true;
}
}
이 코드를 사용했으며 영어와 독일어 텍스트에 잘 작동합니다.
private boolean isTextFile(String filePath) throws Exception {
File f = new File(filePath);
if(!f.exists())
return false;
FileInputStream in = new FileInputStream(f);
int size = in.available();
if(size > 1000)
size = 1000;
byte[] data = new byte[size];
in.read(data);
in.close();
String s = new String(data, "ISO-8859-1");
String s2 = s.replaceAll(
"[a-zA-Z0-9ßöäü\\.\\*!\"§\\$\\%&/()=\\?@~'#:,;\\"+
"+><\\|\\[\\]\\{\\}\\^°²³\\\\ \\n\\r\\t_\\-`´âêîô"+
"ÂÊÔÎáéíóàèìòÁÉÍÓÀÈÌÒ©‰¢£¥€±¿»«¼½¾™ª]", "");
// will delete all text signs
double d = (double)(s.length() - s2.length()) / (double)(s.length());
// percentage of text signs in the text
return d > 0.95;
}
파일이 0x09(탭), 0x0A(줄 바꿈), 0x0C(폼 피드), 0x0D(캐리지 리턴) 또는 0x20~0x7E 바이트로 구성된 경우 이는 아마도 ASCII 텍스트일 것입니다.
파일에 위의 세 문자를 제외하고 0x00부터 0x1F까지의 다른 ASCII 제어 문자가 포함되어 있으면 아마도 이진 데이터일 것입니다.
UTF-8 텍스트는 상위 비트가 있는 모든 바이트에 대해 매우 구체적인 패턴을 따르지만 ISO-8859-1과 같은 고정 길이 인코딩은 그렇지 않습니다.UTF-16에는 널 바이트(0x00)가 포함될 수 있지만 다른 모든 위치에만 포함될 수 있습니다.
다른 것에 대해서는 더 약한 경험적 방법이 필요합니다.
알려주기 위해, 나는 상당히 다른 길을 선택했습니다. 제 경우에는 2 가지 유형의 파일 만 있습니다. 주어진 파일이 바이너리 파일 일 가능성이 높습니다. 그래서
- 그 파일이 이진이라고 가정하고,해야 할 일을 시도하십시오 (예 : deserialize).
- 예외를 잡습니다
- 파일을 텍스트로 취급하십시오
- 실패하면 파일 자체에 문제가 있습니다.
당신은 시도 할 수 있습니다 드로이드 도구.