StreamWriter
默认取得您传入的流的所有权,因此当您处理流式编写器时,它会处理您传入的流,如果您使用this constructor,则可以传入一个布尔值,告诉它不要处理即传入的流。
private static readonly UTF8Encoding UTF8NoBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier:false, throwOnInvalidBytes:true);
public void Serialize(Stream stream, object data)
{
var serializer = new Newtonsoft.Json.JsonSerializer();
using (var textWriter = new StreamWriter(stream, UTF8NoBOM, bufferSize:1024, leaveOpen:true))
using (var jsonWriter = new JsonTextWriter(textWriter))
{
serializer.Serialize(jsonWriter, data);
}
}
你只需要以旧的构造函数已通过在第二和第三参数,这将是一个UTF8Encoding
没有字节顺序标记和1024
分别默认值来传递。
*我使用命名参数,因为我不喜欢传入神秘常量,使用命名参数,它使它更明显是什么1024
和true
表示。
作为替代的解决方案,如果你不上.NET 4.5或更新的象下面穿过所有Stream
命令除了处置
public class DisposeBlocker : Stream
{
private readonly Stream _source;
private readonly bool _blockDispose;
private readonly bool _blockClose;
public DisposeBlocker(Stream source, bool blockDispose = true, bool blockClose = false)
{
if(source == null)
throw new ArgumentNullException(nameof(source));
_source = source;
_blockDispose = blockDispose;
_blockClose = blockClose;
}
protected override void Dispose(bool disposing)
{
if (!_blockDispose && disposing)
{
_source.Dispose();
}
}
public override void Close()
{
if (!_blockClose)
{
_source.Close();
}
}
public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
return _source.CopyToAsync(destination, bufferSize, cancellationToken);
}
public override void Flush()
{
_source.Flush();
}
public override Task FlushAsync(CancellationToken cancellationToken)
{
return _source.FlushAsync(cancellationToken);
}
protected override WaitHandle CreateWaitHandle()
{
//Obsolete method, Reference Source states just return the following.
return new ManualResetEvent(false);
}
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
return _source.BeginRead(buffer, offset, count, callback, state);
}
public override int EndRead(IAsyncResult asyncResult)
{
return _source.EndRead(asyncResult);
}
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _source.ReadAsync(buffer, offset, count, cancellationToken);
}
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
return _source.BeginWrite(buffer, offset, count, callback, state);
}
public override void EndWrite(IAsyncResult asyncResult)
{
_source.EndWrite(asyncResult);
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _source.WriteAsync(buffer, offset, count, cancellationToken);
}
public override long Seek(long offset, SeekOrigin origin)
{
return _source.Seek(offset, origin);
}
public override void SetLength(long value)
{
_source.SetLength(value);
}
public override int Read(byte[] buffer, int offset, int count)
{
return _source.Read(buffer, offset, count);
}
public override int ReadByte()
{
return _source.ReadByte();
}
public override void Write(byte[] buffer, int offset, int count)
{
_source.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
_source.WriteByte(value);
}
protected override void ObjectInvariant()
{
//Obsolete method, nothing to override.
}
public override bool CanRead
{
get { return _source.CanRead; }
}
public override bool CanSeek
{
get { return _source.CanSeek; }
}
public override bool CanTimeout
{
get { return _source.CanTimeout; }
}
public override bool CanWrite
{
get { return _source.CanWrite; }
}
public override long Length
{
get { return _source.Length; }
}
public override long Position
{
get { return _source.Position; }
set { _source.Position = value; }
}
public override int ReadTimeout
{
get { return _source.ReadTimeout; }
set { _source.ReadTimeout = value; }
}
public override int WriteTimeout
{
get { return _source.WriteTimeout; }
set { _source.WriteTimeout = value; }
}
public override object InitializeLifetimeService()
{
return _source.InitializeLifetimeService();
}
public override ObjRef CreateObjRef(Type requestedType)
{
return _source.CreateObjRef(requestedType);
}
public override string ToString()
{
return _source.ToString();
}
public override bool Equals(object obj)
{
return _source.Equals(obj);
}
public override int GetHashCode()
{
return _source.GetHashCode();
}
}
它用于像
可以使用一个类
public void Serialize(Stream stream, object data)
{
var serializer = new Newtonsoft.Json.JsonSerializer();
using (var textWriter = new StreamWriter(new DisposeBlocker(stream)))
using (var jsonWriter = new JsonTextWriter(textWriter))
{
serializer.Serialize(jsonWriter, data);
}
}
你需要处置'StreamWriter' ** AFTER **你完成了使用'JSONTextWriter'并处置它。此外,文件被“破坏”是因为你没有处理这些流。 dispose方法通常也会将剩余内存刷新到文件中 – Sidewinder94
StreamWriter将取得所有权并关闭Dispose上的流。 'bool leaveOpen'有一个构造函数重载。在这里寻找更多的信息:https://msdn.microsoft.com/en-us/library/gg712853(v=vs.110).aspx –
使用语句已经这样做,对吧?但只要一切都结束了,我不能再做stream.Position = 0了,那就是问题所在。但我也需要关闭Json.Net才能正常工作。也许这是他们的序列化程序中的一个错误。 – Xarbrough