4

У меня есть пара исходных файлов C++ (один .cpp и один .h), которые сообщаются как данные типа командой file в Linux. Когда я запускаю команду file -bi этих файлов, я получаю такой вывод (одинаковый вывод для каждого файла):

application/octet-stream; charset=binary

Каждый файл явно текстовый (я могу просмотреть их в vi). Что заставляет file неверно указывать тип этих файлов? Может ли это быть что-то вроде Unicode? Оба эти файла были созданы в Windows-Land (с использованием Visual Studio 2005), но они компилируются в Linux (это кроссплатформенное приложение).

Любые идеи были бы хорошы.

Обновление: я не вижу нулевых символов ни в одном файле. Я нашел несколько расширенных символов в файле .cpp (в блоке комментариев), удалил их, но file прежнему сообщает ту же кодировку. Я пытался форсировать кодировку в SlickEdit, но, похоже, это не дало эффекта. Когда я открываю файл в vim , я вижу [converted] строку, как только я открываю файл. Возможно, я смогу получить vim для принудительного кодирования?

6 ответов6

4

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

Уведомление Vim «[преобразованный]» указывает на то, что в файле есть что-то, что vim не ожидает увидеть в кодировке текста, предложенной вашими настройками локали (LANG и т.д.).

Другие уже предложили

  • cat -v
  • xxd

Вы можете попробовать поискать символы, не входящие в ASCII.

  • grep -P '[\x7f-\xff]' filename

Другая возможность - нестандартные окончания строки для платформы (например, CRLF или CR), но я ожидаю, что file справится с этим и сообщит "текстовый файл DOS" или аналогичный.

3

Если вы запустите file -D filename , file отобразит информацию об отладке, включая тесты, которые он выполняет. Ближе к концу, он покажет, какой тест прошел успешно при определении типа файла.

Для обычного текстового файла это выглядит так:

[31> 0 regex,=^package[ \t]+[0-9A-Za-z_:]+ *;,""]
1 == 0 = 0
ascmagic 1
filename.txt: ISO-8859 text, with CRLF line terminators

Это скажет вам, что он нашел, чтобы определить, что это тот тип пантомимы.

3

Я нашел проблему, используя бинарный поиск, чтобы найти проблемные строки.

head -n {1/2 line count} file.cpp > a.txt
tail -n {1/2 line count} file.cpp > b.txt

Запуск file против каждой половины и повторение процесса помогли мне найти оскорбительную строку. Я нашел в нем встроенный символ Control+P (^P). Удаление это решило проблему. Я напишу сценарий Perl для поиска этих символов (и других расширенных) в будущем.

Большое спасибо всем, кто дал ответ на все советы!

0

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

Вы пытались сбросить их через что-то вроде "head -2 | xxd" и посмотреть, есть ли спецификация?

* BOM = Byte Order Mark - иногда присутствует в текстовых файлах Unicode. http://en.wikipedia.org/wiki/Byte_order_mark

0

Вероятно, это не-ASCII символ из Unicode или некоторого другого набора символов. Поскольку вы используете vi , которая в большинстве дистрибутивов Linux является версией vim , вы можете искать этот символ, набрав

/[<Ctrl-V>x80-<Ctrl-V>xff]

и нажмите Enter, где <Ctrl-V> означает ввод v при нажатии клавиши Ctrl . Точно так же вы можете искать нулевые значения (как предложил Mehrdad) с помощью этого:

/<Ctrl-V>x00
0

В какой кодировке / кодировке /(кодовой странице) находятся файлы?
Возможно, файлы имеют случайные символы. как правило, из-за плохой перекодировки между разными платформами. Недопустимые данные в ваших файлах могут приводить к тому, что file сообщает, как вы описали. Вы можете проверить правильность файла для определенной кодировки кодировки, протестировав его с помощью recode (или iconv).

Перейдите по ссылке, чтобы получить список кодировок общих символов.

Этот сценарий перечисляет кодировки наборов символов (из $my_csets), которые недопустимы для ваших файлов. Вы можете перечислить все кодировки с помощью: recode -l

file="$1"    
my_csets="UTF-16 UTF-8 windows-1250 ASCII"

# Use the next lines to test all charsets
# =======================================
# all_csets=$(recode -l |sed -ne "/^[^:/]/p" | awk '{print $1}')
# my_csets=$all_csets

for cset in $my_csets ;do 
  <"$1" recode $cset.. &>/dev/null || echo  "$cset  ERROR: $?"
done 

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .