Wie bestimme ich die Dateicodierung in OS X?

170

Ich versuche, einige UTF-8-Zeichen in eine LaTeX-Datei in TextMate einzugeben (die besagt, dass die Standardcodierung UTF-8 ist), aber LaTeX scheint sie nicht zu verstehen.

Beim Ausführen cat my_file.texwerden die Zeichen im Terminal ordnungsgemäß angezeigt. Laufen ls -alzeigt etwas, was ich noch nie gesehen habe: ein "@" in der Dateiliste:

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

(Und ja, ich verwende \usepackage[utf8]{inputenc}im LaTeX.)

Ich habe es gefunden iconv, aber das scheint mir nicht sagen zu können, was die Codierung ist - es wird erst konvertiert, wenn ich es herausgefunden habe.

James A. Rosen
quelle
Nach meiner Erfahrung war der Befehl file (1) immer ziemlich gut darin, die Codierung einer Datei zu erraten. Ich weiß nicht, ob es klug genug ist, das erweiterte Attribut com.apple.TextEncoding der Datei zu verwenden oder nicht.
Edward Falk

Antworten:

33

Dies @bedeutet, dass der Datei erweiterte Dateiattribute zugeordnet sind. Sie können sie mit der getxattr()Funktion abfragen .

Es gibt keine eindeutige Möglichkeit, die Codierung einer Datei zu erkennen. Lesen Sie diese Antwort, es erklärt warum.

Es gibt ein Befehlszeilenprogramm, enca , das versucht, die Codierung zu erraten. Vielleicht möchten Sie es überprüfen.

codelogic
quelle
1
Ich ging davon aus, dass OSX die Codierung als Metadaten gespeichert hat. Ich habe verstanden, dass der Dateiinhalt nur eine Ansammlung von Bits ist und keine inhärente Codierung aufweist.
James A. Rosen
1
@ JamesA.Rosen OS X-Apps wie TextEdit speichern die Dateicodierung als Attribut (mit dem Namen "com.apple.TextEncoding"). Es ist sehr wahrscheinlich, dass die dadurch angegebenen Attribute @das Dateicodierungsattribut enthalten. Mit dem Befehl können Sie xattr -p com.apple.TextEncoding <filename>das Codierungsattribut überprüfen, falls vorhanden.
Bames53
1
Können Sie bitte erklären, wie man getxattr benutzt? Ich kann es nicht benutzen.
MeV
1
Dies ist ein Funktionsaufruf, den Sie verwenden würden, wenn Sie ein Programm schreiben möchten. Geben Sie in der Befehlszeile einfach ein, um ls -l@ <filename>zu sehen, welche Attribute für die Datei festgelegt sind. Um das tatsächliche Attribut zu sehen, geben Siexattr -p com.apple.TextEncoding <filename>
Edward Falk
Um dies zu encatun brew install encaund Sie müssen die Sprache angeben, aber keine funktioniert, also:enca FILENAME -L __
Shane
431

Die Verwendung der -IOption (das ist ein Großbuchstabe i) im Dateibefehl scheint die Dateicodierung anzuzeigen.

file -I {filename}
Tim
quelle
58
Ich musste -I
Casebash
7
Diese Funktion schien nicht in der Lage zu sein, den Unterschied zwischen ASCII und UTF-8 zu erkennen (Scheint, dass sie für die meisten US-Zeichen gleich sind, aber nicht für alle, vielleicht etwas, das das Unicode-Bit erkennen würde)
BadPirate
14
ASCII und UTF8 sind identisch, es sei denn, die Datei enthält ein Zeichen jenseits von OxFF oder eine Stückliste.
Davidtbernal
3
file -I *scheint perfekt für mich zu funktionieren (unter OSX). Ein System beschwerte sich über die Codierung einer von vielen Dateien, ohne anzugeben, welche. Alle Dateien waren ASCII, bis auf eine, die utf-8 war. Höchstwahrscheinlich der Schuldige.
McV
1
@notJim Das ist falsch. ASCII wird nur durch 0x7F definiert, sodass alles, was über diesen Punkt hinausgeht, eindeutig nicht ASCII ist. Unicode und Latin-1 haben die gleichen Codepunkte in 0x80-0xFF, aber es gibt keine gemeinsame Codierung von Unicode, die mit Latin-1 identisch ist (da dies von Natur aus auf 8 Bit beschränkt wäre, was für Unicode viel zu wenig ist).
Tripleee
56

