如何确定文件编码?

46

我有一个用VIM创建的PHP文件,但不确定它的编码方式。

当我在终端中使用命令file -bi foo检查编码方式时(我的操作系统是Ubuntu 11.04),它给出了下一个结果:

text/html; charset=us-ascii

但是,当我使用gedit打开该文件时,它显示的编码方式为UTF-8。

哪个是正确的? 我希望该文件以UTF-8编码。

我猜测该文件没有BOM,并且命令file -bi读取文件时没有找到任何UTF-8字符,所以它假设它是ascii编码,但实际上它是以UTF-8编码的。


你的文件中有哪些非ASCII字符? - dan04
有一个很好的解决方案可以使用Microsoft Visual Studio Code,具体描述请参见https://askubuntu.com/a/681803。 - Mahdi
4个回答

74
$ file --mime my.txt 
my.txt: text/plain; charset=iso-8859-1

8
我觉得值得注意的是,正如@ Celada已经提到的那样,“文件”无法保证其检测的100%正确性。 - Rui Pimentel

62
首先,需要注意的是ASCII是UTF-8的子集,因此,如果您的文件只包含ASCII字符,则可以说它是用ASCII编码的,也可以说它是用UTF-8编码的。
话虽如此,file通常只检查文件开头的一个短片段来确定其类型,因此,如果有非ASCII字符但它们在文件的初始片段之外,它可能会声明为us-ascii。另一方面,gedit可能会说文件是UTF-8,即使它是ASCII,因为UTF-8是gedit首选的字符编码,并且它打算在编辑会话中添加任何非ASCII字符时使用UTF-8保存文件。同样,如果gedit这样说,它也不会错。
现在回答您的问题:
  1. Run this command:

    tr -d \\000-\\177 < your-file | wc -c
    

    If the output says "0", then the file contains only ASCII characters. It's in ASCII (and it's also valid UTF-8) End of story.

  2. Run this command

    iconv -f utf-8 -t ucs-4 < your-file >/dev/null
    

    If you get an error, the file does not contain valid UTF-8 (or at least, some part of it is corrupted).

    If you get no error, the file is extremely likely to be UTF-8. That's because UTF-8 has properties that make it very hard to mistake typical text in any other commonly used character encoding for valid UTF-8.


第一条命令返回了0,第二条命令没有返回错误,因此我们可以说它是UTF-8。谢谢! - ecantu
它给了我1120,这是什么意思? - lazarus
1
是什么导致了你得到1120?是wc吗?如果是的话,我猜测文件中有1120个非ASCII字节。 - Celada
使用 tr -d 是一个非常好的解决方案,因为它允许识别 EBCDIC,并使用 tr -d \\100-\\377。无论是 file 还是 chardet 都不能正确处理 EBCDIC! - Alexander Remesch
第一条命令返回 3,第二条命令没有返回任何内容。 :) - Memristor

30

(在Linux上)

$ chardet <filename>

它还会提供输出的置信水平[0-1]。


1
chardet 似乎是 Python 对“通用”字符编码检测器 uchardet 的封装。虽然 uchardet 可以通过 Homebrew 在 macOS 上使用,但它不会给出置信度水平。 - Heath Raftery

0

基于@Celada的答案和@Arthur Zennig的建议,我创建了这个简单的脚本:

#/bin/bash

if [ "$#" -lt 1 ]
then
  echo "Usage: utf8-check filename"
  exit 1
fi

chardet $1
countchars="$(tr -d \\000-\\177 < $1 | wc -c)"
if [ $countchars -eq 0 ]
then
 echo "Ascii";
 exit 0
fi

{
  iconv -f utf-8 -t ucs-4 < $1 >/dev/null
  echo "UTF-8"
} || {
  echo "not UTF-8 or corrupted"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接