Как определить содержимое файла как ASCII или двоичное

Как вы идентифицируете содержимое файла как ASCII или двоичное, используя C ++?


person Community    schedule 10.11.2008    source источник
comment
Другой вопрос лучше, поэтому предложите закрыть его. Дубликаты stackoverflow.com/questions/567757/   -  person Mechanical snail    schedule 06.08.2012


Ответы (10)


Если файл содержит только десятичные байты 913, 32126, вероятно, это чистый текстовый файл ASCII. В противном случае это не так. Однако это может быть текст в другой кодировке.

Если в добавлении к вышеуказанным байтам файл содержит только десятичные байты 128255, вероятно, это текстовый файл в 8-битной кодировке или кодировке на основе ASCII переменной длины. например ISO-8859-1, UTF-8 или ASCII + Big5. Если нет, для некоторых целей вы можете остановиться на этом и считать файл двоичным. Однако это может быть текст в 16- или 32-битной кодировке.

Если файл не соответствует указанным выше ограничениям, проверьте первые 24 байта файла на предмет byte- отметка заказа:

  • Если первые два байта являются шестнадцатеричными FE FF, файл имеет формат ориентировочно в кодировке UTF-16 BE.
  • Если первые два байта имеют шестнадцатеричный FF FE, а следующие два байта не шестнадцатеричный 00 00, файл имеет формат ориентировочно UTF-16 LE.
  • Если первые четыре байта являются шестнадцатеричными 00 00 FE FF, файл имеет формат ориентировочно UTF-32 BE.
  • Если первые четыре байта являются шестнадцатеричными FF FE 00 00, файл имеет формат ориентировочно UTF-32 LE.

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

Если вы не определили предварительную кодировку, файл все еще может быть текстовым файлом в одной из этих кодировок, поскольку отметка порядка байтов не является обязательной, поэтому проверьте все кодировки в следующем списке:

  • Если файл содержит только двухбайтовых слов с прямым порядком байтов с десятичными значениями 913, 32126 и 128 или выше, вероятно, это UTF-16 BE.
  • Если файл содержит только двухбайтовых слов с прямым порядком байтов с десятичными значениями 913, 32126 и 128 или выше, вероятно, это файл UTF-16 LE.
  • Если файл содержит только слова с прямым порядком байтов с прямым порядком байтов с десятичными значениями 913, 32126 и 128 или выше, вероятно, это файл UTF-32 BE.
  • Если файл содержит только четырехбайтовых слов с прямым порядком байтов с десятичными значениями 913, 32126 и 128 или выше, вероятно, это файл UTF-32 LE.

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

