解决方案

Linux-Windows主机目录和文件名中文乱码恢复 - clover_toeic - 博客园

seo靠我 2023-09-23 20:57:17

Linux->Windows主机目录和文件名中文乱码恢复 - clover_toeic - 博客园

https://www.cnblogs.com/clover-toeic/p/5235316.htmlSEO靠我

中国知网文件乱码修复方法。

Linux->Windows主机目录和文件名中文乱码恢复

标签: 字符编码 Python

[TOC]

声明

本文主要记述作者如何通过Python脚本恢复跨平台传输导致的目录和文件名中SEO靠我文乱码。作者对Python编程和字符编码了解不多,纰漏难免,欢迎指正。同时,本文兼做学习笔记,存在啰嗦之处,敬请谅解。

本文同时也发布于作业部落,阅读体验可能更好。

一. 乱码问题

一年前,作者将WindoSEO靠我ws XP系统主机下创建的一批文件(以多级目录组织),通过Samba手工拷贝至Linux系统主机,能正常显示目录和文件名中包含的中文字符。然后,通过filezilla连接Linux主机,将上述文件下载SEO靠我至移动硬盘,这个过程中也未出现乱码。但将移动硬盘连接到Windows 7系统主机上时,却发现目录和文件名中包含的中文字符出现乱码。

例如,文件名"GNU Readline库函数的应用示例"和"守护进程接SEO靠我收终端输入的一种变通性方法"分别显示为"GNU Readline库函数的应用示例"和"守护进程接收终端输入的一种åSEO靠我˜é€šæ€§æ–¹æ³•"。

但除目录和文件名出现中文乱码外,文件内容并无乱码。

作者当时并不熟悉字符编码知识,于是请教《通俗易懂地解决中文乱码问题(1) --- 跨平台乱码》一文的作者Roly-PolSEO靠我y。Roly-Poly非常热心地转换了上述两个文件名,并给出效果图:

以及相应的Java转换方法:String str = new String(new String(messyName.getByteSEO靠我s("ISO-8859-1"), "GBK").getBytes("GBK"), "UTF-8");

其中,messyName对应出现乱码的字符串。getBytes(charset)将Unicode编码SEO靠我存储的字符串按照charset编码,并以字节数组表示;new String(bytes[], charset)则将字节数组按照charset编码进行组合识别,最后转换为Unicode存储。因此,上述代SEO靠我码表示先将当前编码从 ISO-8859-1转为GBK,然后再从GBK转为UTF-8。

当然,Roly-Poly的转换仍有缺憾,毕竟还存在未能正确解析的乱码。"幸运"的是,当时出于谨慎,作者分别通过dirSEO靠我 /S path、tree /F path(Windows)和ls -lRS --time-style=long-iso(Linux)创建了三份文件列表。这样,在Roly-Poly转码的基础上再做些校SEO靠我验,有望替换为完全正确的文件名。

然而,一方面因为作者对Java语言和字符编码比较陌生(主要是懒),另一方面因为解析文件列表并更名的工作量预期较大,作者一直未付诸实践。直到最近,才开始从头着手处理乱码问SEO靠我题。这一过程学到不少知识,也走过不少弯路。教训就是:凡事要一鼓作气!

二. 调试环境

作者使用Python 2.7自带的IDLE进行编码调试。除非特别说明,本文所有代码均为Python语言。

参考PythoSEO靠我n字符编码详解一文,获取当前环境的默认编码:#!/usr/bin/python # -*- coding: utf-8 -*-import sys, locale deSEO靠我f SysCoding():fmt = {0}:{1}#当前系统所使用的默认字符编码print fmt.format(DefaultEncoding , sys.getdefaultencoding(SEO靠我))#转换Unicode文件名至系统文件名时所用的编码(None表示使用系统默认编码)print fmt.format(FileSystemEncoding , sys.getfilesystemenSEO靠我coding())#默认的区域设置并返回元祖(语言, 编码)print fmt.format(DefaultLocale , locale.getdefaultlocale())#用户首选的文本数据编SEO靠我码(猜测结果)print fmt.format(PreferredEncoding , locale.getpreferredencoding())if __name__ == __main__:SySEO靠我sCoding()

