Определение двоичного / текстового типа файла в Java?

StackOverflow https://stackoverflow.com/questions/620993

  •  05-07-2019
  •  | 
  •  

Вопрос

А именно, как бы вы отличили архивный файл (jar / rar / etc.) от текстового (xml / txt, независимого от кодировки)?

Это было полезно?

Решение

Там нет гарантированного пути, но здесь есть несколько возможностей:

1) Найдите заголовок файла. К сожалению, заголовки относятся к конкретному файлу, поэтому, хотя вы сможете узнать, что это RAR-файл, вы не получите более общий ответ, будь то текстовый или двоичный файл.

2) Подсчитайте количество символьных и не символьных типов. Текстовые файлы будут в основном алфавитными символами, в то время как двоичные файлы, особенно сжатые, такие как rar, zip и т. Д., Будут иметь более равномерное представление байтов.

3) Ищите регулярно повторяющийся шаблон новых строк.

Другие советы

Запустите файл -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 для   определение типа файлов MIME или   потоков.

Использование Java 7 Files class 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.

Если файл содержит любой другой управляющий символ ASCII, от 0x00 до 0x1F, исключая три указанных выше, то это, вероятно, двоичные данные.

Текст UTF-8 следует очень специфическому шаблону для любых байтов с битами старшего разряда, а кодировки фиксированной длины, такие как ISO-8859-1, - нет. UTF-16 часто может содержать нулевой байт (0x00), но только в любой другой позиции.

Вам понадобится более слабая эвристика для всего остального.

Просто, чтобы вы знали, я выбрал совершенно другой путь. В моем случае существует только 2 типа файлов, высока вероятность того, что любой данный файл будет двоичным. Так

<Ол>
  • предположите, что файл является двоичным, попробуйте сделать то, что должно быть сделано (например, десериализовать)
  • поймать исключение
  • рассматривать файл как текстовый
  • если это не помогло, значит, что-то не так с самим файлом
  • Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top