StreamReader.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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. public class StreamReader : TextReader {
  13. // buffering members
  14. private char[] buffer;
  15. private int pos;
  16. private Encoding internalEncoding;
  17. private Decoder decoder;
  18. private Stream internalStream;
  19. public new static readonly StreamReader Null = new StreamReader((Stream)null);
  20. public StreamReader(Stream stream)
  21. : this (stream, null, false, 0) { }
  22. public StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks)
  23. : this (stream, null, detectEncodingFromByteOrderMarks, 0) { }
  24. public StreamReader(Stream stream, Encoding encoding)
  25. : this (stream, encoding, false, 0) { }
  26. public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks)
  27. : this (stream, encoding, detectEncodingFromByteOrderMarks, 0) { }
  28. [MonoTODO]
  29. public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
  30. {
  31. internalStream = stream;
  32. // use detect encoding flag
  33. if (encoding == null) {
  34. internalEncoding = Encoding.UTF8;
  35. decoder = Encoding.UTF8.GetDecoder ();
  36. } else {
  37. internalEncoding = encoding;
  38. decoder = encoding.GetDecoder ();
  39. }
  40. buffer = null;
  41. }
  42. public StreamReader(string path)
  43. : this (path, null, false, 0) { }
  44. public StreamReader(string path, bool detectEncodingFromByteOrderMarks)
  45. : this (path, null, detectEncodingFromByteOrderMarks, 0) { }
  46. public StreamReader(string path, Encoding encoding)
  47. : this (path, encoding, false, 0) { }
  48. public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks)
  49. : this (path, encoding, detectEncodingFromByteOrderMarks, 0) { }
  50. [MonoTODO]
  51. public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
  52. {
  53. // use detect encoding flag
  54. if (encoding == null) {
  55. internalEncoding = Encoding.UTF8;
  56. decoder = Encoding.UTF8.GetDecoder ();
  57. } else {
  58. internalEncoding = encoding;
  59. decoder = encoding.GetDecoder ();
  60. }
  61. internalStream = (Stream) File.OpenRead (path);
  62. buffer = null;
  63. }
  64. public virtual Stream BaseStream
  65. {
  66. get {
  67. return internalStream;
  68. }
  69. }
  70. public Encoding CurrentEncoding
  71. {
  72. get {
  73. return internalEncoding;
  74. }
  75. }
  76. public override void Close ()
  77. {
  78. Dispose (true);
  79. }
  80. public void DiscardBufferedData ()
  81. {
  82. if ((buffer == null) || (pos == buffer.Length))
  83. return;
  84. if (!internalStream.CanSeek)
  85. return;
  86. int seek_back = pos - buffer.Length;
  87. internalStream.Seek (seek_back, SeekOrigin.Current);
  88. }
  89. private int GetRemaining ()
  90. {
  91. return (buffer != null) ? buffer.Length - pos : 0;
  92. }
  93. private int RoundUpTo (int number, int roundto)
  94. {
  95. if ((number % roundto) == 0)
  96. return number;
  97. else
  98. return ((number / roundto) + 1) * roundto;
  99. }
  100. private bool ReadBuffer (int count)
  101. {
  102. // There are still enough bytes in the buffer.
  103. if ((buffer != null) && (pos + count <= buffer.Length))
  104. return true;
  105. // Number of bytes remaining in the buffer.
  106. int remaining = GetRemaining ();
  107. // Round up to block size
  108. int size = RoundUpTo (count, 4096);
  109. byte[] bytes = new byte [size];
  110. int cnt = internalStream.Read (bytes, 0, size);
  111. if (cnt <= 0)
  112. return false;
  113. int bufcnt = decoder.GetCharCount (bytes, 0, cnt);
  114. char[] newbuffer = new char [remaining + bufcnt];
  115. if (remaining > 0)
  116. Array.Copy (buffer, pos, newbuffer, 0, remaining);
  117. buffer = newbuffer;
  118. bufcnt = decoder.GetChars (bytes, 0, cnt, buffer, remaining);
  119. pos = 0;
  120. return true;
  121. }
  122. public override int Peek ()
  123. {
  124. if (!internalStream.CanSeek)
  125. return -1;
  126. if (!ReadBuffer (1))
  127. return -1;
  128. return buffer [pos];
  129. }
  130. public override int Read ()
  131. {
  132. if (!ReadBuffer (1))
  133. return -1;
  134. return buffer[pos++];
  135. }
  136. public override int Read (char[] dest_buffer, int index, int count)
  137. {
  138. if (dest_buffer == null)
  139. throw new ArgumentException ();
  140. if (index + count >= dest_buffer.Length)
  141. throw new ArgumentException ();
  142. if ((index < 0) || (count < 0))
  143. throw new ArgumentOutOfRangeException ();
  144. if (!ReadBuffer (count))
  145. return -1;
  146. int remaining = buffer.Length - pos;
  147. int size = Math.Min (remaining, count);
  148. Array.Copy (buffer, pos, dest_buffer, index, size);
  149. return size;
  150. }
  151. public override string ReadLine()
  152. {
  153. StringBuilder text = new StringBuilder ();
  154. while (true) {
  155. int c = Read ();
  156. if (c == -1) { // end of stream
  157. if (text.Length == 0)
  158. return null;
  159. break;
  160. }
  161. if (c == '\n') // newline
  162. break;
  163. if (c == '\r' && Peek () == '\n') { // cr, newline
  164. Read ();
  165. break;
  166. }
  167. text.Append ((char) c);
  168. }
  169. return text.ToString ();
  170. }
  171. public override string ReadToEnd()
  172. {
  173. StringBuilder text = new StringBuilder ();
  174. while (true) {
  175. int c = Read ();
  176. if (c == -1) {
  177. if (text.Length == 0)
  178. return null;
  179. break;
  180. }
  181. text.Append ((char) c);
  182. }
  183. return text.ToString ();
  184. }
  185. }
  186. }