作者的Windows XP系统主机上,区域和语言选项->区域选项->标准和格式及高级->非Unicode程序的语言均设置为"中文(中国)";Windows 7系统主机上,区域和语言-SEO靠我>格式及管理->非Unicode程序的语言均设置为"中文(简体,中国)"。两台主机的SysCoding()输出相同,均显示如下:

DefaultEncoding :ascii FileSSEO靠我ystemEncoding :mbcs DefaultLocale :(zh_CN, cp936) PreferredEncoding :cp936

三. 目录和文件名乱SEO靠我码恢复

3.1 可选方案

3.1.1 通过合适的编解码转换

可使用chardet模块detect()函数检测给定字符的编码。该函数返回检测到的编码encoding及其可信度confidence。

安装方法为:SEO靠我命令提示符下执行C:\Python27\Scripts>easy_install.exe chardet后,自动下载egg文件包。若未安装成功(import提示"ImportError: No modSEO靠我ule named chardet"),可到C:\Python27\Lib\site-packages目录解压egg文件包,将其中的chardet目录(所有文件)拷贝到site-packages下面即SEO靠我可。

安装成功后,按照以下方法检测字符编码:

#coding: gbk import chardet print chardet.detect(abc) #{confideSEO靠我nce: 1.0, encoding: ascii} print chardet.detect(喊) #{confidence: 0.73, encoding: windows-125SEO靠我2} print chardet.detect(汉) #{confidence: 0.99, encoding: TIS-620} ##Thailand print cSEO靠我hardet.detect(汉中华人民共和国) #{confidence: 0.99, encoding: GB2312} print 汉中华人民共和国, repr(汉中华人民共和国)SEO靠我 #汉中华人民共和国 \xba\xba\xd6\xd0\xbb\xaa\xc8\xcb\xc3\xf1\xb9\xb2\xba\xcd\xb9\xfa

可见,当字符"样本"过少时,chaSEO靠我rdet检测结果并不准确(如汉被识别为泰文)。在Shell中执行上述检测时,结果与之相同。

作为对比,声明为coding: utf-8时,检测结果又是另一番"景象":

import chardet SEO靠我 print chardet.detect(abc) #{confidence: 1.0, encoding: ascii} print chardet.detect(成CSEO靠我Unitè¿›è¡) #{confidence: 0.99, encoding: utf-8} print chardet.detect(喊) #{confidence: 0.73, SEO靠我encoding: windows-1252} print chardet.detect(汉) #{confidence: 0.73, encoding: windows-1252} SEO靠我 print chardet.detect(汉中华人民共和国) #{confidence: 0.99, encoding: utf-8} print 汉中华人民共和国, SEO靠我repr(汉中华人民共和国) #姹変腑鍗庝汉姘戝叡鍜屽浗 \xe6\xb1\x89\xe4\xb8\xad\xe5\x8d\x8e\xe4\xba\xba\xe6\xb0\x91\xeSEO靠我5\x85\xb1\xe5\x92\x8c\xe5\x9b\xbd

可见,口语奇招_æ–°æµ被检测为UTF-8编码。这是因为UTF-8是ASCII的超集。当字符串序列中所有字符均为ASSEO靠我CII符号(前128个字符)时,chardet认为该串为ASCII编码;当字符串序列中也含有所有扩展ASCII符号时,chardet很可能认为该串为UTF-8编码。此外,print根据本地操作系统默认SEO靠我字符编码(GBK),将汉中华人民共和国打印为姹変腑鍗庝汉姘戝叡鍜屽浗。

3.1.2 根据文件列表信息匹配

