我正在开发的应用程序需要将xml文件压缩为zip文件,并通过http请求将它们发送到Web服务。因为我不需要保留zip文件,所以我只是在内存中执行压缩。 Web服务拒绝了我的请求,因为zip文件显然格式不正确。
我知道this question中有一个完美无缺的解决方案,但它使用了StreamWriter
。我的解决方案的问题是StreamWriter
需要编码或假定UTF-8
,我不需要知道xml文件的插入。我只需要从这些文件中读取字节,并将它们存储在一个zip文件中,无论它们使用何种编码。
因此,要清楚,这个问题与编码无关,因为我不需要将字节转换为文本或对话框。我只需要压缩byte[]
。
我使用下一个代码来测试我的zip文件格式错误:
static void Main(string[] args)
{
Encoding encoding = Encoding.GetEncoding("ISO-8859-1");
string xmlDeclaration = "<?xml version=\"1.0\" encoding=\"" + encoding.WebName.ToUpperInvariant() + "\"?>";
string xmlBody = "<Test>ª!\"·$%/()=?¿\\|@#~€¬'¡º</Test>";
string xmlContent = xmlDeclaration + xmlBody;
byte[] bytes = encoding.GetBytes(xmlContent);
string fileName = "test.xml";
string zipPath = @"C:\Users\dgarcia\test.zip";
Test(bytes, fileName, zipPath);
}
static void Test(byte[] bytes, string fileName, string zipPath)
{
byte[] zipBytes;
using (var memoryStream = new MemoryStream())
using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: false))
{
var zipEntry = zipArchive.CreateEntry(fileName);
using (Stream entryStream = zipEntry.Open())
{
entryStream.Write(bytes, 0, bytes.Length);
}
//Edit: as the accepted answer states, the problem is here, because i'm reading from the memoryStream before disposing the zipArchive.
zipBytes = memoryStream.ToArray();
}
using (var fileStream = new FileStream(zipPath, FileMode.OpenOrCreate))
{
fileStream.Write(zipBytes, 0, zipBytes.Length);
}
}
如果我尝试打开该文件,我会收到&#34;意外的文件结尾&#34;错误。显然,Web服务正确地报告了格式错误的zip文件。到目前为止我尝试了什么:
entryStream
。entryStream
。entryStream
。请注意,如果我直接从zipArchive
打开fileStream
,则会形成没有错误的zip文件。但是,fileStream
只是作为测试,我需要在内存中创建我的zip文件。
答案 0 :(得分:5)
您试图过早地从MemoryStream
获取字节,ZipArchive
还没有写出它们。相反,这样做:
using (var memoryStream = new MemoryStream()) {
// note "leaveOpen" true, to not dispose memoryStream too early
using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: true)) {
var zipEntry = zipArchive.CreateEntry(fileName);
using (Stream entryStream = zipEntry.Open()) {
entryStream.Write(bytes, 0, bytes.Length);
}
}
// now, after zipArchive is disposed - all is written to memory stream
zipBytes = memoryStream.ToArray();
}
答案 1 :(得分:0)
如果使用内存流加载文本,则可以控制编码类型,并且它可以在WCF服务中运行。这是我目前使用的实现,它适用于我的WCF服务
private byte[] Zip(string text)
{
var bytes = Encoding.UTF8.GetBytes(text);
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream())
{
using (var gs = new GZipStream(mso, CompressionMode.Compress))
{
CopyTo(msi, gs);
}
return mso.ToArray();
}
}
private string Unzip(byte[] bytes)
{
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream())
{
using (var gs = new GZipStream(msi, CompressionMode.Decompress))
{
CopyTo(gs, mso);
}
return Encoding.UTF8.GetString(mso.ToArray());
}
}