gpt4 book ai didi

c# - 如何在文件的一部分上使用 DeflateStream?

转载 作者:行者123 更新时间:2023-11-30 14:20:49 25 4
gpt4 key购买 nike

我正在研究 my other question 的解决方案它正在读取 PNG 的“zTXt” block 中的数据。我就在文件中定位 block ,并阅读 zTXt 的关键字。我无法读取 zTXt 的压缩部分。我以前从未使用过 DeflateStream 对象,并且在使用它时遇到了一些麻烦。读取时,似乎期望长度参数为“未压缩”字节。然而,就我而言,我只知道“压缩”字节中数据的长度。为了有希望地解决这个问题,我将所有需要解压缩的数据放入 MemoryStream 中,然后使用 DeflateStream 进行“读到结束”。现在这简直太棒了,除了它会抛出一个 InvalidDataException 并显示消息“ block 长度与其补码不匹配”。现在我不知道这意味着什么。可能出了什么问题?

block 的格式是 4 个字节的 ID(“zTXt”),一个大端 32 位 int 的数据长度,数据,最后是一个我现在忽略的 CRC32 校验和。

zTXt block 的格式首先是一个空终止(字符串作为关键字),然后是压缩方法的一个字节(始终为 0,DEFLATE 方法),其余数据是压缩文本。

我的方法接受一个新的 FileStream,并返回一个包含 zTXt 关键字和数据的字典。

现在是怪物:

public static List<KeyValuePair<string, string>> GetZtxt(FileStream stream)
{
var ret = new List<KeyValuePair<string, string>>();
try {
stream.Position = 0;
var br = new BinaryReader(stream, Encoding.ASCII);
var head = br.ReadBytes(8); // The header is the same for all PNGs.
if (!head.SequenceEqual(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A })) return null; // Not a PNG.
while (stream.Position < stream.Length) {
int len; // Length of chunk data.
if (BitConverter.IsLittleEndian)
len = BitConverter.ToInt32(br.ReadBytes(4).Reverse().ToArray(), 0);
else
len = br.ReadInt32();

char[] cName = br.ReadChars(4); // The chunk type.
if (cName.SequenceEqual(new[] { 'z', 'T', 'X', 't' })) {
var sb = new StringBuilder(); // Builds the null-terminated keyword associated with the chunk.
char c = br.ReadChar();
do {
sb.Append(c);
c = br.ReadChar();
}
while (c != '\0');
byte method = br.ReadByte(); // The compression method. Should always be 0. (DEFLATE method.)
if (method != 0) {
stream.Seek(len - sb.Length + 3, SeekOrigin.Current); // If not 0, skip the rest of the chunk.
continue;
}
var data = br.ReadBytes(len - sb.Length - 1); // Rest of the chunk data...
var ms = new MemoryStream(data, 0, data.Length); // ...in a MemoryStream...
var ds = new DeflateStream(ms, CompressionMode.Decompress); // ...read by a DeflateStream...
var sr = new StreamReader(ds); // ... and a StreamReader. Yeesh.
var str = sr.ReadToEnd(); // !!! InvalidDataException !!!
ret.Add(new KeyValuePair<string, string>(sb.ToString(), str));
stream.Seek(4, SeekOrigin.Current); // Skip the CRC check.
}
else {
stream.Seek(len + 4, SeekOrigin.Current); // Skip the rest of the chunk.
}
}
}
catch (IOException) { }
catch (InvalidDataException) { }
catch (ArgumentOutOfRangeException) { }
return ret;
}

解决此问题后,我需要编写一个函数,将这些 zTXt block 添加到文件中。所以希望我能在解决这个问题后理解 DeflateStream 是如何工作的。

非常感谢!!

最佳答案

折腾了这么久,我终于找到问题所在了。数据是 zlib 格式,它存储的数据比单独使用 DEFLATE 多一点。如果我在获取压缩数据之前刚好读取了 2 个额外字节,则文件被正确读取。

参见 this feedback page . (我没有提交那个。)

我现在想知道。这两个字节的值分别是 0x78 和 0x9C。如果我发现这些值以外的值,我是否应该假设 DEFLATE 会失败?

关于c# - 如何在文件的一部分上使用 DeflateStream?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/762614/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com