2010-06-22 7 views
5

Я написал следующий метод, чтобы узнать, содержит ли конкретный файл только текстовые символы 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; 
} 

ответ

3

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

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

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

+0

Это трагедия, которая отмечена как правильный ответ, когда этот алгоритм классифицирует файл, содержащий этот «r \ n \ r \ nonly \ r \ ntext» как двоичный. – Ingo

+1

@Ingo true; было бы лучше проверить какое-то отношение управляющих символов к неконтролируемым, а также проверить специальные случаи, такие как обычные символы управления в тексте. Я был так молод, когда набрал этот ответ :) – Pointy

3

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

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

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

должен обрабатывать исключение, если файл не может быть открыт или читать, и т.д.

1

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

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

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

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

Это не будет работать с пакетами установки jdk для Linux или Solaris.у них есть запуск shell-скрипта, а затем бит данных blob.

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

3
  1. Не удается плохо, если размер файла меньше 500 байт

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

  3. Возврат внутри цикла (немного неправильная практика ИМО) забывает закрыть файл.

Смежные вопросы