C# 使用 System.IO.Compression 解压后乱码

2023年10月12日 938点热度 0人点赞 0条评论
内容纲要

System.IO.Compression 是官方发布的一个由于解压缩的工具包,默认使用 utf8 编码解压缩文件。
但是在 Windows 上,编码比较混乱,如果文件或目录是中文名称,那么解压后会出现乱码,即使压缩包都是 UTF8 编码,.NET 解压也会出现乱码问题,所以需要使用 GB2312 编码解压。
但是 .NET 中默认是不包含 GB2312 编码的。

笔者说的不一定对,可能跟压缩文件也有关,总之, .NET 默认不支持 GB2312 编码,导致解压后中文文件名称乱码。

首先引入 System.Text.Encoding.CodePages 包。
然后随便找一个地方执行此段代码,注册更多编码集到 .NET 中。

// 注册更多字符编码
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

文章末尾列出所有可用的编码。

然后在解压目录时,指定编码:

ZipFile.ExtractToDirectory("aaa.zip", "解压目录", Encoding.GetEncoding("GB2312"), overwriteFiles: true);

判断压缩包文件名称编码的方法:

void Main()
{
    // 注册更多字符编码
    Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
    GetZipEncoding(@"d:\Downloads\aaa.zip").Dump();
}

static IEnumerable<Encoding> GetZipEncoding(string path)
{
    List<Encoding> es = new List<System.Text.Encoding>();
    // 打开压缩包文件
    using (ZipArchive archive = ZipFile.OpenRead(@"d:\Users\BSI\Downloads\Modules.zip"))
    {
        // 遍历压缩包中的每个文件
        foreach (ZipArchiveEntry entry in archive.Entries)
        {
            // 检测文件流的编码
            es.Add(GetEncoding(entry.FullName));
        }
    }
    return es;
}

// 判断字符串的编码
static Encoding GetEncoding(string str)
{
    byte[] bytes = Encoding.Default.GetBytes(str);

    if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
    {
        return Encoding.UTF8;
    }
    else if (bytes.Length >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE)
    {
        return Encoding.Unicode;
    }
    else if (bytes.Length >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF)
    {
        return Encoding.BigEndianUnicode;
    }
    else
    {
        return Encoding.Default;
    }
}

file

可以看到,压缩包所有文件都是 UTF8 编码,但是解压后:

    ZipFile.ExtractToDirectory(@"aaa.zip", "D:\\aaa");

file

这样解压会正常:

    ZipFile.ExtractToDirectory(@"aaa.zip", "D:\\aaa", Encoding.GetEncoding("GB2312"));

file

.NET 默认自带的编码:

utf-16
utf-16BE
utf-32
utf-32BE
us-ascii
iso-8859-1
utf-8

引入包后全部可用编码:

shift_jis
IBM860
ibm861
IBM880
DOS-862
IBM863
gb2312
IBM864
IBM865
cp866
koi8-u
IBM037
ibm869
IBM500
x-mac-icelandic
IBM01140
IBM01141
IBM01142
IBM273
IBM01143
IBM01144
IBM01145
windows-1250
IBM01146
windows-1251
IBM01147
macintosh
windows-1252
DOS-720
IBM277
IBM01148
x-mac-japanese
windows-1253
IBM437
IBM278
IBM01149
x-mac-chinesetrad
windows-1254
windows-1255
Johab
windows-1256
x-mac-arabic
windows-1257
x-mac-hebrew
windows-1258
x-mac-greek
x-mac-cyrillic
IBM00924
iso-8859-2
iso-8859-3
iso-8859-4
iso-8859-5
iso-8859-6
IBM870
iso-8859-7
iso-8859-8
iso-8859-9
x-mac-turkish
x-mac-croatian
windows-874
cp875
IBM420
ks_c_5601-1987
IBM423
IBM424
IBM280
IBM01047
IBM284
IBM285
x-mac-romanian
EUC-JP
x-mac-ukrainian
x-Europa
ibm737
x-IA5
big5
x-cp20936
x-IA5-German
x-IA5-Swedish
x-IA5-Norwegian
koi8-r
ibm775
iso-8859-13
IBM290
iso-8859-15
x-Chinese-CNS
ASMO-708
IBM297
x-mac-thai
x-cp20001
IBM905
x-Chinese-Eten
x-ebcdic-koreanextended
x-cp20003
x-cp20004
x-cp20005
ibm850
IBM-Thai
ibm852
IBM871
x-mac-ce
IBM855
cp1025
x-cp20949
ibm857
IBM00858
x-cp20261
IBM1026
x-cp20269
utf-16
utf-16BE
utf-32
utf-32BE
us-ascii
iso-8859-1
utf-8

痴者工良

高级程序员劝退师

文章评论