通过正则表达式提取文件列表中的目录大小、文件数目、文件名及其大小、创建时间等信息,再遍历移动硬盘乱SEO靠我码目录,进行匹配和更名。为保险起见,应维护一份映射文件,存储文件路径、原名和新名,以便恢复或校正。

为减少匹配和更名次数,只操作名称包含字母数字以外字符的目录和文件。此外,还可对文件列表排序,如dir SEO靠我path /S /O:S(按大小升序排列)。

3.1.3 机器学习

因为word、网页等文件打开后通常可以看到标题,作者得以整理若干文件乱码名与正常名的映射数据。这样,借助机器学习(如基于实例的算法),最SEO靠我终有望消除所有乱码。

显然,这一方案难度太高,并不现实。

3.2 逐步实践

3.2.1 获取单级目录及其文件信息

首先,创建名称正常的多级目录供调试用。之所以不用原始乱码目录调试,是因为一旦测试失败很可能会破SEO靠我坏"样本"。

然后,通过以下代码获取单级目录的大小、文件数目、文件名及大小、创建时间等信息:

import time from os.path import join, getsize, SEO靠我getmtime, getctime CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) #os.getcSEO靠我wd()返回当前工作目录 def FilesInfo():for root, dirs, files in os.walk(CURRENT_DIR):for file in filesSEO靠我:path = join(root, file)ctime = time.ctime(getctime(path)) #创建时间print Name:%-12s Size:%-7s Ctime:%s SEO靠我%(file, getsize(path), ctime)print root, "consumes",print sum(getsize(join(root, file)) for file in SEO靠我files),print "bytes in", len(files), "non-directory files!"

注意,当本模块由其他模块import并执行时,os.getcwd()返回的并非本模SEO靠我块目录。

执行FilesInfo()后,输出结果如下:

Name:Coding.py Size:7936 Ctime:Mon Feb 29 09:41:15 2016 Name:d_resSEO靠我.bmp Size:522534 Ctime:Mon Feb 29 09:41:15 2016 Name:error3.bmp Size:70782 Ctime:Mon Feb 29 SEO靠我09:41:15 2016 Name:Open.bmp Size:354746 Ctime:Mon Feb 29 09:41:15 2016 Name:Thumbs.dSEO靠我b Size:19968 Ctime:Mon Feb 29 09:41:47 2016 Name:typec.bmp Size:199022 Ctime:Mon Feb 29 09:4SEO靠我1:15 2016 Name:WalkDir.py Size:4894 Ctime:Mon Feb 29 09:41:15 2016 Name:复Coding.py SSEO靠我ize:6564 Ctime:Mon Feb 29 15:41:37 2016 E:\PyTest\stuff consumes 1186446 bytes in 8 non-direSEO靠我ctory files!

3.2.2 从文件列表中提取目录和文件信息

在命令提示符下dir \F出调试目录的结构。截取部分如下:

C:\Program Files\IDM Computer SolutionSEO靠我s\UEStudio>e:E:\PyTest 的目录2016-02-24 11:53 <DIR> . 2016-02-24 11:53 <DIR> .. 2016-02SEO靠我-23 17:22 1,434 backup_ver2.py

然后,通过ParseFileList()函数解析出"E:\PyTest"之类的路径:

import codecs, re deSEO靠我f ParseFileList():#Windows记事本默认的字符编码为"ANSI"(实际是GBK)file = codecs.open(rE:\PyTest\filelist.txt, encodSEO靠我ing=gbk)for line in file:#下句等效于m = re.match(u (.+) 的目录\s*$, line)m = re.compile(u""" # Python默认字符编码为SEO靠我Ansi, 需加u转为Unicode (.+) 的目录 # 将 的目录前的部分作为分组(Group) \s*$ # 行尾""", re.X).match(line)ifSEO靠我 m != None:print m.groups()[0]

注意,此处并未使用内置的open()方法打开文件。因为该方法得到的line为str类型,需要使用正确的编码格式进行decode(),否则将无SEO靠我法匹配到"的目录"。而codecs.open()方法打开文件时读取的就是Unicode类型,不容易出现编码问题。

