Я записал следующий метод, чтобы видеть, содержит ли конкретный файл символы текста 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;
}
Поскольку вы называете этот класс «isASCIIText», вы точно знаете, что ищете. Другими словами, это не isTextInCurrentLocaleEncoding. Таким образом, вы можете быть более точными с помощью:
if (thisByte < 32 || thisByte > 127) bin++;
edit, долгое время спустя - в комментарии указано, что эта простая проверка может быть остановлена текстовым файлом, который начинается с большого количества символов новой строки. Вероятно, было бы лучше использовать таблицу байтов "ok" и включать печатаемые символы (включая возврат каретки, новую строку и табуляцию и, возможно, подачу формы, хотя я не думаю, что многие современные документы используют их), а затем проверьте стол.
x
, похоже, ничего не делает.
Что делать, если размер файла меньше 500 байт?
В некоторых двоичных файлах есть ситуация, когда у вас может быть заголовок для первых N байтов файла, который содержит некоторые данные, которые полезны для приложения, но что библиотека двоичный файл для не заботится. Вы можете легко иметь 500+ байтов ASCII в такой преамбуле, за которой следуют двоичные данные в следующем гигабайте.
Должен обрабатывать исключение, если файл не может быть открыт или прочитан и т. Д.
Сбой, если размер файла меньше 500 байт
Строка char it = (char) thisByte;
концептуально сомнительна, она смешивает концепции байтов и символов, т.е. неявно предполагает, что кодировка - однобайтный = один символ (они исключают кодировки Unicode). В частности, это не удается, если файл закодирован в UTF-16.
Возврат внутри цикла (немного плохая практика IMO) забывает закрыть файл.
Первое, что я заметил - не связано с вашим вопросом, но вам следует закрывать входной поток в блоке finally
, чтобы убедиться, что он всегда завершен. Обычно это просто обрабатывает исключения, но в вашем случае вы даже не закроете потоки файлов при возврате false
.
Кроме того, почему сравнение с управляющими символами ISO? Это не "двоичный" файл, это "файл, содержащий 5 или более управляющих символов". На мой взгляд, лучшим подходом к ситуации было бы инвертировать проверку - написать вместо нее функцию isAsciiText
, которая утверждает, что все символы в файле (или в первых 500 байтах, если хотите) находятся в наборе байт, которые известны как хорошие.
Теоретически, проверка только первых нескольких сотен байт файла может привести к проблемам, если это какой-то составной файл (например, текст со встроенными картинками), но на практике, я подозреваю, каждый такой файл будет иметь двоичные данные заголовка в начале, так что вы, вероятно, в порядке.
Это не будет работать с пакетами установки jdk для Linux или Solaris. у них есть запуск сценария оболочки, а затем большой двоичный объект данных.
Почему бы не проверить тип mime с помощью некоторой библиотеки, такой как jMimeMagic (http://http://sourceforge.net/projects/jmimemagic/) и десайда на основе mimetype, как обрабатывать файл.