Як визначити кодування файлів в OS X?


170

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

Запуск cat my_file.texпоказує символів належним чином у Terminal. Запуск 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 ОС X такі програми, як TextEdit, зберігають кодування файлів як атрибут (з назвою "com.apple.TextEncoding"). Цілком ймовірно, що атрибути, позначені цим, @включають атрибут кодування файлу. За допомогою команди xattr -p com.apple.TextEncoding <filename>можна переглянути атрибут кодування, якщо він існує.
bames53

1
Ви можете пояснити, як користуватися getxattr? Я не в змозі ним користуватися.
MeV

1
Це виклик функції, який ви використовуєте, якщо хочете написати програму. У командному рядку просто введіть, ls -l@ <filename>щоб побачити, які атрибути встановлені для файлу. Щоб побачити фактичний атрибут, введітьxattr -p com.apple.TextEncoding <filename>
Edward Falk

Для encaцього brew install encaпотрібно вказати мову, але жодна не працює, тому:enca FILENAME -L __
Шейн

433

Використання параметра -I(це велика літера) в команді файлів, схоже, показує кодування файлу.

file -I {filename}

58
Мені потрібно було скористатись -I
Casebash

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

14
ASCII і UTF8 є одними і тими ж, якщо у файлі немає символу, що перебуває за межами OxFF, або BOM.
davidtbernal

3
file -I *здається, працює для мене ідеально (на OSX). Система скаржилася на кодування одного з багатьох файлів, не вказуючи, який. Всі файли були ascii, крім одного, який був utf-8. Швидше за все винуватець.
mcv

1
@notJim Це неправильно. ASCII тільки визначається через 0x7F так нічого , крім цієї точки явно не ASCII. У Unicode та Latin-1 однакові кодові точки в 0x80-0xFF, але немає загального кодування Unicode, ідентичного Latin-1 (тому що це по суті було б обмежене на 8 біт, що для Unicode - це занадто мало).
трійка

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
Я можу підтвердити випадок ОС X, charset = us-ascii або charset = utf-8 залежно від вмісту файлу
Бен

але, здається, лише перегляньте перші кілька КБ файлу. у моєму випадку команда vim на stackoverflow.com/a/33644535/161022 правильно ідентифікувала файл як utf-8, тоді як fileкоманда стверджує йогоus-ascii
lmsurprenant

Дійсно, схоже, що файли обманюють з міркувань продуктивності. Я щойно створив файл 3MB 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 він дає більш точні результати, ніж "файл -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". Хоча, мені довелося зняти зворотні риси.
katy lavallee

Велике спасибі, я зняв косоокість.
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 еквівалентно --ime, що виводить рядки типу mime. Інструменти ОСХ поводяться по-різному від стандартних інструментів Linux.
sillyMunky

Ну, і для file -Iмене кодований файл Windows 1252 отримує text/plain; charset=unknown-8bit. Хоча це працює краще файл utf8: text/plain; charset=utf-8.
МіБ

8

Використання fileкоманди з --mime-encodingопцією (наприклад file --mime-encoding some_file.txt) замість опції -I працює в ОС X X і має додаткову перевагу від опущення типу mime "text / plain", яке, напевно, не хвилює вас.


ls -l @ a покаже розширені атрибути . Переглядаючи сторінку чоловіка для ls на Yosemite, я не бачу опції --mime-кодування.
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

Синалізуйте це! дозволяє порівнювати текст або байти у всіх кодуваннях, які пропонує бібліотека ICU . Використовуючи цю функцію, ви зазвичай відразу бачите, кодова сторінка має сенс для ваших даних.


1

Ви можете спробувати завантажити файл у вікно Firefox, а потім перейти до Перегляд - Кодування символів. Поруч із типом кодування файлу має бути галочка.


0

Який LaTeX ви використовуєте? Коли я використовував 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) Багатобайтові послідовності слідують шаблону, показаному у статті wiki

Якщо ви можете знайти більш простий спосіб отримати програму для перевірки кодування для вас, це, очевидно, ярлик, але якщо все інше не вдасться, це зробить трюк.


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.