JToken.WriteToAsync 没有正确写入流
JToken.WriteToAsync dosen't write to stream correctly
我想将 JToken 异步写入流。我提到了 。
但是,流输出是?[]
,而ToString()
输出是[]
。为什么流的开头包含额外的字节?
我的代码如下:
static async Task Main(string[] args)
{
JArray arr = new JArray();
//var c = JToken.FromObject("abc");
//arr.Add(c);
var stream = new MemoryStream();
await using (var requestWriter = new StreamWriter(stream, System.Text.Encoding.UTF8, leaveOpen: true))
{
var jsonWriter = new JsonTextWriter(requestWriter);
try
{
await arr.WriteToAsync(jsonWriter);
}
finally
{
await jsonWriter.CloseAsync();
}
Console.WriteLine(System.Text.Encoding.UTF8.GetString(stream.GetBuffer(), 0, checked((int)stream.Length)));
Console.WriteLine(arr.ToString());
}
}
为什么流输出不正确?
Json.net 的版本是 13.0.1.
总结
您的问题与异步写入无关。你的问题是 Encoding.UTF8
:
returns a UTF8Encoding object that provides a Unicode byte order mark (BOM).
您看到的额外 ?
是 BOM。为防止写入 BOM,使用 new UTF8Encoding(false)
when writing. Or, you could just do new StreamWriter(stream, leaveOpen: true)
as the StreamWriter
constructors 将默认使用 UTF-8 编码而不使用字节顺序标记 (BOM)。
详情
您的问题可以更简单地重现如下:
JArray arr = new JArray();
var stream = new MemoryStream();
using (var requestWriter = new StreamWriter(stream, System.Text.Encoding.UTF8, leaveOpen: true))
using (var jsonWriter = new JsonTextWriter(requestWriter))
{
arr.WriteTo(jsonWriter);
}
var resultJson = Encoding.UTF8.GetString(stream.GetBuffer(), 0, checked((int)stream.Length));
Console.WriteLine(BitConverter.ToString(stream.GetBuffer(), 0, checked((int)stream.Length)));
Console.WriteLine(resultJson);
Console.WriteLine(arr.ToString());
Assert.AreEqual(arr.ToString(), resultJson);
断言失败并显示以下消息:
NUnit.Framework.AssertionException: Expected string length 2 but was 3. Strings differ at index 0.
并使用 BitConverter.ToString()
的以下输出:
EF-BB-BF-5B-5D
演示 fiddle here.
5B-5D
是括号,但是EF-BB-BF
这三个前导字符是什么?快速搜索显示它是 UTF-8 byte order mark. Since RFC 8259 指定 实现不得在网络传输的 JSON 文本 [=56] 的开头添加字节顺序标记 (U+FEFF) =] 您应该使用 new UTF8Encoding(false)
省略 BOM。因此你的代码应该是这样的:
JArray arr = new JArray();
var stream = new MemoryStream();
await using (var requestWriter = new StreamWriter(stream, new UTF8Encoding(false), leaveOpen: true))
{
var jsonWriter = new JsonTextWriter(requestWriter);
try
{
await arr.WriteToAsync(jsonWriter);
}
finally
{
await jsonWriter.CloseAsync();
}
}
var resultJson = Encoding.UTF8.GetString(stream.GetBuffer(), 0, checked((int)stream.Length));
Console.WriteLine(BitConverter.ToString(stream.GetBuffer(), 0, checked((int)stream.Length)));
Console.WriteLine(resultJson);
Console.WriteLine(arr.ToString());
Assert.AreEqual(arr.ToString(), resultJson);
演示 fiddle #2 here.
我想将 JToken 异步写入流。我提到了 ?[]
,而ToString()
输出是[]
。为什么流的开头包含额外的字节?
我的代码如下:
static async Task Main(string[] args)
{
JArray arr = new JArray();
//var c = JToken.FromObject("abc");
//arr.Add(c);
var stream = new MemoryStream();
await using (var requestWriter = new StreamWriter(stream, System.Text.Encoding.UTF8, leaveOpen: true))
{
var jsonWriter = new JsonTextWriter(requestWriter);
try
{
await arr.WriteToAsync(jsonWriter);
}
finally
{
await jsonWriter.CloseAsync();
}
Console.WriteLine(System.Text.Encoding.UTF8.GetString(stream.GetBuffer(), 0, checked((int)stream.Length)));
Console.WriteLine(arr.ToString());
}
}
为什么流输出不正确? Json.net 的版本是 13.0.1.
总结
您的问题与异步写入无关。你的问题是 Encoding.UTF8
:
returns a UTF8Encoding object that provides a Unicode byte order mark (BOM).
您看到的额外 ?
是 BOM。为防止写入 BOM,使用 new UTF8Encoding(false)
when writing. Or, you could just do new StreamWriter(stream, leaveOpen: true)
as the StreamWriter
constructors 将默认使用 UTF-8 编码而不使用字节顺序标记 (BOM)。
详情
您的问题可以更简单地重现如下:
JArray arr = new JArray();
var stream = new MemoryStream();
using (var requestWriter = new StreamWriter(stream, System.Text.Encoding.UTF8, leaveOpen: true))
using (var jsonWriter = new JsonTextWriter(requestWriter))
{
arr.WriteTo(jsonWriter);
}
var resultJson = Encoding.UTF8.GetString(stream.GetBuffer(), 0, checked((int)stream.Length));
Console.WriteLine(BitConverter.ToString(stream.GetBuffer(), 0, checked((int)stream.Length)));
Console.WriteLine(resultJson);
Console.WriteLine(arr.ToString());
Assert.AreEqual(arr.ToString(), resultJson);
断言失败并显示以下消息:
NUnit.Framework.AssertionException: Expected string length 2 but was 3. Strings differ at index 0.
并使用 BitConverter.ToString()
的以下输出:
EF-BB-BF-5B-5D
演示 fiddle here.
5B-5D
是括号,但是EF-BB-BF
这三个前导字符是什么?快速搜索显示它是 UTF-8 byte order mark. Since RFC 8259 指定 实现不得在网络传输的 JSON 文本 [=56] 的开头添加字节顺序标记 (U+FEFF) =] 您应该使用 new UTF8Encoding(false)
省略 BOM。因此你的代码应该是这样的:
JArray arr = new JArray();
var stream = new MemoryStream();
await using (var requestWriter = new StreamWriter(stream, new UTF8Encoding(false), leaveOpen: true))
{
var jsonWriter = new JsonTextWriter(requestWriter);
try
{
await arr.WriteToAsync(jsonWriter);
}
finally
{
await jsonWriter.CloseAsync();
}
}
var resultJson = Encoding.UTF8.GetString(stream.GetBuffer(), 0, checked((int)stream.Length));
Console.WriteLine(BitConverter.ToString(stream.GetBuffer(), 0, checked((int)stream.Length)));
Console.WriteLine(resultJson);
Console.WriteLine(arr.ToString());
Assert.AreEqual(arr.ToString(), resultJson);
演示 fiddle #2 here.