2008-11-10 3 views
26

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

+1

Другой вопрос лучше, поэтому предложите закрыть этот. Дубликаты http://stackoverflow.com/questions/567757/how-do-i-distinguish-between-binary-and-text-files – 2012-08-06 07:22:37

ответ

1

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

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

8

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

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

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

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

15

Проиллюстрируйте его с помощью обычного цикла с 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». Если вы имеете в виду код символа, то действительно так вы идете. Но если вы имеете в виду только буквенно-цифровые значения, вам нужно будет по-другому.

+1

Я не думаю, что это то, что автор намеревался. Но * фактически * это правильный ответ. :-) – Tomalak 2008-11-10 10:32:11

+0

Это правильный ответ на заданный вопрос. Однако Томалак, вы правы в этом сан, вероятно, не сформулировал вопрос правильно. – 2008-11-10 10:34:58

+1

Я выражение «ASCII или двоичный» - это намек на то, что он действительно означает «текст, а не двоичный». – Tomalak 2008-11-10 10:46:35

51

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

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

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

  • Если первые два байта шестнадцатеричную 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, но я подозреваю, что это выходит за рамки вашей проблемы).

10

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

  • тесты файловой системы
  • magic number тесты
  • и языковые тесты

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

11

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

1

Чтобы проверить, вы должны открыть файл как двоичный файл. Вы не можете открыть файл в виде текста. 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; 
7

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

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

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

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

1

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

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

0

Github's linuguist использует charlock holmes для обнаружения двоичных файлов, которые в свою очередь используют 's charset detection.

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

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