In Mac OS X file -Igibt Ihnen der Befehl (Großbuchstabe i) den richtigen Zeichensatz, solange die zu testende Datei Zeichen außerhalb des grundlegenden ASCII-Bereichs enthält.

Wenn Sie beispielsweise in Terminal gehen und vi verwenden, um eine Datei zu erstellen, z. vi test.txt Fügen Sie dann einige Zeichen ein und fügen Sie ein Zeichen mit Akzent hinzu (versuchen Sie es mit ALT-e gefolgt von e). Speichern Sie dann die Datei.

Sie tippen file -I text.txtund Sie sollten ein Ergebnis wie das folgende erhalten:

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

Cloudranger
quelle
3
Ich kann den OS X-Fall bestätigen, charset = us-ascii oder charset = utf-8, abhängig vom Inhalt der Datei
Ben
aber es scheint nur die ersten paar KB der Datei zu betrachten. In meinem Fall hat der Befehl vim unter stackoverflow.com/a/33644535/161022 die Datei korrekt als utf-8 identifiziert, während der fileBefehl seinenus-ascii
lmsurprenant
In der Tat scheint es, dass Datei aus Leistungsgründen betrügt. Ich habe gerade eine 3-MB-ASCII-Datei unter Ubuntu erstellt und am Ende einige UTF-8-Zeichen hinzugefügt. Es wird weiterhin ASCII und nicht UTF-8 gemeldet. Ich habe die Option -k ausprobiert (mach weiter), aber dann werden "Daten" und nicht "UTF-8" gemeldet, also immer noch nicht gut.
Cloudranger
24
vim -c 'execute "silent !echo " . &fileencoding | q' {filename}

irgendwo in meiner Bash-Konfiguration als

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

also tippe ich einfach

vic {filename}

Auf meinem Vanilla OSX Yosemite liefert es genauere Ergebnisse als "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
jmettraux
quelle
1
Dies ist die einzige Antwort, die mir das gab, was ich brauchte - "latin1" im Gegensatz zu "us-ascii". Obwohl ich die Backslashes entfernen musste.
Katy Lavallee
Vielen Dank, ich habe die Backslashes entfernt.
jmettraux
21

Sie können auch mit dem folgenden Befehl von einem Dateityp in einen anderen konvertieren:

iconv -f original_charset -t new_charset originalfile > newfile

z.B

iconv -f utf-16le -t utf-8 file1.txt > file2.txt
U / min
quelle
13

Benutz einfach:

file -I <filename>

Das ist es.

bx2
quelle
2
Ich kann mir nicht die Mühe machen, abzustimmen, aber diese Antwort ist völlig falsch. Klein -i sagt, klassifiziere den Inhalt nicht, wenn es sich um eine reguläre Datei handelt. -I ist äquivalent zu --mime, das Zeichenfolgen vom Typ MIME ausgibt. Die osx-Tools verhalten sich anders als die Standard-Linux-Tools.
dummMunky
Nun, für eine Windows 1252-codierte Datei file -Ibekomme ich text/plain; charset=unknown-8bit. Obwohl es für eine utf8-Datei besser funktioniert : text/plain; charset=utf-8.
MiB
8

Die Verwendung eines fileBefehls mit der --mime-encodingOption (z. B. file --mime-encoding some_file.txt) anstelle der Option -I funktioniert unter OS X und hat den zusätzlichen Vorteil, dass der MIME-Typ "text / plain" weggelassen wird, der Ihnen wahrscheinlich egal ist.

Adam
quelle
ls -l @ a zeigt erweiterte Attribute an . Wenn ich mir die Manpage für ls auf Yosemite ansehe, sehe ich keine --mime-Codierungsoption.
Stapelhaus
Sie haben über den fileBefehl gesprochen. Wusste nicht, dass es einen gibt. Anfänger. Wie auch immer. Entschuldigung für die Ablehnung. SO kann ich es nicht rückgängig machen, es sei denn, jemand bearbeitet diese Antwort.
Stapelhaus
4

Klassisches 8-Bit-LaTeX ist stark eingeschränkt, in welchen UTF8-Zeichen es verwendet werden kann. Dies hängt stark von der Kodierung der verwendeten Schriftart und den verfügbaren Glyphen ab.

Da Sie kein bestimmtes Beispiel angeben, ist es schwierig, genau zu wissen, wo das Problem liegt - ob Sie versuchen, eine Glyphe zu verwenden, die Ihre Schriftart nicht hat, oder ob Sie in der ersten nicht die richtige Schriftkodierung verwenden Ort.

