将文件从一个 Zip 文件复制到另一个
Copy files from one Zip file to another
在某些情况下,我正在将文件从一个 zip 文件复制到另一个。我想知道是否有比我想出的更好的方法:
using FileStream sourceFileStream = new FileStream(source.FileName, FileMode.Open);
using FileStream targetFileStream = new FileStream(target.FileName, FileMode.Open, FileAccess.ReadWrite);
using ZipArchive sourceZip = new ZipArchive(sourceFileStream, ZipArchiveMode.Read);
using ZipArchive targetZip = new ZipArchive(targetFileStream, ZipArchiveMode.Update);
ZipArchiveEntry sourceEntry = sourceZip.GetEntry(filePathInArchive);
if (sourceEntry == null)
return;
ZipArchiveEntry targetEntry = targetZip.GetEntry(filePathInArchive);
if (targetEntry != null)
targetEntry.Delete();
targetZip.CreateEntry(filePathInArchive);
targetEntry = targetZip.GetEntry(filePathInArchive);
if (targetEntry != null)
{
Stream writer = targetEntry.Open();
Stream reader = sourceEntry.Open();
int b;
do
{
b = reader.ReadByte();
writer.WriteByte((byte)b);
} while (b != -1);
writer.Close();
reader.Close();
}
提示和建议将不胜感激。
您可以通过打开其流并使用 Stream.CopyTo
将源条目内容写入目标条目来迭代源存档中的每个条目。
从 C# 8.0
开始,它看起来紧凑且工作正常:
static void CopyZipEntries(string sourceZipFile, string targetZipFile)
{
using FileStream sourceFS = new FileStream(sourceZipFile, FileMode.Open);
using FileStream targetFS = new FileStream(targetZipFile, FileMode.Open);
using ZipArchive sourceZIP = new ZipArchive(sourceFS, ZipArchiveMode.Read, false, Encoding.GetEncoding(1251));
using ZipArchive targetZIP = new ZipArchive(targetFS, ZipArchiveMode.Update, false, Encoding.GetEncoding(1251));
foreach (ZipArchiveEntry sourceEntry in sourceZIP.Entries)
{
// 'is' is replacement for 'null' check
if (targetZIP.GetEntry(sourceEntry.FullName) is ZipArchiveEntry existingTargetEntry)
existingTargetEntry.Delete();
using (Stream targetEntryStream = targetZIP.CreateEntry(sourceEntry.FullName).Open())
{
sourceEntry.Open().CopyTo(targetEntryStream);
}
}
}
使用早于 C# 8.0
的版本也可以正常工作,但需要更多的括号:
static void CopyZipEntries(string sourceZipFile, string targetZipFile)
{
using (FileStream sourceFS = new FileStream(sourceZipFile, FileMode.Open))
{
using (FileStream targetFS = new FileStream(targetZipFile, FileMode.Open))
{
using (ZipArchive sourceZIP = new ZipArchive(sourceFS, ZipArchiveMode.Read, false, Encoding.GetEncoding(1251)))
{
using (ZipArchive targetZIP = new ZipArchive(targetFS, ZipArchiveMode.Update, false, Encoding.GetEncoding(1251)))
{
foreach (ZipArchiveEntry sourceEntry in sourceZIP.Entries)
{
if (targetZIP.GetEntry(sourceEntry.FullName) is ZipArchiveEntry existingTargetEntry)
{
existingTargetEntry.Delete();
}
using (Stream target = targetZIP.CreateEntry(sourceEntry.FullName).Open())
{
sourceEntry.Open().CopyTo(target);
}
}
}
}
}
}
}
对于单个指定的文件副本,只需将 foreach
循环的底部部分替换为 if 条件:
static void CopyZipEntry(string fileName, string sourceZipFile, string targetZipFile)
{
// ...
// It means specified file exists in source ZIP-archive
// and we can copy it to target ZIP-archive
if (sourceZIP.GetEntry(fileName) is ZipArchiveEntry sourceEntry)
{
if (targetZIP.GetEntry(sourceEntry.FullName) is ZipArchiveEntry existingTargetEntry)
existingTargetEntry.Delete();
using (Stream targetEntryStream = targetZIP.CreateEntry(sourceEntry.FullName).Open())
{
sourceEntry.Open().CopyTo(targetEntryStream);
}
}
else
MessageBox.Show("Source ZIP-archive doesn't contains file " + fileName);
}
感谢到目前为止的输入,我清理并改进了代码。我觉得这样看起来更干净可靠。
//Making sure files exist etc before this part...
string filePathInArchive = source.GetFilePath(fileId);
using FileStream sourceFileStream = new FileStream(source.FileName, FileMode.Open);
using FileStream targetFileStream = new FileStream(target.FileName, FileMode.Open, FileAccess.ReadWrite);
using ZipArchive sourceZip = new ZipArchive(sourceFileStream, ZipArchiveMode.Read, false );
using ZipArchive targetZip = new ZipArchive(targetFileStream, ZipArchiveMode.Update, false);
ZipArchiveEntry sourceEntry = sourceZip.GetEntry(filePathInArchive);
if (sourceEntry != null)
{
if (targetZip.GetEntry(filePathInArchive) is { } existingTargetEntry)
{
existingTargetEntry.Delete();
}
using var targetEntryStream = targetZip.CreateEntry(sourceEntry.FullName).Open();
sourceEntry.Open().CopyTo(targetEntryStream);
}
在某些情况下,我正在将文件从一个 zip 文件复制到另一个。我想知道是否有比我想出的更好的方法:
using FileStream sourceFileStream = new FileStream(source.FileName, FileMode.Open);
using FileStream targetFileStream = new FileStream(target.FileName, FileMode.Open, FileAccess.ReadWrite);
using ZipArchive sourceZip = new ZipArchive(sourceFileStream, ZipArchiveMode.Read);
using ZipArchive targetZip = new ZipArchive(targetFileStream, ZipArchiveMode.Update);
ZipArchiveEntry sourceEntry = sourceZip.GetEntry(filePathInArchive);
if (sourceEntry == null)
return;
ZipArchiveEntry targetEntry = targetZip.GetEntry(filePathInArchive);
if (targetEntry != null)
targetEntry.Delete();
targetZip.CreateEntry(filePathInArchive);
targetEntry = targetZip.GetEntry(filePathInArchive);
if (targetEntry != null)
{
Stream writer = targetEntry.Open();
Stream reader = sourceEntry.Open();
int b;
do
{
b = reader.ReadByte();
writer.WriteByte((byte)b);
} while (b != -1);
writer.Close();
reader.Close();
}
提示和建议将不胜感激。
您可以通过打开其流并使用 Stream.CopyTo
将源条目内容写入目标条目来迭代源存档中的每个条目。
从 C# 8.0
开始,它看起来紧凑且工作正常:
static void CopyZipEntries(string sourceZipFile, string targetZipFile)
{
using FileStream sourceFS = new FileStream(sourceZipFile, FileMode.Open);
using FileStream targetFS = new FileStream(targetZipFile, FileMode.Open);
using ZipArchive sourceZIP = new ZipArchive(sourceFS, ZipArchiveMode.Read, false, Encoding.GetEncoding(1251));
using ZipArchive targetZIP = new ZipArchive(targetFS, ZipArchiveMode.Update, false, Encoding.GetEncoding(1251));
foreach (ZipArchiveEntry sourceEntry in sourceZIP.Entries)
{
// 'is' is replacement for 'null' check
if (targetZIP.GetEntry(sourceEntry.FullName) is ZipArchiveEntry existingTargetEntry)
existingTargetEntry.Delete();
using (Stream targetEntryStream = targetZIP.CreateEntry(sourceEntry.FullName).Open())
{
sourceEntry.Open().CopyTo(targetEntryStream);
}
}
}
使用早于 C# 8.0
的版本也可以正常工作,但需要更多的括号:
static void CopyZipEntries(string sourceZipFile, string targetZipFile)
{
using (FileStream sourceFS = new FileStream(sourceZipFile, FileMode.Open))
{
using (FileStream targetFS = new FileStream(targetZipFile, FileMode.Open))
{
using (ZipArchive sourceZIP = new ZipArchive(sourceFS, ZipArchiveMode.Read, false, Encoding.GetEncoding(1251)))
{
using (ZipArchive targetZIP = new ZipArchive(targetFS, ZipArchiveMode.Update, false, Encoding.GetEncoding(1251)))
{
foreach (ZipArchiveEntry sourceEntry in sourceZIP.Entries)
{
if (targetZIP.GetEntry(sourceEntry.FullName) is ZipArchiveEntry existingTargetEntry)
{
existingTargetEntry.Delete();
}
using (Stream target = targetZIP.CreateEntry(sourceEntry.FullName).Open())
{
sourceEntry.Open().CopyTo(target);
}
}
}
}
}
}
}
对于单个指定的文件副本,只需将 foreach
循环的底部部分替换为 if 条件:
static void CopyZipEntry(string fileName, string sourceZipFile, string targetZipFile)
{
// ...
// It means specified file exists in source ZIP-archive
// and we can copy it to target ZIP-archive
if (sourceZIP.GetEntry(fileName) is ZipArchiveEntry sourceEntry)
{
if (targetZIP.GetEntry(sourceEntry.FullName) is ZipArchiveEntry existingTargetEntry)
existingTargetEntry.Delete();
using (Stream targetEntryStream = targetZIP.CreateEntry(sourceEntry.FullName).Open())
{
sourceEntry.Open().CopyTo(targetEntryStream);
}
}
else
MessageBox.Show("Source ZIP-archive doesn't contains file " + fileName);
}
感谢到目前为止的输入,我清理并改进了代码。我觉得这样看起来更干净可靠。
//Making sure files exist etc before this part...
string filePathInArchive = source.GetFilePath(fileId);
using FileStream sourceFileStream = new FileStream(source.FileName, FileMode.Open);
using FileStream targetFileStream = new FileStream(target.FileName, FileMode.Open, FileAccess.ReadWrite);
using ZipArchive sourceZip = new ZipArchive(sourceFileStream, ZipArchiveMode.Read, false );
using ZipArchive targetZip = new ZipArchive(targetFileStream, ZipArchiveMode.Update, false);
ZipArchiveEntry sourceEntry = sourceZip.GetEntry(filePathInArchive);
if (sourceEntry != null)
{
if (targetZip.GetEntry(filePathInArchive) is { } existingTargetEntry)
{
existingTargetEntry.Delete();
}
using var targetEntryStream = targetZip.CreateEntry(sourceEntry.FullName).Open();
sourceEntry.Open().CopyTo(targetEntryStream);
}