Как определить кодировку файла в OS X?


171

Я пытаюсь ввести некоторые символы UTF-8 в файл LaTeX в TextMate (который говорит, что его кодировка по умолчанию - UTF-8), но LaTeX, кажется, не понимает их.

Запуск cat my_file.texпоказывает символы правильно в терминале. Запуск ls -alпоказывает то, что я никогда раньше не видел: «@» в списке файлов:

-rw-r--r--@  1 me      users      2021 Feb 11 18:05 my_file.tex

(И да, я использую \usepackage[utf8]{inputenc}в LaTeX.)

Я обнаружил iconv, но это, кажется, не в состоянии сказать мне, что такое кодировка - она ​​преобразуется только после того, как я это выясню.


По моему опыту, команда file (1) всегда очень хорошо угадывала кодировку файла. Я не знаю, достаточно ли он умен, чтобы использовать расширенный атрибут файла com.apple.TextEncoding или нет.
Эдвард Фальк

Ответы:


33

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

Нет определенного способа определить кодировку файла. Прочтите этот ответ, он объясняет почему.

Есть инструмент командной строки, enca , который пытается угадать кодировку. Вы можете проверить это.


1
Я предполагал, что OSX хранит кодировку как метаданные. Я понял, что содержимое файла представляет собой просто набор битов и не имеет встроенной кодировки.
Джеймс А. Розен

1
@ JamesA.Rosen Приложения для OS X, такие как TextEdit, хранят кодировку файла как атрибут (с именем «com.apple.TextEncoding»). Вполне вероятно, что указанные атрибуты @включают атрибут кодировки файла. Вы можете использовать команду xattr -p com.apple.TextEncoding <filename>для просмотра атрибута кодировки, если он существует.
bames53

1
Можете ли вы объяснить, как использовать getxattr? Я не могу использовать это.
МэВ

1
Это вызов функции, который вы бы использовали, если хотите написать программу. В командной строке просто введите, ls -l@ <filename>чтобы увидеть, какие атрибуты установлены для файла. Чтобы увидеть фактический атрибут, напечатайтеxattr -p com.apple.TextEncoding <filename>
Эдвард Фальк,

Чтобы получить enca, brew install encaи вы должны указать язык, но ни один не работает, так:enca FILENAME -L __
Шейн

434

Использование -Iопции (это заглавная буква i) в команде file, похоже, показывает кодировку файла.

file -I {filename}

58
Мне нужно было использовать -I
Casebash

7
Похоже, что эта функция не может определить разницу между ASCII и UTF-8 (кажется, что они одинаковы для большинства символов США, но не для всех, возможно, для чего-то, что могло бы обнаружить бит юникода)
BadPirate

14
ASCII и UTF8 одинаковы, если в файле нет символа, кроме OxFF, или спецификации.
davidtbernal

3
file -I *кажется, отлично работает для меня (на OSX). Система жаловалась на кодировку одного из множества файлов, не указывая, какой именно. Все файлы были ascii, кроме одного, который был utf-8. Скорее всего виновник.
MCV

1
@ notJim Это неправильно. ASCII определяется только через 0x7F, поэтому все, что находится за этой точкой, явно не является ASCII. Unicode и Latin-1 имеют одинаковые кодовые точки в 0x80-0xFF, но нет общего кодирования Unicode, идентичного Latin-1 (потому что это по сути будет ограничено 8 битами, что слишком мало для Unicode).
tripleee

56

В Mac OS X команда file -I(заглавная i) даст вам правильный набор символов, при условии, что тестируемый файл содержит символы вне основного диапазона ASCII.

Например, если вы заходите в Терминал и используете vi для создания файла, например. vi test.txt затем вставьте несколько символов и вставьте символ с акцентом (попробуйте ALT-e, а затем e), затем сохраните файл.

Они печатают, file -I text.txtи вы должны получить такой результат:

test.txt: text/plain; charset=utf-8


3
Я могу подтвердить случай OS X, charset = us-ascii или charset = utf-8 в зависимости от содержимого файла
Бен

