8

我想验证像 Zip 这样的多部分压缩文件,因为当压缩文件的任何部分丢失时,它会引发错误,但我想在提取之前对其进行验证,并且不同的软件会创建不同的命名结构。

我还参考了一个DotNetZip相关问题。

下面的截图来自 7z 软件。

在此处输入图像描述

第二个屏幕截图来自 C# 的 DotNetZip。

在此处输入图像描述

另一件事是,我还想测试它是否也已损坏或不像 7z 软件。请参阅下面的屏幕截图了解我的要求。

在此处输入图像描述

请帮我解决这些问题。

4

2 回答 2

2

我不确定您是否能够看到快照中显示的确切错误。但我有一个代码可以帮助您确定多部分文件是否可读。

我用过 nuget Package CombinationStream

ZipArchive构造函数抛出ArgumentExceptionInvalidDataException如果流不可读。

下面是代码:

public static bool IsZipValid()
{
    try
    {
        string basePath = @"C:\multi-part-zip\";
        List<string> files = new List<string> {
                                basePath + "somefile.zip.001",
                                basePath + "somefile.zip.002",
                                basePath + "somefile.zip.003",
                                basePath + "somefile.zip.004",
                                basePath + "somefile.zip.005",
                                basePath + "somefile.zip.006",
                                basePath + "somefile.zip.007",
                                basePath + "somefile.zip.008"
                            };

        using (var zipFile = new ZipArchive(new CombinationStream(files.Select(x => new FileStream(x, FileMode.Open) as Stream).ToList()), ZipArchiveMode.Read))
        {
            // Do whatever you want
        }
    }
    catch(InvalidDataException ex)
    {
        return false;
    }

    return true;
}

我不确定这是否是您要查找的内容,或者您​​需要错误中的更多详细信息。但是希望这可以帮助您解决问题。

于 2020-02-06T19:57:28.957 回答
1

从您的评论中,我了解到您遇到的问题是识别文件(获取属于一起的部分列表)。您可以获取文件列表,例如

List<string> files = System.IO.Directory.EnumerateFiles(@"D:\Zip\ForExtract\multipart\",
            "500mbInputData.*", SearchOption.TopDirectoryOnly).OrderBy(x => x).ToList();

或者你的第二种情况

List<string> files = System.IO.Directory.EnumerateFiles(@"D:\Zip\ForExtract\multipart\", 
            "500mbInputData.zip.*", SearchOption.TopDirectoryOnly).OrderBy(x => x).ToList();

然后使用你的文件列表CombinationStream。其余的代码看起来就像Manoj Choudhari写的那样。您也可以将带有通配符的路径和文件名放入参数中,因此我建议将以下参数添加到函数中:

public static bool IsZipValid(string basePath, string fileNameWithWildcard)
{
    try
    {
        List<string> files = System.IO.Directory.EnumerateFiles(
                    basePath, fileNameWithWildcard, 
                    SearchOption.TopDirectoryOnly).OrderBy(x => x).ToList();

        using (var zipFile = // ... rest is as Manoj wrote

并像这样使用它:

if (IsZipValid(@"D:\Zip\ForExtract\multipart\", "500mbInputData.*")) { // ... }

或者

if (IsZipValid(@"D:\Zip\ForExtract\multipart\", "500mbInputData.zip.*")) { // ... }

要找出基本路径中有哪些类型的文件,您可以编写一个辅助函数,例如

List<string> getZipFormat(string path)
{
    bool filesFound(string basePath, string pattern) => System.IO.Directory.EnumerateFiles(
            basePath, pattern, SearchOption.TopDirectoryOnly).Any();

    var isTar = filesFound(path, "*.tar.???");
    var isZip = filesFound(path, "*.z??");
    var is7Zip = filesFound(path, "*.7z.???");

    var result = new List<string>();
    if (isTar) result.Add("TAR");
    if (isZip) result.Add("ZIP");
    if (is7Zip) result.Add("7ZIP");
    return result;
}

根据您的需要对其进行修改 - 它将返回包含“TAR”、“ZIP”或“7ZIP”(或多个)的字符串列表,具体取决于与基目录中文件匹配的模式。

用法(多压缩格式检查示例):

    var isValid = true;
    var basePath = @"D:\Zip\ForExtract\multipart\";
    foreach(var fmt in getZipFormat(basePath))
    switch (fmt)
    {
    case "TAR": 
        isValid = isValid & IsZipValid(basePath, "500mbInputData.tar.*");
        break;
    case "ZIP":
        isValid = isValid & IsZipValid(basePath, "500mbInputData.zip.*");
        break;
    case "7ZIP":
        isValid = isValid & IsZipValid(basePath, "500mbInputData.7z.*");
        break;
    default: 
        break;
    }

注意:根据我的实验,尽管您的程序已经结束,但文件可能仍然打开 - 这意味着您下次运行代码时文件仍将被锁定。所以,我强烈建议明确关闭它们,比如

    var fStreams = files.Select(x => 
            new FileStream(x, FileMode.Open) as System.IO.Stream).ToList();
    using (var cStream = new CombinationStream(fStreams))
    using (var zipFile = new ZipArchive(cStream, ZipArchiveMode.Read))
    {
        // Do whatever you want...

        // ... but ensure you close the files
        fStreams.Select(s => { s.Close(); return s; });
    };
于 2020-02-11T08:29:36.640 回答