Python 如何检查文件名是否为 UTF8?

Phy*_*ser 5 python windows unicode filenames utf-8

我有一个 PHP 脚本,可以在目录中创建文件列表,但是,PHP 只能看到英文文件名,而完全忽略其他语言(例如俄语或亚洲语言)的文件名。

\n\n

经过大量努力,我找到了唯一适合我的解决方案 - 使用 python 脚本将文件重命名为 UTF8,以便 PHP 脚本可以在之后处理它们。

\n\n

(PHP处理完文件后,我将文件重命名为英文,不将它们保留为UTF8)。

\n\n

我使用了以下 python 脚本,效果很好:

\n\n
import sys\nimport os\nimport glob\nimport ntpath\nfrom random import randint\n\nfor infile in glob.glob( os.path.join('C:\\\\MyFiles', u'*') ):\n    if os.path.isfile(infile):\n      infile_utf8 = infile.encode('utf8')\n      os.rename(infile, infile_utf8)\n
Run Code Online (Sandbox Code Playgroud)\n\n

问题是它还会转换已经采用 UTF8 格式的文件名。我需要一种方法来跳过转换,以防文件名已经是 UTF8。

\n\n

我正在尝试这个 python 脚本:

\n\n
for infile in glob.glob( os.path.join('C:\\\\MyFiles', u'*') ):\n    if os.path.isfile(infile):\n      try:\n        infile.decode('UTF-8', 'strict')\n      except UnicodeDecodeError:\n        infile_utf8 = infile.encode('utf8')\n        os.rename(infile, infile_utf8)    \n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,如果文件名已经是 utf8 格式,我会收到致命错误:

\n\n
UnicodeDecodeError: 'ascii' codec can't decode characters in position 18-20\nordinal not in range(128)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我还尝试了另一种方法,同样不起作用:

\n\n
for infile in glob.glob( os.path.join('C:\\\\MyFiles', u'*') ):\n    if os.path.isfile(infile):\n      try:\n        tmpstr = str(infile)\n      except UnicodeDecodeError:\n        infile_utf8 = infile.encode('utf8')\n        os.rename(infile, infile_utf8)      \n
Run Code Online (Sandbox Code Playgroud)\n\n

我得到了与以前完全相同的错误。

\n\n

有任何想法吗?

\n\n

Python对我来说非常陌生,即使是一个简单的脚本对我来说调试也是一个巨大的努力,所以请写一个明确的答案(即代码)。我没有能力测试可能有效或无效的一般想法。谢谢。

\n\n

文件名示例:

\n\n
 hello.txt\n \xe4\xbd\xa0\xe5\xa5\xbd.txt\n \xec\x95\x88\xeb\x85\x95\xed\x95\x98\xec\x84\xb8\xec\x9a\x94.html\n cha\xcd\x80o.doc\n
Run Code Online (Sandbox Code Playgroud)\n

Ala*_*ack 4

我认为您混淆了术语并做出了一些错误的假设。AFAIK,PHP 可以打开任何编码类型的文件名 - PHP 对于编码类型非常不可知。

\n

你还不清楚你想要实现什么,因为 UTF-8 != English ,示例外国文件名可以用多种方式编码,但不能用 ASCII 英语!您能否解释一下现有的 UTF-8 文件是什么样子以及非 UTF-8 文件是什么?

\n

更让您困惑的是,在 Windows 下,文件名透明地存储为 UTF-16。\n因此,您不应尝试将文件名编码为 UTF-8。相反,您应该使用 Unicode 字符串并允许 Python 进行正确的转换。(也不要使用 UTF-16 进行编码!)

\n

请进一步澄清您的问题。

\n

更新

\n

我现在明白你的 PHP 问题了。http://evertpot.com/filesystem-encoding-and-php/告诉我们非拉丁字符在 PHP+Windows 中很麻烦。似乎只能看到和打开由 Windows 1252 字符集字符组成的文件。

\n

您面临的挑战是将文件名转换为与 Windows 1252 兼容。正如您在问题中所述,最好不要重命名已经兼容的文件。我已将您的尝试修改为:

\n
import os\nfrom glob import glob\nimport shutil\nimport urllib\n\nfiles = glob(u\'*.txt\')\nfor my_file in files:\n    try:\n        print "File %s" % my_file\n    except UnicodeEncodeError:\n        print "File (escaped): %s" % my_file.encode("unicode_escape")\n    new_name = my_file\n    try:\n        my_file.encode("cp1252" , "strict")\n        print "    Name unchanged. Copying anyway"\n    except UnicodeEncodeError:\n        print "    Can not convert to cp1252"\n        utf_8_name = my_file.encode("UTF-8")\n        new_name = urllib.quote(utf_8_name )\n        print "    New name: (%% encoded): %s" % new_name\n    \n    shutil.copy2(my_file, os.path.join("fixed", new_name))\n
Run Code Online (Sandbox Code Playgroud)\n

分解:

\n
    \n
  1. 打印文件名。默认情况下,Windows shell 仅显示本地 DOS 代码页中的结果。例如,我的 shell 可以显示,\xc3\xbc.txt\xe2\x82\xac.txt显示为?.txt. 因此,您需要小心Python抛出异常,因为它无法正确打印。此代码尝试打印 Unicode 版本,但改为打印 Unicode 代码点转义。

    \n
  2. \n
  3. 尝试将字符串编码为 Windows-1252。如果有效,则文件名没问题

    \n
  4. \n
  5. 否则:将文件名转换为 UTF-8,然后对其进行百分比编码。这样,文件名保持唯一,您可以在 PHP 中反转此过程。

    \n
  6. \n
  7. 将文件复制到新的/已验证的文件。

    \n
  8. \n
\n

例如,\xe4\xbd\xa0\xe5\xa5\xbd.txt 变为 %E4%BD%A0%E5%A5%BD.txt

\n