当然,若将源代码文件中的字符编码声明改为#coding=gbk,并去掉pattern字符SEO靠我串前缀u,则使用内置的open()方法仍可匹配到"的目录"。

目录大小、文件数目、文件名及其大小等,均可通过合适的正则表达式提取。然而,作者很快意识到,根据文件列表遍历和更名的方案实现起来过于复杂。于是SEO靠我,放弃正则匹配的尝试。

3.2.3 遍历目录并更名

虽然文件列表正则匹配的方案不可行,但遍历和更名却是所有方案所必需的。

Python中有三种遍历目录的方法,即os.listdir()、os.walk()和SEO靠我os.path.walk()。这三者中,作者首选os.walk()方法,遍历代码如下:

import os def ValidateDir(dirPath):#判断路径是否为UnicodSEO靠我e。若否,将其转换为Unicode编码if isinstance(dirPath, unicode) == False:#下句等效于dirPath = dirPath.decode(utf8)dirPSEO靠我ath = unicode(dirPath, utf8)#判断路径是否存在(不区分大小写)if os.path.exists(dirPath) == False:print dirPath + is SEO靠我non-existent!return #判断路径是否为目录(不区分大小写)if os.path.isdir(dirPath) == False:print dirPath + is not a diSEO靠我rectory!return return dirPathdef WalkDirReport(dirPath, fileNum):print ############## + str(fileNum)SEO靠我 + files processed##############def WalkDir(dirPath):dirPath = ValidateDir(dirPath)if not dirPath:reSEO靠我turn#遍历路径下的文件及子目录fileNum = 0for root, dirs, files in os.walk(dirPath):for file in files:#处理文件#ChangeSEO靠我Names(root, file)#RestoreNames(root, file)fileNum += 1while(fileNum % 100) == 0:prompt = $ + str(filSEO靠我eNum) + files processed, \+ pause for checking. Type c to continue: if raw_input(prompt) == c:breakWSEO靠我alkDirReport(dirPath, fileNum)

其中,ValidateDir()用于校验路径合法性,同时还将非Unicode路径转为Unicode路径(该步骤也可由使用者自行完成)。

os.SEO靠我listdir()方法遍历目录则较为"笨拙",对比如下:

def WalkDir_unsafe(dirPath):dirPath = ValidateDir(dirPath)if not dirPathSEO靠我:return#遍历路径下的文件及子目录fileNum = 0nameList = os.listdir(dirPath)for name in nameList:path = os.path.joiSEO靠我n(dirPath, name)#类型为目录,递归(存在栈溢出风险)if os.path.isdir(path) == True:fileNum += WalkDir_unsafe(path)contSEO靠我inue#处理文件此时name等效于os.path.basename(path),即文件名; dirPath等效于os.path.dirname(path),即目录名; SEO靠我 path等效于os.path.abspath(os.path.basename(path)),即绝对路径fileNum += 1return fileNum

因为采用递归处理,所以该方法存在栈溢出风险SEO靠我(不过作者尚未遇到这种情况)。使用时,需按照如下方式调用:

WalkDirReport(rE:\Pytest\测试, WalkDir_unsafe(rE:\Pytest\测试))

注意,虽然os.walkSEO靠我()本身仍由os.listdir()递归实现,但却是生成器(generator)写法,相比普通递归更节省内存资源。

遍历目录调试通过后,就可着手实现目录和文件更名。为简单起见,更名规则为"尾部添0",即SEO靠我"E:\a\b.txt"会转换为"E:\a0\b.txt0"。同时提供恢复函数,以便反复调试。代码如下:

def ChangeNames(dir, file):#将E:\a\b.txt转换为E:\a0\SEO靠我b.txt0,以此类推filePath = os.path.join(dir, file)newdir = dir.split(\\)newdir[1:] = map(lambda x: x+0, nSEO靠我ewdir[1:]) #盘符不变newdir = \\.join(newdir)ufilePath = os.path.join(newdir, file) + 0print filePath + =SEO靠我> + ufilePathos.renames(filePath, ufilePath)def RestoreNames(dir, file):#将E:\a0\b.txt0恢复为E:\a\b.txt,SEO靠我以此类推filePath = os.path.join(dir, file)newdir = dir.split(\\)newdir[1:] = map(lambda x: x[:-1], newdiSEO靠我r[1:])newdir = \\.join(newdir)ufilePath = os.path.join(newdir, file)[:-1]print filePath + => + ufileSEO靠我Pathos.renames(filePath, ufilePath)

可见,"添0"和恢复的方法比较"笨拙"。但作为Python新手,作者暂时只能如此。结合遍历代码,ChangeNames()和ResSEO靠我toreNames()可有效地更名和恢复。

注意os.renames()方法,该方法可对嵌套目录及其文件更名,可能会创建临时目录以存放新命名的子目录和文件。因此,若以WalkDir(rE:\bPytesSEO靠我t)方式调用且bPytest目录下存在空的子目录,则更名后该子目录保持原名原位置(仍在E:\bPytest目录下),而其他子目录及文件被更名且"转移"到E:\bPytest0目录下——同时出现bPytSEO靠我est和bPytest0两个目录!

3.2.4 消除单个文件名乱码

遍历和更名调试成功后,接下来便是重中之重——乱码文件名恢复。

浏览各种网络资料后,作者终于在Stackoverflow网站上一则问答GetSEO靠我ting correct utf8 Chinese characters from messed-up iso-8859-1 in Python and MySQL里找到一线曙光。回答者通过u最.SEO靠我encode(cp1252).decode(utf8)成功地将最转换为"最"——这与作者遇到的乱码何其相似!

在尝试cp1252、cp1254...等众多Windows编码后,作者终于找到正确的编码SEO靠我格式,即latin_1,别名iso-8859-1, iso8859-1, 8859, cp819, latin, latin1, L1。测试代码如下:

print u项目中集成CUnSEO靠我it进行开发测试.encode(latin_1).decode(utf8) print u《NBC夜间新闻(2011-2å­£).encodSEO靠我e(latin_1).decode(utf8) print 新浪博客.decode(utf8).encode(latin_1).decode(utf8)

其中,ustriSEO靠我ng等效于string.decode(utf8)。运行结果为:

项目中集成CUnit进行开发测试 《NBC夜间新闻(2011-2季) 新浪博客

经人工检验,完全符合期望!

SEO靠我时再回想Roly-Poly提供的Java转码语句:

String str = new String(new String(messyName.getBytes("ISO-8859-1"), "GBK")SEO靠我.getBytes("GBK"), "UTF-8");

因为字符串在Java内存中以Unicode编码存储,且getBytes()和new String()分别对应Python里的encode()和deSEO靠我code(),所以等效的Python转码语句如下:

str = umessyName.encode(latin_1).decode(gbk).encode(gbk).decode(utf8)

从字符编码规SEO靠我则可知,经过GBK编解码"中转"后,很可能出现data loss。以第一章的两个文件名为例,其Python转码如下:

s1 = uGNU Readline库函数的应用示例SEO靠我.encode(latin_1).decode(gbk).encode(gbk,replace).decode(utf8) s2 = u守护进程接收终端SEO靠我输入的一种变通性方法.encode(latin_1).decode(gbk,replace).encode(gbk,replace).decode(utf8,rSEO靠我eplace) s3 = u守护进程接收终端输入的一种变通性方法.encode(latin_1).decode(SEO靠我utf8) print s1 #GNU Readline库函数的应用示例 print s2 #守护进程接收终�?输入的一种变通�?方法 print s3SEO靠我 #守护进程接收终端输入的一种变通性方法