person Daniel Cassidy    schedule 10.11.2008
comment
Это работает, только если текст в формате ASCII. Если UTF16 или UTF32, то он может содержать байты со значениями 0-8, 14-31 и 127. Таким образом, ваш ответ сбивает с толку. - person David Arno; 10.11.2008
comment
@David Arno, это правда, но вопрос был собственно об ASCII или нет. - person quinmars; 10.11.2008
comment
@quinmars, я обращаю ваше внимание на первую строку этого ответа. Я предполагаю, что вы действительно хотите определить, является ли файл текстовым (в любой кодировке), а не только ASCII .. Учитывая это, вторая строка явно неверна. Таким образом, ответ сбивает с толку и вводит в заблуждение. - person David Arno; 10.11.2008
comment
@ Дэвид Арно: Я согласен, поэтому я отредактировал свой ответ, чтобы отразить ваши комментарии. Спасибо :). - person Daniel Cassidy; 10.11.2008
comment
Извините, Даниэль, но система не позволяет мне отменить мой голос против, что смешно, поскольку вы отредактировали его, чтобы сделать его действительно хорошим ответом :( - person David Arno; 10.11.2008

Вы перебираете его, используя обычный цикл с stream.get (), и проверяете, равны ли прочитанные вами байтовые значения <= 127. Один из многих способов сделать это:

int c;
std::ifstream a("file.txt");
while((c = a.get()) != EOF && c <= 127) 
    ;
if(c == EOF) {
    /* file is all ASCII */
}

Однако, как кто-то упомянул, в конце концов, все файлы являются двоичными. Кроме того, непонятно, что вы подразумеваете под «ascii». Если вы имеете в виду код символа, то это действительно ваш путь. Но если вы имеете в виду только буквенно-цифровые значения, вам понадобится другой способ.

person Johannes Schaub - litb    schedule 10.11.2008
comment
Не думаю, что автор имел в виду именно это. Но фактически это правильный ответ. :-) - person Tomalak; 10.11.2008
comment
Это правильный ответ на заданный вопрос. Однако Томалак, ты прав в том, что сан, вероятно, неправильно сформулировал вопрос. - person David Arno; 10.11.2008
comment
Я выражение ASCII или двоичный намек на то, что он действительно имеет в виду текст, а не двоичный. - person Tomalak; 10.11.2008
comment
Кстати: буквенно-цифровые символы - это только часть текста. - person Tomalak; 10.11.2008
comment
да. может, он этого хотел. но, возможно, он также хочет включить '[' ... никто не знает :) - person Johannes Schaub - litb; 10.11.2008
comment
Этот код помечает как ASCII некоторые файлы, которых нет. Вы хотите проверить 'c' следующим образом: c ›= '' && c‹ = 127 || c == '\ n' || c == '\ r' || c == '\ t' Отрегулируйте в соответствии с вашим представлением об ASCII и вашей платформе. Некоторые возможные дополнения будут '\ f' и '\ v'. - person ; 10.11.2008
comment
man ascii показывает мне 128 символов ascii, включая значения ниже '' (0x20) - person Johannes Schaub - litb; 10.11.2008
comment
@Arkadiy, ASCII охватывает 0–127, что включает все управляющие символы. ASCII - это НЕ просто печатные символы. - person David Arno; 10.11.2008
comment
А как насчет французских персонажей? э - ›130 - person Cédric Guillemette; 12.02.2009
comment
@Cedrik ну, это не стандартный ascii, ascii - это американский стандартный код для обмена информацией, в конце концов :(. Если вы также включите значения ›128 в свой тест, он сделает каждый файл текстовым (поскольку каждый файл состоит из байтов ... от 0 до 255). - person Ben; 14.04.2009

Мой текстовый редактор определяет наличие нулевых байтов. На практике это работает очень хорошо: двоичный файл без нулевых байтов встречается крайне редко.

person bart    schedule 10.11.2008
comment
Это то, что делает и gnu diff. За исключением того, что они смотрят только на заранее определенную длину файла. (Не хочу просматривать файл размером 4 ГБ для нулевых байтов ...) - person Bill Lynch; 14.04.2009
comment
То же самое и с grep -I. - person kervin; 03.07.2009

Содержимое каждого файла является двоичным. Так что, не зная ничего другого, нельзя быть уверенным.

ASCII - это вопрос интерпретации. Если вы откроете двоичный файл в текстовом редакторе, вы поймете, что я имею в виду.

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

Если вы не определите свой вопрос более подробно, однозначного ответа быть не может.

person Tomalak    schedule 10.11.2008

Посмотрите, как работает команда file; у него есть три стратегии для определения типа файла:

В зависимости от вашей платформы и возможных файлов, которые вас интересуют, вы можете посмотреть на ее реализацию или даже вызвать ее.

person philant    schedule 10.11.2008

Если вопрос действительно заключается в том, как определить только ASCII, то ответ litb будет правильным. Однако если сан узнал, как определить, содержит ли файл текст или нет, проблема становится намного сложнее. ASCII - это всего лишь один из способов представления текста, который становится все более непопулярным. Системы Unicode - UTF16, UTF32 и UTF8 стали популярными. Теоретически их можно легко проверить, проверив, являются ли первые два байта меткой порядка байтов unicocde (BOM) 0xFEFF (или 0xFFFE, если порядок байтов обратный). Однако, поскольку эти два байта портят многие форматы файлов для систем Linux, их наличие не может быть гарантировано. Кроме того, двоичный файл может начинаться с 0xFEFF.

Поиск 0x00 (или других управляющих символов) тоже не поможет, если файл в формате Unicode. Если файл, скажем, UFT16, и файл содержит текст на английском языке, то каждый второй символ будет 0x00.

Если вы знаете язык, на котором будет написан текстовый файл, то можно будет проанализировать байты и статистически определить, содержит ли он текст или нет. Например, наиболее распространенной буквой на английском языке является E, за которой следует T. Так что, если файл содержит намного больше E и T, чем Z и X, скорее всего, это текст. Конечно, чтобы убедиться, необходимо протестировать это как ASCII и различные юникоды.

Если файл написан не на английском языке - или вы хотите поддерживать несколько языков - тогда остаются только два варианта - посмотреть на расширение файла в Windows и проверить первые четыре байта в базе данных кодов "волшебных файлов", чтобы определить тип файла и, таким образом, содержит ли он текст или нет.

person David Arno    schedule 10.11.2008

Что ж, это зависит от вашего определения ASCII. Вы можете проверить значения с помощью кода ASCII ‹128 или определенной кодировки (например, 'a' - 'z', 'A' - 'Z', '0' - '9' ...) и обработать файл как двоичный, если он содержит другие символы.

Вы также можете проверить наличие обычных разрывов строк (0x10 или 0x13,0x10) для обнаружения текстовых файлов.

person schnaader    schedule 10.11.2008

Для проверки вы должны открыть файл как двоичный. Вы не можете открыть файл как текст. ASCII - это фактически подмножество двоичного кода. После этого необходимо проверить значения байтов. ASCII имеет байтовые значения 0–127, но символы 0–31 являются управляющими. TAB, CR и LF - единственные общие управляющие символы. Вы не можете (переносно) использовать "A" и "Z"; нет никакой гарантии, что они находятся в кодировке ASCII (!). Если они вам нужны, вам нужно будет определить.

const unsigned char ASCII_A = 0x41; // NOT 'A'
const unsigned char ASCII_Z = ASCII_A + 25;
person MSalters    schedule 10.11.2008

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

Вот ссылка на The Old New Thing Article о том, как блокнот определяет тип файла ascii. Это не идеально, но интересно посмотреть, как Microsoft справится с этим.

person Shane Powell    schedule 18.11.2008

лингвист Github использует библиотека Чарлока Холмса для обнаружения двоичных файлов, которая, в свою очередь, использует ICU определение кодировки.

Библиотека ICU доступна для многих языков программирования, включая C и Java.

person cweiske    schedule 23.03.2015