如何在 C# 中验证多部分压缩(即 zip)文件是否包含所有部分?
How to validate multi part compressed (i.e zip) files have all parts or not in C#?
我想验证像 Zip 这样的多部分压缩文件,因为当压缩文件缺少任何部分时会引发错误,但我想在提取之前验证它,不同的软件会创建不同的命名结构。
我还参考了一个 DotNetZip 相关问题。
以下截图来自7z软件
第二个屏幕截图来自 C# 的 DotNetZip。
还有一件事是我也想测试它是否也像 7z 软件一样损坏。请参考下面的截图了解我的要求。
请帮我解决这些问题。
我不确定您是否能够看到快照中显示的确切错误。但我有一个代码可以帮助您确定多部分文件是否可读。
我用过nuget包CombinationStream。
如果流不可读,ZipArchive 构造函数将抛出 ArgumentException
或 InvalidDataException
。
代码如下:
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;
}
我不确定这是否是您要查找的内容,或者您需要错误中的更多详细信息。但希望这可以帮助您解决问题。
根据您的评论,我了解到您遇到的问题是识别文件(获取属于同一部分的列表)。您可以获得文件列表,例如
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;
}
根据您的需要对其进行修改 - 它将 return 包含 "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; });
};
我想验证像 Zip 这样的多部分压缩文件,因为当压缩文件缺少任何部分时会引发错误,但我想在提取之前验证它,不同的软件会创建不同的命名结构。
我还参考了一个 DotNetZip 相关问题。
以下截图来自7z软件
第二个屏幕截图来自 C# 的 DotNetZip。
还有一件事是我也想测试它是否也像 7z 软件一样损坏。请参考下面的截图了解我的要求。
请帮我解决这些问题。
我不确定您是否能够看到快照中显示的确切错误。但我有一个代码可以帮助您确定多部分文件是否可读。
我用过nuget包CombinationStream。
如果流不可读,ZipArchive 构造函数将抛出 ArgumentException
或 InvalidDataException
。
代码如下:
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;
}
我不确定这是否是您要查找的内容,或者您需要错误中的更多详细信息。但希望这可以帮助您解决问题。
根据您的评论,我了解到您遇到的问题是识别文件(获取属于同一部分的列表)。您可以获得文件列表,例如
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;
}
根据您的需要对其进行修改 - 它将 return 包含 "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; });
};