其中,replace参数以适当的字符替换编解码过程中无法识别的字符,否则将产生UnicodeDecodeError和UnicodeEncodeError异常。可SEO靠我见,就本文问题而言,并不需要GBK编解码"中转"。

3.2.5 消除单级目录下文件名乱码

文件名字符串乱码恢复成功后,接下来将对文件更名。该步骤需要在挂接移动硬盘的Windows 7主机上进行,因为在WiSEO靠我ndows XP主机上文件名乱码无法以期望的方式显示和解析。例如:

最后那个以乱码字符串为名创建的文件,无法打开(UEStudio提示"含有一个无效的路径",记事本提示"无效的窗口句柄"),os.renSEO靠我ame()也会报错。

在Windows 7主机上,作者从移动硬盘拷贝一个单级乱码目录至磁盘作调试用。然后,编写代码恢复该目录下的所有乱码文件名:

from nt import chdir SEO靠我def RecodeName(dirPath):nameList = os.listdir(dirPath)for fileName in nameList:try:ufileName = fileNSEO靠我ame.encode(latin_1).decode(utf8)except UnicodeEncodeError as e:print [e] + fileName + (Possibly needSEO靠我n\t xcode!)continueprint (fileName + => + ufileName)#rename之前要先用chdir()函数进入到目标文件所在的路径chdir(dirPath)oSEO靠我s.rename(fileName, ufileName)

因为存在某些文件已被手工更名的可能性,encode(latin_1)时会抛出UnicodeEncodeError异常,所以需要跳过这些文件。

SEO靠我行结果如下:

8.26南京990小经验,希望对以后的人有帮助 - 英语托业考试(TOEIC) - 大家è®SEO靠我ºå› -.url => 8.26南京990小经验,希望对以后的人有帮助 - 英语托业考试(TOEIC) - 大家论坛 -.url ~2011.5.29~托业905æ„ŸæƒSEO靠我³~感谢大家网论坛~希望能给大家带来帮助 - 英语托业考试(TOEIC) - 大家论坛 -.SEO靠我url => ~2011.5.29~托业905感想~感谢大家网论坛~希望能给大家带来帮助 - 英语托业考试(TOEIC) - 大家论坛 -.url 中国雅思网.urSEO靠我l => 中国雅思网.url 如何提高英语听力_提高英语听力的方法_听力课堂.url => 如何提高SEO靠我英语听力_提高英语听力的方法_听力课堂.url >>>

经验证,指定目录下所有乱码文件名均正确恢复。

3.2.6 消除嵌套目录名及其文件名乱码

单级目录下文件名乱码消除后,作者换用os.reSEO靠我names()方法消除嵌套目录名及其文件名。代码如下:

def RecodeNames(dir, file):filePath = os.path.join(dir, file)try:filePathSEO靠我New = filePath.encode(latin_1).decode(utf8)except UnicodeEncodeError as e:os.renames()会创建临时目录以存放新命名的SEO靠我子目录和文件,故此处异常 表明最底层文件已解码成功(可能是手工处理),但其目录路径仍未解码。 因此,需构造已解码全路径,以便renames将上述文件拷贝至新目录。 SEO靠我 print [e] + filePath + (Possibly needn\t xcode!)filePathNew = os.path.join(dir.encode(latin_1)SEO靠我.decode(utf8), file)print (filePath + => + filePathNew)os.renames(filePath, filePathNew)

以WalkDir(rF:SEO靠我\Pytest\Study)运行,结果如下:

