つまり、アーカイブ(jar/rar/etc)ファイルとテキスト(xml/txt、エンコーディングに依存しない)ファイルをどのように区別しますか?
保証された方法はありませんが、ここにいくつかの可能性があります:
1)ファイルのヘッダーを探します。残念ながら、ヘッダーはファイル固有であるため、RARファイルであることがわかるかもしれませんが、テキストかバイナリかというより一般的な答えは得られません。
2)文字タイプと非文字タイプの数を数えます。テキストファイルはほとんどがアルファベット文字ですが、バイナリファイル(特にrar、Zipなどの圧縮ファイル)は、バイトがより均等に表現される傾向があります。
3)定期的に繰り返される改行パターンを探します。
Java 7 Filesクラスの使用 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;
}
}
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は、ファイルまたはストリームのMIMEタイプを判別するためのJavaライブラリです。
私はこのコードを使用しましたが、英語とドイツ語のテキストでかなりうまくいきます:
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 text。
ファイルに他のASCII制御文字、上記の3つを除く0x00から0x1Fまでが含まれている場合、それはおそらくバイナリデータです。
UTF-8テキストは、高位ビットのバイトに対して非常に特定のパターンに従いますが、ISO-8859-1のような固定長エンコーディングはそうではありません。 UTF-16はしばしばヌルバイト(0x00)を含むことができますが、他のすべての位置にのみあります。
それ以外の場合は、より弱いヒューリスティックが必要になります。
ただお知らせするために、私はまったく異なるパスを選択しました。私の場合、ファイルは2種類しかありません。特定のファイルがバイナリファイルになる可能性は高いです。そう
[〜#〜] droid [〜#〜] ツールを試すことができます。