MemoryStream.ToArray() return 如果 StreamWriter 没有被释放,则为空数组
MemoryStream.ToArray() return empty array if StreamWriter is not disposed
我正在尝试从我的模型中获取字节数组以将其放入文件中。我有这样的方法:
public static byte[] GetByteArray(List<MyModel> models)
{
using var ms = new MemoryStream();
using var sw = new StreamWriter(ms);
foreach (var model in models)
{
sw.Write(model.Id + "," + model.Name);
sw.WriteLine();
}
sw.Dispose();
return ms.ToArray();
}
此方法工作正常,但我可能认为我不需要手动处理 StreamWriter,因为我有一个 using 语句。我也这么想,但是当我删除 sw.Dispose();
时 ms.ToArray();
returns 一个空数组。有人可以向我解释这种行为吗?
dispose 完成了部分工作。它冲洗了作家。使用 Flush()
手动刷新它。
public static byte[] GetByteArray(List<MyModel> models)
{
var ms = new MemoryStream();
using var sw = new StreamWriter(ms);
foreach (var model in models)
{
sw.Write(model.Id + "," + model.Name);
sw.WriteLine();
}
// flush the writer, to make sure it is written to the stream.
sw.Flush();
return ms.ToArray();
}
您不需要处置内存流,因为 StreamWriter 拥有所有权。
我不喜欢 streamwriter 拥有内存流的结构。这可能是因为 streamwriter 也可以直接在文件上使用。具有文件路径作为参数的构造函数。 (所以不需要流参数)
你有这条线:
using var sw = new StreamWriter(ms);
这只会在方法末尾处理 StreamWriter
。但是,您在方法结束前ms.ToArray()
调用。这意味着您在 StreamWriter
被释放之前调用 ms.ToArray()
。
但是,StreamWriter
正在内部缓冲一些数据,并且仅在处理时将其刷新到 MemoryStream
。因此,您需要确保在 调用 ms.ToArray()
.
之前处理 StreamWriter
使用旧的 using
语法可能更清楚,它明确说明何时发生处置:
public static byte[] GetByteArray(List<MyModel> models)
{
using var ms = new MemoryStream();
using (var sw = new StreamWriter(ms))
{
foreach (var model in models)
{
sw.Write(model.Id + "," + model.Name);
sw.WriteLine();
}
}
return ms.ToArray();
}
如果将 List<MyModel>
项写成字符串,可以通过以下方式简化转换:
public static byte[] GetByteArray(List<MyModel> models) =>
Encoding.UTF8.GetBytes(string.Join(Environment.NewLine,
models.Select(model => $"{model.Id},{model.Name}")));
或使用第三方序列化程序,例如 Newtonsoft.Json(示例来自 here):
public static byte[] Serialize<T>(this T source)
{
var asString = JsonConvert.SerializeObject(source, SerializerSettings);
return Encoding.Unicode.GetBytes(asString);
}
public static T Deserialize<T>(this byte[] source)
{
var asString = Encoding.Unicode.GetString(source);
return JsonConvert.DeserializeObject<T>(asString);
}
正如其他人提到的,您必须刷新 StreamWriter
这是您的函数的样子:
public static byte[] GetByteArray(List<MyModel> models)
{
MemoryStream memoryStream = new MemoryStream();
try
{
StreamWriter streamWriter = new StreamWriter(memoryStream);
try
{
List<MyModel>.Enumerator enumerator = models.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
MyModel current = enumerator.Current;
streamWriter.Write(string.Concat(current.Id, ",", current.Name));
streamWriter.WriteLine();
}
}
finally
{
((IDisposable)enumerator).Dispose();
}
streamWriter.Dispose();
return memoryStream.ToArray();
}
finally
{
if (streamWriter != null)
{
((IDisposable)streamWriter).Dispose();
}
}
}
finally
{
if (memoryStream != null)
{
((IDisposable)memoryStream).Dispose();
}
}
}
我正在尝试从我的模型中获取字节数组以将其放入文件中。我有这样的方法:
public static byte[] GetByteArray(List<MyModel> models)
{
using var ms = new MemoryStream();
using var sw = new StreamWriter(ms);
foreach (var model in models)
{
sw.Write(model.Id + "," + model.Name);
sw.WriteLine();
}
sw.Dispose();
return ms.ToArray();
}
此方法工作正常,但我可能认为我不需要手动处理 StreamWriter,因为我有一个 using 语句。我也这么想,但是当我删除 sw.Dispose();
时 ms.ToArray();
returns 一个空数组。有人可以向我解释这种行为吗?
dispose 完成了部分工作。它冲洗了作家。使用 Flush()
手动刷新它。
public static byte[] GetByteArray(List<MyModel> models)
{
var ms = new MemoryStream();
using var sw = new StreamWriter(ms);
foreach (var model in models)
{
sw.Write(model.Id + "," + model.Name);
sw.WriteLine();
}
// flush the writer, to make sure it is written to the stream.
sw.Flush();
return ms.ToArray();
}
您不需要处置内存流,因为 StreamWriter 拥有所有权。
我不喜欢 streamwriter 拥有内存流的结构。这可能是因为 streamwriter 也可以直接在文件上使用。具有文件路径作为参数的构造函数。 (所以不需要流参数)
你有这条线:
using var sw = new StreamWriter(ms);
这只会在方法末尾处理 StreamWriter
。但是,您在方法结束前ms.ToArray()
调用。这意味着您在 StreamWriter
被释放之前调用 ms.ToArray()
。
但是,StreamWriter
正在内部缓冲一些数据,并且仅在处理时将其刷新到 MemoryStream
。因此,您需要确保在 调用 ms.ToArray()
.
StreamWriter
使用旧的 using
语法可能更清楚,它明确说明何时发生处置:
public static byte[] GetByteArray(List<MyModel> models)
{
using var ms = new MemoryStream();
using (var sw = new StreamWriter(ms))
{
foreach (var model in models)
{
sw.Write(model.Id + "," + model.Name);
sw.WriteLine();
}
}
return ms.ToArray();
}
如果将 List<MyModel>
项写成字符串,可以通过以下方式简化转换:
public static byte[] GetByteArray(List<MyModel> models) =>
Encoding.UTF8.GetBytes(string.Join(Environment.NewLine,
models.Select(model => $"{model.Id},{model.Name}")));
或使用第三方序列化程序,例如 Newtonsoft.Json(示例来自 here):
public static byte[] Serialize<T>(this T source)
{
var asString = JsonConvert.SerializeObject(source, SerializerSettings);
return Encoding.Unicode.GetBytes(asString);
}
public static T Deserialize<T>(this byte[] source)
{
var asString = Encoding.Unicode.GetString(source);
return JsonConvert.DeserializeObject<T>(asString);
}
正如其他人提到的,您必须刷新 StreamWriter
这是您的函数的样子:
public static byte[] GetByteArray(List<MyModel> models)
{
MemoryStream memoryStream = new MemoryStream();
try
{
StreamWriter streamWriter = new StreamWriter(memoryStream);
try
{
List<MyModel>.Enumerator enumerator = models.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
MyModel current = enumerator.Current;
streamWriter.Write(string.Concat(current.Id, ",", current.Name));
streamWriter.WriteLine();
}
}
finally
{
((IDisposable)enumerator).Dispose();
}
streamWriter.Dispose();
return memoryStream.ToArray();
}
finally
{
if (streamWriter != null)
{
((IDisposable)streamWriter).Dispose();
}
}
}
finally
{
if (memoryStream != null)
{
((IDisposable)memoryStream).Dispose();
}
}
}