Hier ist ein minimales Beispiel, das zeigt, wie einige UTF8-Zeichen in einem LaTeX-Dokument verwendet werden können:

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

Sie haben vielleicht mehr Glück mit der [utf8x] -Codierung, aber seien Sie leicht gewarnt, dass sie nicht mehr unterstützt wird und im Vergleich zu [utf8] einige Besonderheiten aufweist (soweit ich mich erinnere; es ist eine Weile her, seit ich sie mir angesehen habe). Aber wenn es den Trick macht, ist das alles, was für Sie wichtig ist.

Will Robertson
quelle
3

Das @ -Zeichen bedeutet, dass die Datei erweiterte Attribute hat . xattr fileZeigt an, welche Attribute es hat, xattr -l filezeigt auch die Attributwerte an (die manchmal groß sein können - versuchen Sie beispielsweise xattr /System/Library/Fonts/HelveLTMM, eine alte Schriftart zu sehen, die in der Ressourcengabel vorhanden ist).

Jouni K. Seppänen
quelle
2

Tippen file myfile.tex ein Terminal können Sie manchmal die Codierung und den Dateityp mithilfe einer Reihe von Algorithmen und magischen Zahlen ermitteln. Es ist ziemlich nützlich, aber verlassen Sie sich nicht darauf, dass es konkrete oder zuverlässige Informationen liefert.

Eine Localizable.stringsDatei (in lokalisierten Mac OS X-Anwendungen enthalten) wird normalerweise als UTF-16 C-Quelldatei gemeldet.

Dreamlax
quelle
1

Synalyse It! ermöglicht den Vergleich von Text oder Bytes in allen Codierungen, die die ICU-Bibliothek bietet. Mit dieser Funktion sehen Sie normalerweise sofort, welche Codepage für Ihre Daten sinnvoll ist.

pi3
quelle
1

Sie können versuchen, die Datei in ein Firefox-Fenster zu laden, und dann zu Ansicht - Zeichenkodierung wechseln. Neben dem Codierungstyp der Datei sollte ein Häkchen stehen.

jmdeamer
quelle
0

Welches LaTeX verwenden Sie? Als ich teTeX verwendete, musste ich das Unicode- Paket manuell herunterladen und zu meinen .tex-Dateien hinzufügen:

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

Jetzt habe ich vom TeXlive 2008-Paket ( hier ) auf XeTeX umgestellt , es ist noch einfacher:

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

Was die Erkennung der Codierung einer Datei angeht, könnte man damit spielen file(1)(aber es ist ziemlich begrenzt), aber wie jemand anderes sagte, ist es schwierig.

Keltia
quelle
0

Eine Brute-Force-Methode zum Überprüfen der Codierung besteht möglicherweise darin, die Datei in einem Hex-Editor oder ähnlichem zu überprüfen. (oder schreiben Sie ein Programm zur Überprüfung) Sehen Sie sich die Binärdaten in der Datei an. Das UTF-8-Format ist ziemlich leicht zu erkennen. Alle ASCII-Zeichen sind Einzelbytes mit Werten unter 128 (0x80). Multibyte-Sequenzen folgen dem in der Abbildung gezeigten Muster Wiki-Artikel

Wenn Sie einen einfacheren Weg finden, ein Programm zu erhalten, um die Codierung für Sie zu überprüfen, ist dies offensichtlich eine Abkürzung, aber wenn alles andere fehlschlägt, würde dies den Trick tun.

jalf
quelle
0

Ich habe das Bash-Skript unten implementiert, es funktioniert für mich.

Es wird zunächst versucht, iconvvon der von file --mime-encodingan zurückgegebenen Codierungutf-8 .

Wenn dies fehlschlägt, werden alle Codierungen durchlaufen und der Unterschied zwischen der ursprünglichen und der neu codierten Datei angezeigt. Es werden Codierungen übersprungen, die eine große Diff-Ausgabe erzeugen ("groß", wie durch definiertMAX_DIFF_LINES Variable oder das zweite Eingabeargument definiert), da dies höchstwahrscheinlich die falsche Codierung ist.

Wenn durch die Verwendung dieses Skripts "schlechte Dinge" passieren, beschuldigen Sie mich nicht. Da ist ein rm -fdrin, also gibt es Monster. Ich habe versucht, nachteilige Auswirkungen zu verhindern, indem ich es für Dateien mit einem zufälligen Suffix verwendet habe, aber ich mache keine Versprechungen.

Getestet auf Darwin 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
Joao Encarnacao
quelle