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





Ну, это зависит от вашего определения ASCII. Вы можете проверить значения с помощью кода ASCII <128 или определенной вами кодировки (например, 'a' - 'z', 'A' - 'Z', '0' - '9' ...) и обработать файл как двоичный, если он содержит другие символы.
Вы также можете проверить регулярные разрывы строк (0x10 или 0x13,0x10) для обнаружения текстовых файлов.
Содержимое файла каждый является двоичным. Так что, не зная ничего другого, нельзя быть уверенным.
ASCII - это вопрос интерпретации. Если вы откроете двоичный файл в текстовом редакторе, вы поймете, что я имею в виду.
Большинство двоичных файлов содержат фиксированный заголовок (для каждого типа), который вы можете искать, или вы можете использовать расширение файла как подсказку. Вы можете искать метки порядка байтов, если ожидаете файлы в кодировке UTF, но они также не являются обязательными.
Если вы не определите свой вопрос более подробно, однозначного ответа быть не может.
Вы перебираете его, используя обычный цикл с 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 или двоичный» является намеком на то, что на самом деле он означает «текст, а не двоичный».
Кстати: «Буквенно-цифровой» - это только часть текста.
да. может, он этого хотел. но, возможно, он также хочет включить '[' ... никто не знает :)
Этот код пометит как ASCII некоторые файлы, которых нет. Вы хотите проверить 'c' следующим образом: c> = '' && c <= 127 || c == '\ n' || c == '\ r' || c == '\ t' Отрегулируйте в соответствии с вашим представлением об ASCII и вашей платформе. Некоторые возможные дополнения будут '\ f' и '\ v'.
"man ascii" показывает мне 128 символов ascii, включая значения ниже '' (0x20)
@Arkadiy, ASCII охватывает 0–127, что включает все управляющие символы. ASCII - это НЕ просто печатные символы.
А как насчет французских персонажей? é -> 130
@Cedrik ну, это не стандартный ascii, ascii - это американский стандартный код для обмена информацией, в конце концов :(. Если вы также включите значения> 128 в свой тест, он сделает каждый файл текстовым (поскольку каждый файл состоит из байтов ... от 0 до 255).
Если файл содержит Только десятичные байты 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.Если с помощью вышеуказанных проверок вы определили предварительную кодировку, проверьте только соответствующую кодировку ниже, чтобы убедиться, что файл не является двоичным файлом, который соответствует метке порядка байтов.
Если вы не определили предварительную кодировку, файл все равно может быть текстовым файлом в одной из этих кодировок, поскольку отметка порядка байтов не является обязательной, поэтому проверьте все кодировки в следующем списке:
Если после всех этих проверок вы все еще не определили кодировку, файл не является текстовым файлом в какой-либо известной мне кодировке на основе ASCII, поэтому для большинства целей вы, вероятно, можете считать его двоичным (он все еще может быть текстовым файлом в кодировке, отличной от ASCII, такой как EBCDIC, но я подозреваю, что это выходит далеко за рамки вашей озабоченности).
Это работает, только если текст в формате ASCII. Если UTF16 или UTF32, то он может содержать байты со значениями 0-8, 14-31 и 127. Таким образом, ваш ответ сбивает с толку.
@David Arno, это правда, но вопрос был собственно об ASCII или нет.
@quinmars, обращаю ваше внимание на первую строку этого ответа: «Я полагаю, вы действительно хотите определить, является ли файл текстовым (в любой кодировке), а не только ASCII». Учитывая это, вторая строка совершенно неверна. Таким образом, ответ сбивает с толку и вводит в заблуждение.
@ Дэвид Арно: Я согласен, поэтому я отредактировал свой ответ, чтобы отразить ваши комментарии. Спасибо :).
Извини, Даниэль, но система не позволяет мне отменить мой голос против, что нелепо, поскольку вы отредактировали его, чтобы он стал действительно хорошим ответом :(
Посмотрите, как работает команда файла; у него есть три стратегии для определения типа файла:
В зависимости от вашей платформы и возможных файлов, которые вас интересуют, вы можете посмотреть на ее реализацию или даже вызвать ее.
Мой текстовый редактор определяет наличие нулевых байтов. На практике это работает очень хорошо: двоичный файл без нулевых байтов встречается крайне редко.
Это то, что делает и gnu diff. За исключением того, что они смотрят только на заранее определенную длину файла. (Не хочу просматривать файл размером 4 ГБ для нулевых байтов ...)
То же самое и с grep -I.
Для проверки вы должны открыть файл как двоичный. Вы не можете открыть файл как текст. 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;
Если вопрос действительно в том, как определить только 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 и проверить первые четыре байта в базе данных кодов "волшебных файлов", чтобы определить тип файла и, таким образом, содержит ли он текст или нет.
На этот вопрос действительно нет правильного или неправильного ответа, просто сложные решения, которые не будут работать для всех возможных текстовых файлов.
Вот ссылка на Статья Old New Thing о том, как блокнот определяет тип файла ascii. Это не идеально, но интересно посмотреть, как Microsoft справится с этим.
Лингвист Github использует библиотека чарлока холмса для обнаружения двоичных файлов, который, в свою очередь, использует определение кодировкиICU.
Библиотека ICU доступна для многих языков программирования, включая C и Java.
Другой вопрос лучше, поэтому предложите закрыть его. Дубликаты stackoverflow.com/questions/567757/…