StreamWriter.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. //
  2. // System.IO.StreamWriter.cs
  3. //
  4. // Author:
  5. // Dietmar Maurer ([email protected])
  6. //
  7. // (C) Ximian, Inc. http://www.ximian.com
  8. //
  9. using System.Text;
  10. using System;
  11. namespace System.IO {
  12. [Serializable]
  13. public class StreamWriter : TextWriter {
  14. private Encoding internalEncoding;
  15. private Stream internalStream;
  16. private bool closed = false;
  17. private bool iflush;
  18. private const int DefaultBufferSize = 1024;
  19. private const int DefaultFileBufferSize = 4096;
  20. private const int MinimumBufferSize = 2;
  21. private int pos;
  22. private int BufferSize;
  23. private byte[] TheBuffer;
  24. private bool DisposedAlready = false;
  25. public new static readonly StreamWriter Null = new StreamWriter (Stream.Null, Encoding.UTF8Unmarked, 0);
  26. public StreamWriter (Stream stream)
  27. : this (stream, new UTF8Encoding (false, true), DefaultBufferSize) {}
  28. public StreamWriter (Stream stream, Encoding encoding)
  29. : this (stream, encoding, DefaultBufferSize) {}
  30. internal void Initialize(Encoding encoding, int bufferSize) {
  31. internalEncoding = encoding;
  32. pos = 0;
  33. BufferSize = Math.Max(bufferSize, MinimumBufferSize);
  34. TheBuffer = new byte[BufferSize];
  35. }
  36. //[MonoTODO("Nothing is done with bufferSize")]
  37. public StreamWriter (Stream stream, Encoding encoding, int bufferSize) {
  38. if (null == stream)
  39. throw new ArgumentNullException("stream");
  40. if (null == encoding)
  41. throw new ArgumentNullException("encoding");
  42. if (bufferSize < 0)
  43. throw new ArgumentOutOfRangeException("bufferSize");
  44. if (!stream.CanWrite)
  45. throw new ArgumentException("bufferSize");
  46. internalStream = stream;
  47. Initialize(encoding, bufferSize);
  48. }
  49. public StreamWriter (string path)
  50. : this (path, false, Encoding.UTF8Unmarked, DefaultFileBufferSize) {}
  51. public StreamWriter (string path, bool append)
  52. : this (path, append, Encoding.UTF8Unmarked, DefaultFileBufferSize) {}
  53. public StreamWriter (string path, bool append, Encoding encoding)
  54. : this (path, append, encoding, DefaultFileBufferSize) {}
  55. public StreamWriter (string path, bool append, Encoding encoding, int bufferSize) {
  56. if (null == path)
  57. throw new ArgumentNullException("path");
  58. if (String.Empty == path)
  59. throw new ArgumentException("path cannot be empty string");
  60. if (path.IndexOfAny (Path.InvalidPathChars) != -1)
  61. throw new ArgumentException("path contains invalid characters");
  62. if (null == encoding)
  63. throw new ArgumentNullException("encoding");
  64. if (bufferSize < 0)
  65. throw new ArgumentOutOfRangeException("bufferSize");
  66. string DirName = Path.GetDirectoryName(path);
  67. if (DirName != String.Empty && !Directory.Exists(DirName))
  68. throw new DirectoryNotFoundException();
  69. FileMode mode;
  70. if (append)
  71. mode = FileMode.Append;
  72. else
  73. mode = FileMode.Create;
  74. internalStream = new FileStream (path, mode, FileAccess.Write);
  75. if (append)
  76. internalStream.Position = internalStream.Length;
  77. else
  78. internalStream.SetLength (0);
  79. Initialize(encoding, bufferSize);
  80. }
  81. public virtual bool AutoFlush {
  82. get {
  83. return iflush;
  84. }
  85. set {
  86. iflush = value;
  87. }
  88. }
  89. public virtual Stream BaseStream {
  90. get {
  91. return internalStream;
  92. }
  93. }
  94. public override Encoding Encoding {
  95. get {
  96. return internalEncoding;
  97. }
  98. }
  99. protected override void Dispose (bool disposing) {
  100. if (!DisposedAlready && disposing && internalStream != null) {
  101. Flush();
  102. DisposedAlready = true;
  103. internalStream.Close ();
  104. }
  105. internalStream = null;
  106. TheBuffer = null;
  107. internalEncoding = null;
  108. }
  109. public override void Flush () {
  110. if (DisposedAlready)
  111. throw new ObjectDisposedException("StreamWriter");
  112. if (pos > 0) {
  113. internalStream.Write (TheBuffer, 0, pos);
  114. internalStream.Flush ();
  115. pos = 0;
  116. }
  117. }
  118. public override void Write (char[] buffer, int index, int count) {
  119. if (DisposedAlready)
  120. throw new ObjectDisposedException("StreamWriter");
  121. byte[] res = new byte [internalEncoding.GetByteCount (buffer)];
  122. int len;
  123. int BytesToBuffer;
  124. int resPos = 0;
  125. len = internalEncoding.GetBytes (buffer, index, count, res, 0);
  126. // if they want AutoFlush, don't bother buffering
  127. if (iflush) {
  128. Flush();
  129. internalStream.Write (res, 0, len);
  130. internalStream.Flush ();
  131. } else {
  132. // otherwise use the buffer.
  133. // NOTE: this logic is not optimized for performance.
  134. while (resPos < len) {
  135. // fill the buffer if we've got more bytes than will fit
  136. BytesToBuffer = Math.Min(BufferSize - pos, len - resPos);
  137. Array.Copy(res, resPos, TheBuffer, pos, BytesToBuffer);
  138. resPos += BytesToBuffer;
  139. pos += BytesToBuffer;
  140. // if the buffer is full, flush it out.
  141. if (pos == BufferSize) Flush();
  142. }
  143. }
  144. }
  145. public override void Write (char value)
  146. {
  147. Write (new char [] {value}, 0, 1);
  148. }
  149. public override void Write (char [] value)
  150. {
  151. Write (value, 0, value.Length);
  152. }
  153. public override void Write(string value) {
  154. if (DisposedAlready)
  155. throw new ObjectDisposedException("StreamWriter");
  156. if (value != null)
  157. Write (value.ToCharArray (), 0, value.Length);
  158. }
  159. public override void Close()
  160. {
  161. Dispose (true);
  162. }
  163. ~StreamWriter() {
  164. Dispose(false);
  165. }
  166. }
  167. }