C# ZipArchive 路径中的非法字符

C# ZipArchive Illegal characters in path

给定以下代码:

using (var data = new MemoryStream(bytes))
using(var archive = new ZipArchive(data))
{
    foreach (var entry in archive.Entries)
    {
        entry.FullName.Log();
    }
    ...

抛出的异常是:

Illegal characters in path.

foreach 行。

如何找出受影响的条目?每当我尝试访问条目时,它都会抛出异常。这个特定的存档似乎是从 Mac 创建的,因为它包含 _MACOSX 文件夹。

堆栈跟踪:

[ArgumentException: Illegal characters in path.]
   System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional) +14351233
   System.IO.Path.GetFileName(String path) +29
   System.IO.Compression.ZipHelper.EndsWithDirChar(String test) +9
   System.IO.Compression.ZipArchiveEntry.set_FullName(String value) +93
   System.IO.Compression.ZipArchiveEntry..ctor(ZipArchive archive, ZipCentralDirectoryFileHeader cd) +228
   System.IO.Compression.ZipArchive.ReadCentralDirectory() +172
   System.IO.Compression.ZipArchive.get_Entries() +36

同意评论。您确定您的文件完好无损并且来自兼容平台吗?如果您使用例如打开您的存档会发生什么WinRar ?

我之前测试了下面的代码,并像您一样使用内存流成功地修改了它,我相信您的版本应该也能正常工作..

    [Test]
    public void TestZipper()
    {
        using (var dataFromFile = new FileStream("d:\lx\MyZip.ZIP", FileMode.Open))
        {
            var dataInMemory = new MemoryStream();
            dataFromFile.CopyTo(dataInMemory);
            using (var archive = new ZipArchive(dataInMemory))
            {
                foreach (var entry in archive.Entries)
                {
                    Debug.WriteLine(entry.FullName);
                }
                Assert.That(MyZipListIsComplete(archive.Entries));
            }
        }
    }

您的异常被抛出,因为 ZipArchive.Entries 试图读取 zip 中央目录以便为每个条目构造一个 ZipArchiveEntryZipArchiveEntry 构造函数正在调用 Path.GetFileName,后者调用 Path.CheckInvalidPathChars,如果路径包含 [=15=].

,则抛出

尽管在读取中央目录的过程中出现异常会使 ZipArchive 留下部分填充的条目列表,但似乎没有任何方法可以在不触发读取的情况下读取它中央目录,除非你使用调试器/反射读取 _entries_entriesCollection。这将告诉您哪些条目成功了,这可能会缩小失败的条目的范围。如果您要达到这些长度,调试 .Entries 调用会准确告诉您哪个条目失败。

看起来在不同平台上以不同方式对待路径的相关问题是 recognised in 2015, and as part of that a change was made to get the file name without calling Path.CheckInvalidPathChars,这应该可以避免该问题(如果您尝试将此条目写入文件Windows,但至少 .Entries 不应该抛出)。不幸的是,这仅在 .NET Core 中引入。