Как вы идентифицируете содержимое файла как ASCII или двоичное, используя C ++?
Как определить содержимое файла как ASCII или двоичное
Ответы (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, но я подозреваю, что это выходит далеко за рамки вашей озабоченности).
Вы перебираете его, используя обычный цикл с 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». Если вы имеете в виду код символа, то это действительно ваш путь. Но если вы имеете в виду только буквенно-цифровые значения, вам понадобится другой способ.
Мой текстовый редактор определяет наличие нулевых байтов. На практике это работает очень хорошо: двоичный файл без нулевых байтов встречается крайне редко.
Содержимое каждого файла является двоичным. Так что, не зная ничего другого, нельзя быть уверенным.
ASCII - это вопрос интерпретации. Если вы откроете двоичный файл в текстовом редакторе, вы поймете, что я имею в виду.
Большинство двоичных файлов содержат фиксированный заголовок (для каждого типа), который вы можете искать, или вы можете использовать расширение файла как подсказку. Вы можете искать метки порядка байтов, если ожидаете файлы в кодировке UTF, но они также не являются обязательными.
Если вы не определите свой вопрос более подробно, однозначного ответа быть не может.
Посмотрите, как работает команда file; у него есть три стратегии для определения типа файла:
- тесты файловой системы
- Тесты магического числа
- и языковые тесты
В зависимости от вашей платформы и возможных файлов, которые вас интересуют, вы можете посмотреть на ее реализацию или даже вызвать ее.
Если вопрос действительно заключается в том, как определить только 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 и проверить первые четыре байта в базе данных кодов "волшебных файлов", чтобы определить тип файла и, таким образом, содержит ли он текст или нет.
Что ж, это зависит от вашего определения ASCII. Вы можете проверить значения с помощью кода ASCII ‹128 или определенной кодировки (например, 'a' - 'z', 'A' - 'Z', '0' - '9' ...) и обработать файл как двоичный, если он содержит другие символы.
Вы также можете проверить наличие обычных разрывов строк (0x10 или 0x13,0x10) для обнаружения текстовых файлов.
Для проверки вы должны открыть файл как двоичный. Вы не можете открыть файл как текст. 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;
На этот вопрос действительно нет правильного или неправильного ответа, просто сложные решения, которые не будут работать для всех возможных текстовых файлов.
Вот ссылка на The Old New Thing Article о том, как блокнот определяет тип файла ascii. Это не идеально, но интересно посмотреть, как Microsoft справится с этим.
лингвист Github использует библиотека Чарлока Холмса для обнаружения двоичных файлов, которая, в свою очередь, использует ICU определение кодировки.
Библиотека ICU доступна для многих языков программирования, включая C и Java.