如何确定OS X中的文件编码?


170

我正在尝试在TextMate的LaTeX文件中输入一些UTF-8字符(它的默认编码为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扩展属性是否足够聪明。
爱德华·福尔克

Answers:


33

@意味着该文件具有与之关联的扩展文件属性。您可以使用getxattr()函数查询它们。

没有确定的方法来检测文件的编码。阅读答案,说明原因。

有一个命令行工具enca,它会尝试猜测编码。您可能需要检查一下。


1
我以为OSX将编码存储为元数据。我知道文件内容只是一堆位,没有固有编码。
詹姆斯·罗森

1
@ JamesA.Rosen OS X应用程序(例如TextEdit)确实将文件编码存储为属性(名为“ com.apple.TextEncoding”)。指示的属性很可能@包括文件编码属性。您可以使用该命令xattr -p com.apple.TextEncoding <filename>查看encoding属性(如果存在)。
bames53 2014年

1
您能解释一下如何使用getxattr吗?我无法使用它。
MeV

1
如果要编写程序,将使用该函数。在命令行中,只需键入ls -l@ <filename>以查看为文件设置了哪些属性。要查看实际属性,请输入xattr -p com.apple.TextEncoding <filename>
Edward Falk

enca做到这一点brew install enca,您必须指定语言,但没有任何规定,因此:enca FILENAME -L __
Shane

433

-I在file命令上使用(大写i)选项似乎显示了文件编码。

file -I {filename}

58
我需要使用-I
Casebash 2010年

7
此功能似乎无法分辨ASCII和UTF-8之间的区别(似乎对于大多数美国字符而言,它们是相同的,但不是全部,也许可以检测到Unicode位的某些东西)
BadPirate 2010年

14
ASCII和UTF8相同,除非文件或BOM表中的字符超出OxFF。
davidtbernal 2011年

3
file -I *似乎对我来说很完美(在OSX上)。系统抱怨许多文件之一的编码,但未指定哪个。除了一个文件utf-8,所有文件均为ascii。罪魁祸首。
mcv 2011年

1
@notJim 那是不正确的。ASCII仅通过0x7F进行定义,因此超出该范围的任何内容显然都不是ASCII。Unicode和Latin-1在0x80-0xFF中具有相同的代码点,但是没有通用的Unicode 编码与Latin-1相同(因为从本质上来说,它只能限制为8位,这对于Unicode而言太少了)。
2015年

56

在Mac OS X中,file -I只要所测试的文件包含基本ASCII范围之外的字符,命令(大写i)将为您提供正确的字符集。

例如,如果您进入Terminal并使用vi创建文件,例如。vi test.txt 然后插入一些字符并包含带重音符号的字符(尝试ALT-e后跟e),然后保存文件。

他们输入file -I text.txt,您应该得到如下结果:

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


3
我可以确认的OS X的情况下,字符集= US-ASCII字符集或= UTF-8取决于文件的内容

但似乎只看文件的前几KB。就我而言,位于stackoverflow.com/a/33644535/161022的vim命令正确地将文件标识为utf-8,而该file命令声称其us-ascii
lmsurprenant

确实,文件由于性能原因而作弊。我刚刚在Ubuntu上创建了一个3MB的ASCII文件,并在末尾添加了一些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

在OS X上使用file--mime-encoding选项(例如file --mime-encoding some_file.txt)而不是-I选项的command 可以在OS X上使用,它还有一个好处,就是可以省去您可能不在乎的mime类型“ text / plain”。


ls -l @ a将显示扩展属性。在优胜美地上查看ls的手册页时,我看不到--mime-encoding选项。
rstackhouse 2015年

您在谈论file命令。不知道一个人存在。菜鸟。无论如何。对不起,不好意思。因此,除非有人编辑此答案,否则我不会撤消它。
rstackhouse

4

经典的8位LaTeX在使用UTF8字符方面有严格的限制。它高度取决于您使用的字体的编码以及该字体可用的字形。

由于您没有给出具体的示例,因此很难确切地知道问题出在哪里–您是尝试使用字体中没有的字形还是在第一个示例中使用的字体编码不正确地点。

这是一个最小的示例,显示了如何在LaTeX文档中使用几个UTF8字符:

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

您可能对[utf8x]编码有更多的希望,但是要稍微警告一下,与[utf8]相比,它不再受支持并且具有一些特质(据我所记得;自从我看过已经有一段时间了)。但是,如果成功,那么这对您就很重要。



2

file myfile.tex在终端上键入内容有时可以使用一系列算法和幻数来告诉您文件的编码和类型。它相当有用,但不要依赖它提供具体或可靠的信息。

Localizable.strings文件(在局部Mac OS X应用发现)通常报道为一个UTF-16 C源文件。


1

合成吧!允许比较ICU库提供的所有编码中的文本或字节。使用该功能,您通常会立即看到哪个代码页对您的数据有意义。


1

您可以尝试将文件加载到firefox窗口中,然后转到“查看”“字符编码”。文件的编码类型旁边应有一个复选标记。


0

您正在使用哪个乳胶?当我使用teTeX时,我不得不手动下载unicode软件包并将其添加到我的.tex文件中:

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

现在,我已经从TeXlive 2008软件包(此处)切换到XeTeX ,它更加简单:

% 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,所以有怪物。我试图通过在带有随机后缀的文件中使用它来防止不利影响,但我没有做出任何承诺。

在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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.