StreamReader.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. //
  2. // System.IO.StreamReader.cs
  3. //
  4. // Author:
  5. // Dietmar Maurer ([email protected])
  6. //
  7. // (C) Ximian, Inc. http://www.ximian.com
  8. //
  9. using System;
  10. using System.Text;
  11. namespace System.IO {
  12. [Serializable]
  13. public class StreamReader : TextReader {
  14. private const int DefaultBufferSize = 1024;
  15. private const int DefaultFileBufferSize = 4096;
  16. private const int MinimumBufferSize = 128;
  17. // buffering members
  18. private byte [] rgbEncoded;
  19. // private int cbEncoded;
  20. private char [] rgchDecoded;
  21. private int cchDecoded;
  22. private int pos;
  23. private Encoding internalEncoding;
  24. private Decoder decoder;
  25. private Stream internalStream;
  26. public new static readonly StreamReader Null = new StreamReader((Stream)null);
  27. public StreamReader(Stream stream)
  28. : this (stream, null, false, DefaultBufferSize) { }
  29. public StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks)
  30. : this (stream, null, detectEncodingFromByteOrderMarks, DefaultBufferSize) { }
  31. public StreamReader(Stream stream, Encoding encoding)
  32. : this (stream, encoding, false, DefaultBufferSize) { }
  33. public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks)
  34. : this (stream, encoding, detectEncodingFromByteOrderMarks, DefaultBufferSize) { }
  35. public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
  36. {
  37. Initialize (stream, encoding, detectEncodingFromByteOrderMarks, bufferSize);
  38. }
  39. public StreamReader(string path)
  40. : this (path, null, false, DefaultFileBufferSize) { }
  41. public StreamReader(string path, bool detectEncodingFromByteOrderMarks)
  42. : this (path, null, detectEncodingFromByteOrderMarks, DefaultFileBufferSize) { }
  43. public StreamReader(string path, Encoding encoding)
  44. : this (path, encoding, false, DefaultFileBufferSize) { }
  45. public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks)
  46. : this (path, encoding, detectEncodingFromByteOrderMarks, DefaultFileBufferSize) { }
  47. [MonoTODO]
  48. public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
  49. {
  50. Stream stream = (Stream) File.OpenRead (path);
  51. Initialize (stream, encoding, detectEncodingFromByteOrderMarks, bufferSize);
  52. }
  53. [MonoTODO]
  54. protected void Initialize (Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
  55. {
  56. internalStream = stream;
  57. // use detect encoding flag
  58. if (encoding == null) {
  59. internalEncoding = Encoding.UTF8;
  60. decoder = Encoding.UTF8.GetDecoder ();
  61. } else {
  62. internalEncoding = encoding;
  63. decoder = encoding.GetDecoder ();
  64. }
  65. if (bufferSize < MinimumBufferSize)
  66. bufferSize = MinimumBufferSize;
  67. rgbEncoded = new byte [bufferSize];
  68. rgchDecoded = new char [internalEncoding.GetMaxCharCount (bufferSize)];
  69. pos = 0;
  70. cchDecoded = 0;
  71. }
  72. public virtual Stream BaseStream
  73. {
  74. get {
  75. return internalStream;
  76. }
  77. }
  78. public virtual Encoding CurrentEncoding
  79. {
  80. get {
  81. return internalEncoding;
  82. }
  83. }
  84. public override void Close ()
  85. {
  86. Dispose (true);
  87. }
  88. public void DiscardBufferedData ()
  89. {
  90. pos = 0;
  91. cchDecoded = 0;
  92. /* I'm sure there's no need to do all this
  93. if ((cchDecoded == null) || (pos == cchDecoded.Length))
  94. return;
  95. if (!internalStream.CanSeek)
  96. return;
  97. int seek_back = pos - cchDecoded.Length;
  98. internalStream.Seek (seek_back, SeekOrigin.Current);
  99. */
  100. }
  101. // the buffer is empty, fill it again
  102. [MonoTODO ("handle byte order marks here")]
  103. private int ReadBuffer ()
  104. {
  105. pos = 0;
  106. int cbEncoded = 0;
  107. cchDecoded = 0;
  108. do // keep looping until the decoder gives us some chars
  109. {
  110. cbEncoded = internalStream.Read (rgbEncoded, 0, rgbEncoded.Length);
  111. // TODO: remove this line when iconv is fixed
  112. int bufcnt = decoder.GetCharCount (rgbEncoded, 0, cbEncoded);
  113. if (cbEncoded == 0)
  114. return 0;
  115. // TODO: remove byte order marks here
  116. cchDecoded += decoder.GetChars (rgbEncoded, 0, cbEncoded, rgchDecoded, 0);
  117. } while (cchDecoded == 0);
  118. return cchDecoded;
  119. }
  120. public override int Peek ()
  121. {
  122. if (!internalStream.CanSeek)
  123. return -1;
  124. if (pos >= cchDecoded && ReadBuffer () == 0)
  125. return -1;
  126. return rgchDecoded [pos];
  127. }
  128. public override int Read ()
  129. {
  130. if (pos >= cchDecoded && ReadBuffer () == 0)
  131. return -1;
  132. return rgchDecoded [pos++];
  133. }
  134. public override int Read (char[] dest_buffer, int index, int count)
  135. {
  136. if (dest_buffer == null)
  137. throw new ArgumentException ();
  138. if (index + count >= dest_buffer.Length)
  139. throw new ArgumentException ();
  140. if ((index < 0) || (count < 0))
  141. throw new ArgumentOutOfRangeException ();
  142. int cchRead = 0;
  143. while (count > 0)
  144. {
  145. if (pos >= cchDecoded && ReadBuffer () == 0)
  146. return -1;
  147. int cch = Math.Min (cchDecoded - pos, count);
  148. Array.Copy (rgchDecoded, pos, dest_buffer, index, cch);
  149. pos += cch;
  150. index += cch;
  151. count -= cch;
  152. cchRead += cch;
  153. }
  154. return cchRead;
  155. }
  156. public override string ReadLine()
  157. {
  158. StringBuilder text = new StringBuilder ();
  159. while (true) {
  160. int c = Read ();
  161. if (c == -1) { // end of stream
  162. if (text.Length == 0)
  163. return null;
  164. break;
  165. }
  166. if (c == '\n') // newline
  167. break;
  168. if (c == '\r' && Peek () == '\n') { // cr, newline
  169. Read ();
  170. break;
  171. }
  172. text.Append ((char) c);
  173. }
  174. return text.ToString ();
  175. }
  176. public override string ReadToEnd()
  177. {
  178. StringBuilder text = new StringBuilder ();
  179. int c;
  180. while ((c = Read ()) != -1) {
  181. text.Append ((char) c);
  182. }
  183. if (text.Length == 0)
  184. return null;
  185. return text.ToString ();
  186. }
  187. }
  188. }