но он только смотрит на первые несколько килобайт файла. в моем случае команда vim на stackoverflow.com/a/33644535/161022 правильно определила файл как utf-8, тогда как fileкоманда us-ascii
объявляет

Действительно, похоже, что файлы читы по соображениям производительности. Я только что создал 3-мегабайтный ASCII-файл в Ubuntu и добавил несколько символов UTF-8 в конец, и он по-прежнему сообщает ASCII, а не UTF-8. Я попробовал опцию -k (продолжать), но затем он сообщает «данные», а не «UTF-8», так что все равно ничего хорошего.
Cloudranger

24
vim -c 'execute "silent !echo " . &fileencoding | q' {filename}

где-то в моей конфигурации bash

alias vic="vim -c 'execute \"silent !echo \" . &fileencoding | q'"

так что я просто набираю

vic {filename}

На моем ванильном OSX Yosemite он дает более точные результаты, чем "file -I":

$ file -I pdfs/udocument0.pdf
pdfs/udocument0.pdf: application/pdf; charset=binary
$ vic pdfs/udocument0.pdf
latin1
$
$ file -I pdfs/t0.pdf
pdfs/t0.pdf: application/pdf; charset=us-ascii
$ vic pdfs/t0.pdf
utf-8

1
Это единственный ответ, который дал мне то, что мне было нужно - «latin1», а не «us-ascii». Хотя мне пришлось убрать обратную косую черту.
Кэти Лавалле

Большое спасибо, я убрал обратные слеши.
Jmettraux

21

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

iconv -f original_charset -t new_charset originalfile > newfile

например

iconv -f utf-16le -t utf-8 file1.txt > file2.txt

13

Просто используйте:

file -I <filename>

Вот и все.


2
Я не могу быть обеспокоен, чтобы голосовать вниз, но этот ответ совершенно неверен. Маленький -i говорит, что не классифицируйте содержимое, если это обычный файл. -I эквивалентно --mime, который выводит строки типа mime. Инструменты osx ведут себя не так, как стандартные инструменты linux.
sillyMunky

Ну, для Windows 1252 закодированный файл file -Iдостается мне text/plain; charset=unknown-8bit. Хотя это работает лучше файл utf8: text/plain; charset=utf-8.
MiB

8

Использование fileкоманды с --mime-encodingпараметром (например file --mime-encoding some_file.txt) вместо параметра -I работает в OS X и имеет дополнительное преимущество, заключающееся в исключении типа mime, «text / plain», который вам, вероятно, не важен.


ls -l @ a покажет расширенные атрибуты . Глядя на страницу руководства для ls на Yosemite, я не вижу опции --mime-encoding.
rstackhouse

Вы говорили о fileкоманде. Не знал, что он существует. Новичек. Тем не мение. Извините за понижение. ТАК не позволит мне отменить это, если кто-то не редактирует этот ответ.
rstackhouse

4

Классический 8-битный LaTeX очень ограничен, в котором могут использоваться символы UTF8; это сильно зависит от кодировки шрифта, который вы используете, и от того, какие глифы у этого шрифта есть в наличии.

Поскольку вы не приводите конкретный пример, трудно точно определить, в чем проблема - пытаетесь ли вы использовать глиф, которого нет в вашем шрифте, или не используете правильную кодировку шрифта в первом место.

Вот минимальный пример, показывающий, как несколько символов UTF8 могут использоваться в документе LaTeX:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[utf8]{inputenc}
\begin{document}
‘Héllø—thêrè.’
\end{document}

Возможно, вам повезет больше с кодировкой [utf8x], но следует немного предупредить, что она больше не поддерживается и имеет некоторые отличительные особенности по сравнению с [utf8] (насколько я помню; прошло некоторое время с тех пор, как я на нее смотрел). Но если это поможет, это все, что важно для вас.


3

Знак @ означает, что файл имеет расширенные атрибуты . xattr fileпоказывает, какие атрибуты у него есть, также xattr -l fileпоказывает значения атрибутов (которые иногда могут быть большими - попробуйте, например, xattr /System/Library/Fonts/HelveLTMMувидеть шрифт старого стиля, который существует в ветке ресурсов).


