Delphi TZipFile 提取零字节文件
Delphi TZipFile extracts zero byte files
使用 Delphi XE2 和本机 TZipFile 我尝试提取下载的 zip 文件的内容(其中包含 2 个压缩的 XML 文件)并且它总是提取零字节文件。
文件正在被 C# 代码压缩,如下所示:
var zipFile = new ZipFile();
foreach (Tuple<string, string> t in filesMeta) {
zipFile.AddFile(string.Format("{0}{1}", StaticVariables.WebServerFileStorage, t.Item2), "").FileName = t.Item1 + ".xml";
}
response.Clear();
response.ContentType = "application/zip";
zipFile.Save(response.OutputStream);
response.End();
Delphi提取码是这样的:
zipFile := TZipFile.Create;
try
filename := 'C:\testf52480-ec87-4169-a820-0a65bc4ad952.zip';
if zipFile.IsValid(filename) then begin
zipFile.Open(filename, zmRead);
zipFile.ExtractAll('C:\test\');
end;
finally
zipFile.Free;
end;
我什至尝试使用 TStream 作为源而不是磁盘上的文件。这实际上是我想要做的,因为 zip 文件是从 Web 服务器下载到 TStream 中的。我尝试使用 TZipFile 的重载打开方法打开流来提取数据。
这让我得到了零字节文件,所以我将 zip 文件保存到磁盘并尝试从磁盘打开文件并提取。提取相同的零字节文件。
我什至尝试使用 class 方法从磁盘上的 zip 文件中提取文件:
System.Zip.TZipFile.ExtractZipFile(filename, 'C:\Test\');
提取相同的零字节文件。
zip 文件有效,XML 2 个压缩文件可以通过 Windows 7 本机文件处理和 7-Zip 正确提取。
现在有些疯狂...
无奈之下我试着看看ExtractToFile()程序是什么
David Heffernan 在这个关于 extracting a zip to a stream would do so 的问题中想出了我试过这样使用它:
var x : integer;
var fileCount : integer;
var fileNames : TArray<string>;
begin
zipFile := TZipFile.Create;
try
filename := 'C:\testf52480-ec87-4169-a820-0a65bc4ad952.zip';
if zipFile.IsValid(filename) then begin
zipFile.Open(filename, zmRead);
fileCount := zipFile.FileCount;
fileNames := copy(zipFile.FileNames, 0, MaxInt);
zipFile.Close;
for x := 0 to fileCount-1 do begin
// Use David Heffernan's stream procedure
ExtractToFile(filename, x, 'C:\test\' + fileNames[x]);
end;
end;
finally
zipFile.Free;
end;
end;
David 的程序按预期将文件提取到磁盘!什么鬼???
我真的很困惑为什么复杂的提取方法有效而简单的提取方法无效。如果必须的话,我会使用 David 的例子,但如果可能的话,我更愿意让正常的提取工作。
欢迎任何想法。
干杯!
TJ
TL;DR:我的问题的解决方案是外部组件。 Zip Forge(或缩写)
继续阅读了解详情。
除了保存文件并使用 David 的函数重新打开它的迂回方式外,我没有尝试任何其他方法。虽然这会奏效,但它不是最佳选择,因为它要求我先将下载的文件保存到磁盘并重新打开以进行提取,然后删除 zip 文件。我的目标是只打开下载的流并将文件直接提取到磁盘。一次写入磁盘,没有临时文件。
我们甚至尝试了两个不同的 C# 库来压缩文件,并且都在流式数据上给出了相同的结果。 Delphi TZipFile 组件无法处理它。
事实证明我们有 ZipForge 的许可证,我已经忘记了,因为我已经很久没有使用它了,它可以处理来自 C# Web 服务器的下载流并成功提取文件。
作为参考,我还尝试了 Abbrevia 组件版本 5.2,它也成功地从流中提取了文件。
希望这对其他人有所帮助。
感谢 David 和 Uwe 的所有建议。
干杯!
TJ
我遇到了同样的问题。
TZipFile 的源代码显示 TStream 传递到读取函数 returns 整个 zip 文件,位置设置为您想要的文件名的开头。所以不要倒带。对于 TZipHeader 中给出的未压缩长度,只需复制或使用 TStream 执行您想要的操作。
ZipStream := TStream.Create;
ZipFile.Read(MyFileName, ZipStream, ZipHeader);
//leave ZipStream pointer where it is!!!
SomethingElse.LoadFromStream(ZipStream, ZipHeader.UncompressedSize);
ZipStream.Free;
在我看来,TZipFile 应该只加载所请求的 ZipStream。如果不先查看 TZipFile 源代码,这种实现方式并不直观。
使用 Delphi XE2 和本机 TZipFile 我尝试提取下载的 zip 文件的内容(其中包含 2 个压缩的 XML 文件)并且它总是提取零字节文件。
文件正在被 C# 代码压缩,如下所示:
var zipFile = new ZipFile();
foreach (Tuple<string, string> t in filesMeta) {
zipFile.AddFile(string.Format("{0}{1}", StaticVariables.WebServerFileStorage, t.Item2), "").FileName = t.Item1 + ".xml";
}
response.Clear();
response.ContentType = "application/zip";
zipFile.Save(response.OutputStream);
response.End();
Delphi提取码是这样的:
zipFile := TZipFile.Create;
try
filename := 'C:\testf52480-ec87-4169-a820-0a65bc4ad952.zip';
if zipFile.IsValid(filename) then begin
zipFile.Open(filename, zmRead);
zipFile.ExtractAll('C:\test\');
end;
finally
zipFile.Free;
end;
我什至尝试使用 TStream 作为源而不是磁盘上的文件。这实际上是我想要做的,因为 zip 文件是从 Web 服务器下载到 TStream 中的。我尝试使用 TZipFile 的重载打开方法打开流来提取数据。
这让我得到了零字节文件,所以我将 zip 文件保存到磁盘并尝试从磁盘打开文件并提取。提取相同的零字节文件。
我什至尝试使用 class 方法从磁盘上的 zip 文件中提取文件:
System.Zip.TZipFile.ExtractZipFile(filename, 'C:\Test\');
提取相同的零字节文件。
zip 文件有效,XML 2 个压缩文件可以通过 Windows 7 本机文件处理和 7-Zip 正确提取。
现在有些疯狂...
无奈之下我试着看看ExtractToFile()程序是什么 David Heffernan 在这个关于 extracting a zip to a stream would do so 的问题中想出了我试过这样使用它:
var x : integer;
var fileCount : integer;
var fileNames : TArray<string>;
begin
zipFile := TZipFile.Create;
try
filename := 'C:\testf52480-ec87-4169-a820-0a65bc4ad952.zip';
if zipFile.IsValid(filename) then begin
zipFile.Open(filename, zmRead);
fileCount := zipFile.FileCount;
fileNames := copy(zipFile.FileNames, 0, MaxInt);
zipFile.Close;
for x := 0 to fileCount-1 do begin
// Use David Heffernan's stream procedure
ExtractToFile(filename, x, 'C:\test\' + fileNames[x]);
end;
end;
finally
zipFile.Free;
end;
end;
David 的程序按预期将文件提取到磁盘!什么鬼???
我真的很困惑为什么复杂的提取方法有效而简单的提取方法无效。如果必须的话,我会使用 David 的例子,但如果可能的话,我更愿意让正常的提取工作。
欢迎任何想法。
干杯! TJ
TL;DR:我的问题的解决方案是外部组件。 Zip Forge(或缩写)
继续阅读了解详情。
除了保存文件并使用 David 的函数重新打开它的迂回方式外,我没有尝试任何其他方法。虽然这会奏效,但它不是最佳选择,因为它要求我先将下载的文件保存到磁盘并重新打开以进行提取,然后删除 zip 文件。我的目标是只打开下载的流并将文件直接提取到磁盘。一次写入磁盘,没有临时文件。
我们甚至尝试了两个不同的 C# 库来压缩文件,并且都在流式数据上给出了相同的结果。 Delphi TZipFile 组件无法处理它。
事实证明我们有 ZipForge 的许可证,我已经忘记了,因为我已经很久没有使用它了,它可以处理来自 C# Web 服务器的下载流并成功提取文件。
作为参考,我还尝试了 Abbrevia 组件版本 5.2,它也成功地从流中提取了文件。
希望这对其他人有所帮助。
感谢 David 和 Uwe 的所有建议。
干杯!
TJ
我遇到了同样的问题。
TZipFile 的源代码显示 TStream 传递到读取函数 returns 整个 zip 文件,位置设置为您想要的文件名的开头。所以不要倒带。对于 TZipHeader 中给出的未压缩长度,只需复制或使用 TStream 执行您想要的操作。
ZipStream := TStream.Create;
ZipFile.Read(MyFileName, ZipStream, ZipHeader);
//leave ZipStream pointer where it is!!!
SomethingElse.LoadFromStream(ZipStream, ZipHeader.UncompressedSize);
ZipStream.Free;
在我看来,TZipFile 应该只加载所请求的 ZipStream。如果不先查看 TZipFile 源代码,这种实现方式并不直观。