F:\Pytest\Study\John_新浪博客.url => F:\Pytest\Study\John_新浪博客.url SEO靠我 [e]F:\Pytest\Study\ABR\~2011.5.29~托业905感想~感谢大家网论坛~希望能给大家带来帮助 - 英语托业考试(TOEIC) - 大家论坛 -.url(Possibly SEO靠我neednt xcode!) F:\Pytest\Study\ABR\~2011.5.29~托业905感想~感谢大家网论坛~希望能给大家带来帮助 - 英语托业考试(TOEIC) - 大SEO靠我家论坛 -.url => F:\Pytest\Study\ABR\~2011.5.29~托业905感想~感谢大家网论坛~希望能给大家带来帮助 - 英语托业考试(TOEIC) - 大家论坛 -.url SEO靠我 F:\Pytest\Study\待读\《NBC夜间新闻(2011-2å­£)》(NBC Nightly News)([m4v]英语听力äSEO靠我¸‹è½½ -学习资料库.url => F:\Pytest\Study\待读\《NBC夜间新闻(2011-2季)》(NBC Nightly News)([m4v]英语听力下载 -学SEO靠我习资料库.url ##############3 files processed##############

可见,根目录和子目录及所有下属文件均正确更名。

读者可能已经注意到,上述根目录SEO靠我路径名均为英文字符。假如该路径包含已解码的中文目录名(可能是手工处理)呢?例如将Study目录名改为外语学习。显然,encode(latin_1)时会触发UnicodeEncodeError异常。因此SEO靠我,编解码时需要跳过这些中文目录名:

def RecodeNames(dir, file):filePath = os.path.join(dir, file)#对路径解码paths = filePathSEO靠我.split(\\)for i in range(len(paths)):try:paths[i] = paths[i].encode(latin_1).decode(utf8)except UnicSEO靠我odeEncodeError as e:#路径可能出现已解码的中文(可能是手工处理),不再重复解码continuefilePathNew = \\.join(paths)print (filePathSEO靠我 + => + filePathNew)os.renames(filePath, filePathNew)

什么?假如目录名包含部分乱码部分中文字符?拜托,这种情况不可能出现。

3.2.7 恢复原始乱码目SEO靠我录和文件名

激动人心的时刻来到了!本节将正式处理移动硬盘中的原始乱码目录和文件名。基于以上调试结果,最终的乱码恢复代码如下:

failedNamesList = [] def RecordSEO靠我FailedNames(name):failedNamesList.append(name)import ctypes def RecodeNames(dir, file):filePSEO靠我ath = os.path.join(dir, file)#对路径解码paths = filePath.split(\\)for i in range(len(paths)):try:paths[i]SEO靠我 = paths[i].encode(latin_1).decode(utf8)except UnicodeEncodeError as e:#路径可能出现已解码的中文(可能是手工处理),不再重复解码SEO靠我continuefilePathNew = \\.join(paths)print (filePath + => + filePathNew)try:os.renames(filePath, fileSEO靠我PathNew)except WindowsError as e:print "[e]WindowsError({0}): {1}".format(e.winerror, ctypes.FormatESEO靠我rror(e.winerror))RecordFailedNames(filePath)def WalkDirReport(dirPath, fileNum):print ##############SEO靠我 + str(fileNum) + files processed##############print Failed files(%d): %(len(failedNamesList))for i SEO靠我in range(len(failedNamesList)):print + failedNamesList[i]

某些乱码文件名过长(多为.mht文件),os.renames()时会触发WindowsSEO靠我Error[3]异常,如:

事实上,在资源管理器里打开这些文件时,会提示"源路径过长":

上述代码可有效地恢复原始乱码目录和文件名。当时的运行截图如下:

以及

经初步检验,更名成功。此时可通过tree命令生成SEO靠我生成目录树,与原先保存的文件列表对比。遗憾的是,两者树状列表顺序不同,无法直接对比。当然,如果够闲,也可以编程比照。

四. 后记

本文所述的乱码恢复实践其实是种"摸着石头过河(trial and erroSEO靠我r)"的过程。如果当初先研究字符编码,而不是左右开弓,应该会避免不少弯路。当然论及性价比,孰优孰劣,亦未可知。

最后,关于Python字符编码基础知识,作者将在后续文章中加以说明,同时澄清本文一些谬误之SEO靠我处。脸皮薄,就不说"敬请期待"了~~
“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2