当写入文件时Async
本文关键字:Async 文件 | 更新日期: 2023-09-27 18:05:46
Json.net具有将对象转换为json的async函数,如:
json = await JsonConvert.DeserializeObjectAsync<T>
但是当我想写一个对象到json文件时,对我来说直接使用文件流似乎更好。
所以我认为应该是这样的:
var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite);
using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
{
using (StreamWriter sw = new StreamWriter(fileStream.AsStreamForWrite()))
{
using (JsonWriter jw = new JsonTextWriter(sw))
{
jw.Formatting = Formatting.Indented;
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(jw, obj);
}
}
但是在JsonSerzializer对象上,我找不到异步方法。另外,我认为IO操作不应该放在自己的线程中。
Json。. NET并不真正支持异步反/序列化。JsonConvert
上的异步方法只是在另一个线程上运行它们的同步方法的包装(这正是库不应该做的)。
async
的全部优点(它会浪费一个线程),但它不会阻塞UI线程。
参见此代码,它使用正确的异步方式(例如,它不会创建巨大的字节数组以避免LOH内存分配,它不会等待IO操作完成)。
// create this in the constructor, stream manages can be reused
// see details in this answer https://stackoverflow.com/a/42599288/185498
var streamManager = new RecyclableMemoryStreamManager();
using (var file = File.Open(destination, FileMode.Create))
{
using (var memoryStream = streamManager.GetStream()) // RecyclableMemoryStream will be returned, it inherits MemoryStream, however prevents data allocation into the LOH
{
using (var writer = new StreamWriter(memoryStream))
{
var serializer = JsonSerializer.CreateDefault();
serializer.Serialize(writer, data);
await writer.FlushAsync().ConfigureAwait(false);
memoryStream.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(file).ConfigureAwait(false);
}
}
await file.FlushAsync().ConfigureAwait(false);
}
整个文件:https://github.com/imanushin/AsyncIOComparison/blob/0e2527d5c00c2465e8fd2617ed8bcb1abb529436/IntermediateData/FileNames.cs
对于JSON.NET/Newtonsoft.JSON不能这样做。
但是,您可以使用System.Text.Json。
以获得与JSON相同的行为。. NET,只需将IncludeFields和PropertyNameCaseInsensitive设置为true。
public static class JsonExtensions
{
private static readonly System.Text.Json.JsonSerializerOptions _jsonOptions =
new System.Text.Json.JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
IncludeFields = true
}
;
public static string ToJson<T>(this T obj)
{
return System.Text.Json.JsonSerializer.Serialize<T>(obj, _jsonOptions);
}
public static T FromJson<T>(this string json)
{
return System.Text.Json.JsonSerializer.Deserialize<T>(json, _jsonOptions);
}
public static async System.Threading.Tasks.Task ToJsonAsync<T>(this T obj, System.IO.Stream stream)
{
await System.Text.Json.JsonSerializer.SerializeAsync(stream, obj, typeof(T), _jsonOptions);
}
public static async System.Threading.Tasks.Task<T> FromJsonAsync<T>(this System.IO.Stream stream)
{
return await System.Text.Json.JsonSerializer.DeserializeAsync<T>(stream, _jsonOptions);
}
}
就这样了。
同样,如果您想异步序列化为string:
public static async System.Threading.Tasks.Task<string> ToJsonAsync<T>(this T obj)
{
string ret = null;
Microsoft.IO.RecyclableMemoryStreamManager streamManager =
new Microsoft.IO.RecyclableMemoryStreamManager();
using (System.IO.MemoryStream ms = streamManager.GetStream())
{
await System.Text.Json.JsonSerializer.SerializeAsync(ms, obj, typeof(T), _jsonOptions);
ms.Position = 0;
using (System.IO.TextReader sr = new System.IO.StreamReader(ms, System.Text.Encoding.UTF8))
{
ret = await sr.ReadToEndAsync();
}
}
return ret;
}