在 C# 中解压数据
我是 C# 新手,正在编写一个简单的 Web 服务。它获取 zip 文件并将其解压缩到文件系统中。在 C# 代码中是:
[WebMethod]
public String SetZip(string device_id, string file)
{
if (device_id == null || device_id.Length == 0)
{
return "10;no auth data";
}
StringBuilder output = new StringBuilder();
if (direcory == null)
{
return output.ToString();
}
string dirname = "c:\\temp\\" + direcory + "\\";
if (!System.IO.Directory.Exists(dirname))
{
System.IO.Directory.CreateDirectory(dirname);
}
string filename = dirname + "file1.txt";
string text = UnZipStr(Convert.FromBase64String(file));
File.WriteAllText(filename, text);
output.AppendLine("0;done");
return output.ToString();
}
public static string UnZipStr(byte[] input)
{
using (MemoryStream memstream = new MemoryStream())
{
using (MemoryStream inputStream = new MemoryStream(input))
{
using (DeflateStream gzip =
new DeflateStream(inputStream, CompressionMode.Decompress))
{
using (StreamReader reader =
new StreamReader(gzip, System.Text.Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
}
}
并从 java 代码发送 zip 数据:
void callService(byte[] xmlData) {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("device_id", AGENT);
Deflater deflater = new Deflater();
deflater.setInput(xmlData);
deflater.finish();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
while (!deflater.finished()) {
int byteCount = deflater.deflate(buf);
baos.write(buf, 0, byteCount);
}
deflater.end();
byte[] compressedBytes = baos.toByteArray();
request.addPropertyIfValue("file", org.kobjects.base64.Base64.encode(compressedBytes));...}
在 C# 代码中,从 StreamReader 读取数据时出现异常
SoapFault - faultcode: 'soap:Server' faultstring: 'System.Web.Services.Protocols.SoapException: ---> InvalidDataException: Block length does not correspond to the complement.
System.IO.Compression.Inflater.DecodeUncompressedBlock(Boolean& end_of_block)
System.IO.Compression.Inflater.Decode()
System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)
System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)
System.IO.StreamReader.ReadBuffer()
System.IO.StreamReader.ReadToEnd()
Service.UnZipStr(Byte[] input) в c:\inetpub\wwwroot\WebSite\App_Code\Service.cs: at 94
Service.SetZip(String device_id, String file) в c:\inetpub\wwwroot\WebSite\App_Code \Service.cs: at 73
我做错了什么?
I'm new at C#, I writing a simple web service. It takes the zip file and decompress it in file system. In C# code is:
[WebMethod]
public String SetZip(string device_id, string file)
{
if (device_id == null || device_id.Length == 0)
{
return "10;no auth data";
}
StringBuilder output = new StringBuilder();
if (direcory == null)
{
return output.ToString();
}
string dirname = "c:\\temp\\" + direcory + "\\";
if (!System.IO.Directory.Exists(dirname))
{
System.IO.Directory.CreateDirectory(dirname);
}
string filename = dirname + "file1.txt";
string text = UnZipStr(Convert.FromBase64String(file));
File.WriteAllText(filename, text);
output.AppendLine("0;done");
return output.ToString();
}
public static string UnZipStr(byte[] input)
{
using (MemoryStream memstream = new MemoryStream())
{
using (MemoryStream inputStream = new MemoryStream(input))
{
using (DeflateStream gzip =
new DeflateStream(inputStream, CompressionMode.Decompress))
{
using (StreamReader reader =
new StreamReader(gzip, System.Text.Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
}
}
And send zip data from java code:
void callService(byte[] xmlData) {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("device_id", AGENT);
Deflater deflater = new Deflater();
deflater.setInput(xmlData);
deflater.finish();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
while (!deflater.finished()) {
int byteCount = deflater.deflate(buf);
baos.write(buf, 0, byteCount);
}
deflater.end();
byte[] compressedBytes = baos.toByteArray();
request.addPropertyIfValue("file", org.kobjects.base64.Base64.encode(compressedBytes));...}
At C# code I have Exception when read data from StreamReader
SoapFault - faultcode: 'soap:Server' faultstring: 'System.Web.Services.Protocols.SoapException: ---> InvalidDataException: Block length does not correspond to the complement.
System.IO.Compression.Inflater.DecodeUncompressedBlock(Boolean& end_of_block)
System.IO.Compression.Inflater.Decode()
System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)
System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)
System.IO.StreamReader.ReadBuffer()
System.IO.StreamReader.ReadToEnd()
Service.UnZipStr(Byte[] input) в c:\inetpub\wwwroot\WebSite\App_Code\Service.cs: at 94
Service.SetZip(String device_id, String file) в c:\inetpub\wwwroot\WebSite\App_Code \Service.cs: at 73
What I'm doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
编辑:我一直在研究,有一种方法可以从 Java 生成 C# 识别的 DEFLATE 格式数据:您必须使用
Deflater(int,boolean)
构造函数。因此,将您的 Java 代码更改为:原因是默认情况下 deflater 会发出 ZLIB 标头和校验和,这是 C#
DeflateStream
所不期望的。看来 Java 和 C# 在“deflate”压缩算法的确切种类上并不一致,但根据我的测试,“gzip”应该可以工作:
这在 Java 中压缩
xmlData
:这解压缩
input在 C# 中:
Edit: I've been digging around and there is a way to generate DEFLATE format data from Java that C# recognizes: you have to use the
Deflater(int,boolean)
constructor. So change your Java code to:The reason is that by default the deflater emits a ZLIB header and checksum, which the C#
DeflateStream
doesn't expect.It seems that Java and C# don't agree on the exact variety of "deflate" compression algorithm, but by my tests "gzip" should work:
This compresses
xmlData
in Java:This decompress
input
in C#:看起来@Joni Salonen 已经给出了 deflate 问题的答案,所以我想添加一些关于架构的内容。要隔离问题,您应该将这两个问题分开。首先,您需要删除一个压缩文件。然后你需要给它放气。然后,分别关注问题领域。您稍后可以随时“管道”这两个问题。
顺便说一句,在许多情况下拥有原始 zip 文件很有用。当某些事情没有按计划进行时,尤其是当事情没有按计划进行时,它就成为一个安全网。如果您只有一次捕获该文件的机会。
It looks like @Joni Salonen has given an answer to the deflate problem, so I want to add a bit about architecture. To isolate the issue, you should separate the two concerns. First, you need to drop a zipped file. Then you need to deflate it. Then, focus on the problem area separately. You can always "pipeline" the two concerns later.
BTW, it is useful to have the raw zip file in many instances. It becomes a safety net when something does not work as planned, esp. if you only have one chance to capture the file.