C# 流适配器提供写到接口到写输出实用程序,但也提供读取接口
我不喜欢在流接口之间使用MemoryStream对象。它们很笨拙,需要您从头开始重新查找,并且在要求苛刻的情况下也会达到内存使用的峰值 有时,实用程序只能以某种方式工作。它可能会输出字节[]s,或者写入流,或者是从中读取的管道中的流,从而将数据拉过 此Newtonsoft JSON序列化程序是一个只能写入流的实用程序C# 流适配器提供写到接口到写输出实用程序,但也提供读取接口,c#,stream,json.net,gzipstream,C#,Stream,Json.net,Gzipstream,我不喜欢在流接口之间使用MemoryStream对象。它们很笨拙,需要您从头开始重新查找,并且在要求苛刻的情况下也会达到内存使用的峰值 有时,实用程序只能以某种方式工作。它可能会输出字节[]s,或者写入流,或者是从中读取的管道中的流,从而将数据拉过 此Newtonsoft JSON序列化程序是一个只能写入流的实用程序 var js = new Newtonsoft.Json.JsonSerializer(); var sw = new StreamWriter(ps); js.Serialize
var js = new Newtonsoft.Json.JsonSerializer();
var sw = new StreamWriter(ps);
js.Serialize(sw, o);
这对我来说是个问题,因为我想连锁:
数不清
JSON序列化
GZIP压缩
HTTP到客户端
网络
来自服务器的HTTP
GZIP解压
JSON反序列化
数不清
除了让JSON反序列化程序提供一个好的IEnumerable接口的困难之外,其余部分都没有提供适合流水线的接口。甚至GZIP压缩端也是错误的
理想情况下,在服务器端,我可以:
IEnumerable<object> o = GetData();
var js = new Newtonsoft.Json.JsonSerialization(o);
var gz = new System.IO.Compression.GZipStream(js, System.IO.Compression.CompressionMode.Compress, true);
return new FileStreamResult(gz, "application/x-gzip");
我可能会扩展Newtonsoft项目以提供管道实现,而且我可能会这样做。但在此之前,我需要一个解决方案,我相信其他实用程序(包括BCL GZipStream)也需要一个解决方案
是否有任何解决方案可以让人们更有效地加入这些实用程序?
是否有一个库包含用于此类情况的适配器?
我正在开发这样一个库,不希望有这样一个库。答案是全新的StreamAdapter项目: . 它仍然需要一些工作——将其打包为一个NuGet包会很好,但它已经全部就绪并经过测试 所以界面看起来有点像这样:
var data = GetData(); //Get the source data
var sa = new StreamAdaptor(); //This is what wraps the write-only utility source
sa.UpstreamSource((ps) => //ps is the dummy stream which does most of the magic
{
//This anon. function is run on a separate thread and can therefore be blocked
var sw = new StreamWriter(ps);
sw.AutoFlush = true;
var js = new Newtonsoft.Json.JsonSerializer();
js.Serialize(sw, data); //This is the main component of the implementation
sw.Flush();
});
var sa2 = new StreamAdaptor();
sa2.UpstreamSource((ps) =>
{
using (var gz = new System.IO.Compression.GZipStream(ps, System.IO.Compression.CompressionMode.Compress, true))
sa.CopyTo(gz);
});
相反的过程更容易,因为它自然地支持一个通读管道
System.IO.Compression.GZipStream sw = new System.IO.Compression.GZipStream(sa2, System.IO.Compression.CompressionMode.Decompress);
var jsonTextReader = new JsonTextReader(new StreamReader(sw));
return TestA.Deserialize(jsonTextReader);
我还演示了IEnumerable反序列化问题的解决方法。它要求您利用JsonTextReader创建自己的反序列化程序,但效果很好
序列化程序本机支持IEnumerable。上面的GetData函数使用IEnumerable函数以及其他功能为序列化程序设置数据源:
public static IEnumerable<TestB> GetTestBs()
{
for (int i = 0; i < 2; i++)
{
var b = new TestB();
b.A = "A";
b.B = "B";
b.C = TestB.GetCs();
yield return b;
}
}
IEnumerable反序列化器函数之一:
static IEnumerable<TestB> DeserializeTestBs(JsonTextReader reader)
{
while (reader.Read())
{
if (reader.TokenType == JsonToken.EndArray)
break;
yield return TestB.Deserialize(reader);
}
reader.Read(); //End of object
}
这当然可以通过反复试验来实现,尽管JSON.NET中的内置支持是可取的。我已经确认了这是可能的,并且还准备了一个IEnumerable反序列化解决方案,使用JSON.NET,但手动控制序列化和反序列化。我正在应用我的解决方案,然后将其抽象为一个独立的项目进行共享。我希望IEnumerable反序列化功能最终能够作为一种不需要手动控制序列化的通用实现进入JSON.NET
static IEnumerable<TestB> DeserializeTestBs(JsonTextReader reader)
{
while (reader.Read())
{
if (reader.TokenType == JsonToken.EndArray)
break;
yield return TestB.Deserialize(reader);
}
reader.Read(); //End of object
}