放气流适用于二进制数据。文本文件中间的任意二进制块也称为:损坏的文本文件。没有明智的解码方法:
- 您无法阅读“行”,因为在谈论二进制数据时没有“行”的定义;CR/LF/CRLF/等的任何组合都可以在二进制数据中完全随机出现
- 您无法读取“字符串行”,因为这表明您正在通过
Encoding
;运行数据。但由于这不是文本数据,再次:这只会给你无法处理的乱码(读取时它会丢失数据)
现在,这两个问题中的第二个可以通过读取Stream
API 而不是StreamReader
API 来解决,因此您只能读取二进制文件;然后,您需要自己查找行尾,使用 anEncoding
来探测您能做的事情(注意,如果您使用的是多/可变字节编码,例如 UTF-8,这并不像听起来那么简单)。
然而,这两个问题中的第一个问题本身是无法解决的。为了可靠地做到这一点,您需要某种二进制帧协议——同样,文本文件中不存在这种协议。看起来该示例使用了“mark”和“endmark” - 同样,从技术上讲,这些可能会随机发生,但对于 99.999% 的情况,您可能会侥幸逃脱。Stream
那么,诀窍是使用and手动读取整个文件Encoding
,寻找“标记”和“结束标记” - 并从压缩数据位中剥离编码为文本的位。然后通过正确的Encoding
.
然而!在您读取二进制文件时,这很简单:您只需缓冲正确的数量(使用写入数据的任何帧/哨兵协议),然后使用类似的东西:
using(var ms = new MemoryStream(bytes))
using(var inflate = new GZipStream(ms, CompressionMode.Decompress))
{
// now read from 'inflate'
}
随着l 73
标记的添加,以及它是 ASCII 的信息,它变得更加可行。
这对我不起作用,因为 SO 上的数据已经损坏(以文本形式发布二进制文件),但基本上类似于:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
using (var file = File.OpenRead("my.txt"))
using (var buffer = new MemoryStream())
{
List<string> lines = new List<string>();
string line;
while ((line = ReadToCRLF(file, buffer)) != null)
{
lines.Add(line);
Console.WriteLine(line);
if (line == "mark" && lines.Count >= 2)
{
var match = Regex.Match(lines[lines.Count - 2], "^l ([0-9]+)$");
int bytes;
if (match.Success && int.TryParse(match.Groups[1].Value, out bytes))
{
ReadBytes(file, buffer, bytes);
string inflated = Inflate(buffer);
lines.Add(inflated); // or something similar
Console.WriteLine(inflated);
}
}
}
}
}
static string Inflate(Stream source)
{
using (var deflate = new DeflateStream(source, CompressionMode.Decompress, true))
using (var reader = new StreamReader(deflate, Encoding.ASCII))
{
return reader.ReadToEnd();
}
}
static void ReadBytes(Stream source, MemoryStream buffer, int count)
{
buffer.SetLength(count);
int read, offset = 0;
while (count > 0 && (read = source.Read(buffer.GetBuffer(), offset, count)) > 0)
{
count -= read;
offset += read;
}
if (count != 0) throw new EndOfStreamException();
buffer.Position = 0;
}
static string ReadToCRLF(Stream source, MemoryStream buffer)
{
buffer.SetLength(0);
int next;
bool wasCr = false;
while ((next = source.ReadByte()) >= 0)
{
if(next == 10 && wasCr) { // CRLF
// end of line (minus the CR)
return Encoding.ASCII.GetString(
buffer.GetBuffer(), 0, (int)buffer.Length - 1);
}
buffer.WriteByte((byte)next);
wasCr = next == 13;
}
// end of file
if (buffer.Length == 0) return null;
return Encoding.ASCII.GetString(buffer.GetBuffer(), 0, (int)buffer.Length);
}
}