一个讨厌的编码问题
编码问题很讨厌。昨天就碰到了一个,花了几个小时才解决。
使用DotNetZip这个库自动打包文件夹,原来的代码是:
1 2 3 4 5 6 | var dir = new DirectoryInfo( @"c:\foo" ); using (ZipFile zip = new ZipFile(Encoding.UTF8)) { var entry = zip.AddDirectory(dir.FullName, dir.Name); zip.Save(Path.Combine(path, dir.Name + ".zip" )); } |
看上去很正常,也似乎能work,成功打包,用7-zip打开,里面的中文文件夹也显示正常。
但是,如果是用7-zip手工打包的zip,在资源管理器里双击可以看到里面的文件夹。而这个用代码生成的zip,如果打包进去的是中文文件夹,双击却显示空白。这似乎不成问题,但因为我打包的都是pdg文件(某电子书格式文件,不懂的一搜便知),本来直接把zip后缀改成uvz,便可用一个叫做UnicornViewer的软件阅读,而这个用代码生成的zip,改名后却用UnicornViewer打不开,提示打开失败。
英文文件夹可以,中文文件夹不行,似乎很可能是“编码问题”。
用下面的代码查看zip的属性:
1 2 3 4 5 6 7 8 9 10 | using (ZipFile zip = ZipFile.Read( "foo.zip" ))) { foreach (ZipEntry entry in zip) { if (entry.IsDirectory) { //这里加上断点,以便查看entry的属性 break ; } } } |
结果发现,用7-zip打包的文件,entry的AlternateEncoding显示为IBM437,FileName属性显示为乱码,比如“世界第一位六冠王赵国荣实战专辑”,显示为“╩└╜τ╡┌╥╗╬╗┴∙╣┌═⌡╒╘╣·╚┘╩╡╒╜╫¿╝¡”。
查了很多资料,调试了半天,最后终于理解了,原来这是用IBM437去解码gb2312/gbk编码的字符串的结果。理解了这一点,修改代码:
1 2 3 4 5 6 7 8 9 | var dir = new DirectoryInfo( @"c:\foo" ); byte [] bytes = Encoding.GetEncoding( "gb2312" ).GetBytes(dir.Name.ToCharArray()); string newName = Encoding.GetEncoding( "IBM437" ).GetString(bytes); using (ZipFile zip = new ZipFile(Encoding.UTF8)) { zip.AlternateEncoding = Encoding.GetEncoding( "IBM437" ); var entry = zip.AddDirectory(dir.FullName, newName); zip.Save(Path.Combine(path, dir.Name + ".zip" )); } |
测试通过。
以前碰到的编码问题,多是将乱码转成正常显示的字符,这次却要故意生成“乱码”才能工作正常,呵呵。管他呢,反正it just works。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律