Как проверить, является ли файл двоичным? - PullRequest
6 голосов
/ 22 июня 2010

Я написал следующий метод, чтобы увидеть, содержит ли конкретный файл только текстовые символы ASCII или контрольные символы в дополнение к этому. Не могли бы вы взглянуть на этот код, предложить улучшения и указать упущения?

Логика следующая: «Если первые 500 байтов файла содержат 5 или более управляющих символов - сообщить об этом как двоичный файл»

спасибо.

public boolean isAsciiText(String fileName) throws IOException {

    InputStream in = new FileInputStream(fileName);
    byte[] bytes = new byte[500];

    in.read(bytes, 0, bytes.length);
    int x = 0;
    short bin = 0;

    for (byte thisByte : bytes) {
        char it = (char) thisByte;
        if (!Character.isWhitespace(it) && Character.isISOControl(it)) {

            bin++;
        }
        if (bin >= 5) {
            return false;
        }
        x++;
    }
    in.close();
    return true;
}

Ответы [ 6 ]

3 голосов
/ 22 июня 2010
  1. Неудачно, если размер файла меньше 500 байт

  2. Строка char it = (char) thisByte; концептуально сомнительна, она смешивает понятия байтов и символов, т. Е.неявно предполагает, что кодировка однобайтовая = один символ (они исключают кодировки Unicode).В частности, происходит сбой, если файл имеет кодировку UTF-16.

  3. При возврате внутри цикла (немного плохая практика IMO) забывает закрыть файл.

3 голосов
/ 22 июня 2010

Поскольку вы называете этот класс "isASCIIText", вы точно знаете, что ищете.Другими словами, это не «isTextInCurrentLocaleEncoding».Таким образом, вы можете быть более точным с:

if (thisByte < 32 || thisByte > 127) bin++;

edit, долгое время спустя - в комментарии указано, что эта простая проверка будет запущена текстовым файлом, который запустилсяс большим количеством новых строк.Вероятно, было бы лучше использовать таблицу байтов "ok" и включать печатные символы (включая возврат каретки, перевод строки и табуляцию, а также, возможно, подачу формы, хотя я не думаю, что многие современные документы используют их), а затем проверитьстол.

3 голосов
/ 22 июня 2010

x, похоже, ничего не делает.

Что если размер файла меньше 500 байт?

В некоторых двоичных файлах есть ситуация, когда вы можете иметь заголовок для первых N байтов файла, который содержит некоторые данные, которые полезны для приложения, но для библиотеки, для которой предназначен двоичный файл, плевать. Вы можете легко получить более 500 байтов ASCII в такой преамбуле, за которой следуют двоичные данные в следующем гигабайте.

Должен обрабатывать исключение, если файл нельзя открыть или прочитать и т. Д.

1 голос
/ 22 июня 2010

Первое, что я заметил - не имеет отношения к вашему актуальному вопросу, но вы должны закрыть входной поток в блоке finally, чтобы убедиться, что он всегда выполняется.Обычно это просто обрабатывает исключения, но в вашем случае вы даже не закроете потоки файлов при возврате false.

Помимо этого, почему сравнение с управляющими символами ISO?Это не «двоичный» файл, это «файл, который содержит 5 или более управляющих символов».На мой взгляд, лучший способ подойти к ситуации - инвертировать проверку - вместо этого напишите функцию isAsciiText, которая утверждает, что все символы в файле (или в первых 500 байтах, если вы этого хотите) находятся в наборебайтов, которые известны исправно .

Теоретически, проверка только первых нескольких сотен байтов файла может привести к проблемам, если это будет своего рода составной файл (например, текст со встроенными изображениями).), но на практике я подозреваю, что каждый такой файл будет иметь двоичные данные заголовка в начале, так что вы, вероятно, в порядке.

0 голосов
/ 22 июня 2010

Это не будет работать с установочными пакетами jdk для linux или solaris. у них есть запуск сценария оболочки, а затем большой двоичный объект данных.

Почему бы не проверить MIME-тип, используя некоторую библиотеку, например, jMimeMagic (http://http://sourceforge.net/projects/jmimemagic/), и на основе MIME-типа выбрать способ обработки файла.

0 голосов
/ 22 июня 2010
  1. Вы игнорируете, что возвращает read (), что если файлы короче, чем 500 байт?
  2. Когда вы возвращаете false, файл не закрывается.
  3. Когдапреобразовывая байт в символ, вы предполагаете, что ваш файл является 7-битным ASCII.
...