ChatGPT解决这个技术问题 Extra ChatGPT

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

我正在尝试将一些 UTF-8 字符输入到 TextMate 中的 LaTeX 文件中(表示其默认编码为 UTF-8),但 LaTeX 似乎不理解它们。

运行 cat my_file.tex 在终端中正确显示字符。运行 ls -al 会显示我以前从未见过的内容:文件列表中的“@”:

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

(而且,是的,我在 LaTeX 中使用了 \usepackage[utf8]{inputenc}。)

我找到了 iconv,但这似乎无法告诉我编码是什么——它只有在我弄清楚后才会转换。

根据我的经验,file(1) 命令一直非常擅长猜测文件的编码。我不知道使用文件的 com.apple.TextEncoding 扩展属性是否足够聪明。

N
Naman

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

file -I {filename}

这个函数似乎无法区分 ASCII 和 UTF-8 (似乎它们对于大多数美国字符都是相同的,但不是全部,也许可以检测到 unicode 位)
我在这里和@BadPirate 在一起,不区分 ascii 和 utf-8(在 OSX 上测试)
ASCII 和 UTF8 是相同的,除非文件中存在超出 OxFF 的字符或 BOM。
file -I * 似乎非常适合我(在 OSX 上)。系统抱怨许多文件之一的编码,但没有指定哪个。所有文件都是 ascii,除了一个是 utf-8。很可能是罪魁祸首。
@notJim That's incorrect. ASCII 仅在 0x7F 之前定义,因此超出该点的任何内容显然都不是 ASCII。 Unicode 和 Latin-1 在 0x80-0xFF 中具有相同的代码点,但没有与 Latin-1 相同的 Unicode 通用 encoding (因为它固有地被限制为 8 位,这很对于 Unicode 来说太少了)。
r
random_user_name

在 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


我可以根据文件的内容确认 OS X 的情况,charset=us-ascii 或 charset=utf-8
但它似乎只查看文件的前几 KB。在我的例子中,stackoverflow.com/a/33644535/161022 处的 vim 命令正确地将文件识别为 utf-8,而 file 命令声称它的 us-ascii
事实上,文件作弊似乎是出于性能原因。我刚刚在 Ubuntu 上创建了一个 3MB 的 ASCII 文件,并在末尾添加了一些 UTF-8 字符,但它仍然报告 ASCII 而不是 UTF-8。我尝试了 -k 选项(继续),但它报告“数据”而不是“UTF-8”,所以仍然不好。
C
Community

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

没有确定的方法来检测文件的编码。阅读this答案,它解释了原因。

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


我假设 OSX 将编码存储为元数据。我知道文件内容只是一组位,没有固有的编码。
@JamesA.Rosen 像 TextEdit 这样的 OS X 应用程序确实将文件编码存储为属性(名为“com.apple.TextEncoding”)。 @ 指示的属性很可能包含文件编码属性。您可以使用命令 xattr -p com.apple.TextEncoding <filename> 查看编码属性(如果存在)。
你能解释一下如何使用 getxattr 吗?我无法使用它。
如果您想编写程序,那是您将使用的函数调用。在命令行中,只需键入 ls -l@ <filename> 即可查看为文件设置了哪些属性。要查看实际属性,请输入 xattr -p com.apple.TextEncoding <filename>
要获得 enca,请执行 brew install enca,您必须指定语言,但 none 有效,因此:enca FILENAME -L __
j
jmettraux
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

这是给我所需的唯一答案——“latin1”,而不是“us-ascii”。虽然,我确实必须删除反斜杠。
非常感谢,我删除了反斜杠。
$ alias vic="vim -c '执行 \"silent !echo \" . &fileencoding | q'" -bash: !echo: 未找到事件
@AntonTropashko alias vic="vim -c 'execute \"silent \!echo \" . &fileencoding | q'"
R
RPM

您还可以使用以下命令从一种文件类型转换为另一种文件类型:

iconv -f original_charset -t new_charset originalfile > newfile

例如

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

b
bx2

只需使用:

file -I <filename>

而已。


我懒得投反对票,但这个答案是完全错误的。小 -i 表示如果是常规文件,则不要对内容进行分类。 -I 相当于 --mime 输出 mime 类型字符串。 osx 工具的行为与标准 linux 工具不同。
好吧,对于 Windows 1252 编码文件,file -I 让我text/plain; charset=unknown-8bit。虽然它对 utf8 文件效果更好:text/plain; charset=utf-8
r
rstackhouse

使用带有 --mime-encoding 选项(例如 file --mime-encoding some_file.txt)的 file 命令而不是 -I 选项在 OS X 上有效,并且具有省略 mime 类型“text/plain”的额外好处,您可能不会这样做关心。


ls -l@a 将显示 extended attributes。查看 Yosemite 上 ls 的手册页,我没有看到 --mime-encoding 选项。
您在谈论 file 命令。不知道有那个存在。小白。反正。很抱歉投反对票。除非有人编辑此答案,否则不会让我撤消它。
W
Will Robertson

经典的 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] 相比有一些特质(据我记得;我已经有一段时间没有看过它了)。但如果它成功了,那对你来说就是最重要的。


J
Jouni K. Seppänen

@ 符号表示文件有 extended attributesxattr file 显示它具有哪些属性,xattr -l file 也显示属性值(有时可能很大 — 尝试例如 xattr /System/Library/Fonts/HelveLTMM 来查看资源分支中存在的旧式字体)。


d
dreamlax

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

Localizable.strings 文件(可在本地化的 Mac OS X 应用程序中找到)通常报告为 UTF-16 C 源文件。


p
pi3

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


j
jmdeamer

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


J
Joao Encarnacao

我实现了下面的 bash 脚本,它对我有用。

它首先尝试将 iconvfile --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

K
Keltia

您使用的是哪种 LaTeX?当我使用 teTeX 时,我必须手动下载 unicode 包并将其添加到我的 .tex 文件中:

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

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

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

至于检测文件的编码,您可以使用 file(1) (但它相当有限)但就像其他人所说的那样,这很困难。


j
jalf

检查编码的蛮力方法可能只是在十六进制编辑器或类似工具中检查文件。 (或编写程序检查)查看文件中的二进制数据。 UTF-8 格式相当容易识别。所有 ASCII 字符都是单字节,其值低于 128 (0x80) 多字节序列遵循 wiki article 中显示的模式

如果您能找到一种更简单的方法来让程序为您验证编码,那显然是一种捷径,但如果一切都失败了,这将起到作用。