2

Набрав file myfile.texв терминале, иногда можно узнать кодировку и тип файла, используя серию алгоритмов и магических чисел. Это довольно полезно, но не полагайтесь на него, предоставляя конкретную или надежную информацию.

Localizable.stringsФайл (находится в локализованных приложений Mac OS X) , как правило , сообщается, UTF-16 исходный файл C.


1

Synalyze It! позволяет сравнивать текст или байты во всех кодировках, которые предлагает библиотека ICU . Используя эту функцию, вы обычно сразу видите, какая кодовая страница имеет смысл для ваших данных.


1

Вы можете попробовать загрузить файл в окно Firefox, а затем перейти к View - Character Encoding. Рядом с типом кодировки файла должна стоять галочка.


0

Какой латекс вы используете? Когда я использовал teTeX, мне пришлось вручную загрузить пакет Unicode и добавить его в мои файлы .tex:

% UTF-8 stuff
\usepackage[notipa]{ucs}
\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc}

Теперь я перешел на XeTeX из пакета TeXlive 2008 ( здесь ), это еще проще:

% UTF-8 stuff
\usepackage{fontspec}
\usepackage{xunicode}

Что касается обнаружения кодировки файла, вы можете поиграть с ней file(1)(но она довольно ограничена), но, как сказал кто-то другой, это сложно.


0

Простой способ проверить кодировку может быть просто проверить файл в шестнадцатеричном редакторе или аналогичном. (или напишите программу для проверки) Посмотрите на двоичные данные в файле. Формат UTF-8 довольно легко распознать. Все символы ASCII представляют собой отдельные байты со значениями ниже 128 (0x80). Многобайтовые последовательности следуют шаблону, показанному в статье вики.

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


0

Я реализовал скрипт bash ниже, он работает для меня.

Сначала он пытается iconvиз кодировки, возвращаемой file --mime-encodingв utf-8.

Если это не удается, он проходит через все кодировки и показывает разницу между исходным и перекодированным файлом. Он пропускает кодировки, которые производят большой вывод различий («большой», как определено MAX_DIFF_LINESпеременной или вторым входным аргументом), так как это, скорее всего, неправильная кодировка.

Если в результате использования этого скрипта произойдут «плохие вещи», не вините меня. Там rm -fесть и монстры. Я пытался предотвратить негативные последствия, используя его для файлов со случайным суффиксом, но я не даю никаких обещаний.

Проверено на Дарвине 15.6.0.

#!/bin/bash

if [[ $# -lt 1 ]]
then
  echo "ERROR: need one input argument: file of which the enconding is to be detected."
  exit 3
fi

if [ ! -e "$1" ]
then
  echo "ERROR: cannot find file '$1'"
  exit 3
fi

if [[ $# -ge 2 ]]
then
  MAX_DIFF_LINES=$2
else
  MAX_DIFF_LINES=10
fi


#try the easy way
ENCOD=$(file --mime-encoding $1 | awk '{print $2}')
#check if this enconding is valid
iconv -f $ENCOD -t utf-8 $1 &> /dev/null
if [ $? -eq 0 ]
then
  echo $ENCOD
  exit 0
fi

#hard way, need the user to visually check the difference between the original and re-encoded files
for i in $(iconv -l | awk '{print $1}')
do
  SINK=$1.$i.$RANDOM
  iconv -f $i -t utf-8 $1 2> /dev/null > $SINK
  if [ $? -eq 0 ]
  then
    DIFF=$(diff $1 $SINK)
    if [ ! -z "$DIFF" ] && [ $(echo "$DIFF" | wc -l) -le $MAX_DIFF_LINES ]
    then
      echo "===== $i ====="
      echo "$DIFF"
      echo "Does that make sense [N/y]"
      read $ANSWER
      if [ "$ANSWER" == "y" ] || [ "$ANSWER" == "Y" ]
      then
        echo $i
        exit 0
      fi
    fi
  fi
  #clean up re-encoded file
  rm -f $SINK
done

echo "None of the encondings worked. You're stuck."
exit 3
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.