Как идентифицировать содержимое файла как ASCII или двоичный - PullRequest
27 голосов
/ 10 ноября 2008

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

Ответы [ 10 ]

51 голосов
/ 10 ноября 2008

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

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

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

  • Если первые два байта являются шестнадцатеричными 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.

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

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

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

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

15 голосов
/ 10 ноября 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". Если вы имеете в виду код символа, то на самом деле это ваш путь. Но если вы имеете в виду только буквенно-цифровые значения, вам понадобится другой путь.

11 голосов
/ 10 ноября 2008

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

10 голосов
/ 10 ноября 2008

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

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

8 голосов
/ 10 ноября 2008

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

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

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

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

7 голосов
/ 10 ноября 2008

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

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

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

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

1 голос
/ 18 ноября 2008

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

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

1 голос
/ 10 ноября 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;
1 голос
/ 10 ноября 2008

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

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

0 голосов
/ 23 марта 2015

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

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

...