BinaryWriter.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. //
  2. // System.IO.BinaryWriter
  3. //
  4. // Author:
  5. // Matt Kimball ([email protected])
  6. //
  7. //
  8. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System;
  30. using System.Text;
  31. using System.Globalization;
  32. using Mono.Security;
  33. using System.Runtime.InteropServices;
  34. namespace System.IO {
  35. [Serializable]
  36. [ComVisible (true)]
  37. public class BinaryWriter : IDisposable {
  38. // Null is a BinaryWriter with no backing store.
  39. public static readonly BinaryWriter Null = new BinaryWriter ();
  40. protected Stream OutStream;
  41. private Encoding m_encoding;
  42. private byte [] buffer;
  43. private bool disposed = false;
  44. protected BinaryWriter() : this (Stream.Null, Encoding.UTF8UnmarkedUnsafe) {
  45. }
  46. public BinaryWriter(Stream output) : this(output, Encoding.UTF8UnmarkedUnsafe) {
  47. }
  48. public BinaryWriter(Stream output, Encoding encoding) {
  49. if (output == null)
  50. throw new ArgumentNullException("output");
  51. if (encoding == null)
  52. throw new ArgumentNullException("encoding");
  53. if (!output.CanWrite)
  54. throw new ArgumentException(Locale.GetText ("Stream does not support writing or already closed."));
  55. OutStream = output;
  56. m_encoding = encoding;
  57. buffer = new byte [16];
  58. }
  59. public virtual Stream BaseStream {
  60. get {
  61. return OutStream;
  62. }
  63. }
  64. public virtual void Close() {
  65. Dispose (true);
  66. }
  67. #if NET_4_0
  68. public void Dispose ()
  69. #else
  70. void IDisposable.Dispose()
  71. #endif
  72. {
  73. Dispose (true);
  74. }
  75. protected virtual void Dispose (bool disposing)
  76. {
  77. if (disposing && OutStream != null)
  78. OutStream.Close();
  79. buffer = null;
  80. m_encoding = null;
  81. disposed = true;
  82. }
  83. public virtual void Flush() {
  84. OutStream.Flush();
  85. }
  86. public virtual long Seek(int offset, SeekOrigin origin) {
  87. return OutStream.Seek(offset, origin);
  88. }
  89. public virtual void Write(bool value) {
  90. if (disposed)
  91. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  92. buffer [0] = (byte) (value ? 1 : 0);
  93. OutStream.Write(buffer, 0, 1);
  94. }
  95. public virtual void Write(byte value) {
  96. if (disposed)
  97. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  98. OutStream.WriteByte(value);
  99. }
  100. public virtual void Write(byte[] buffer) {
  101. if (disposed)
  102. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  103. if (buffer == null)
  104. throw new ArgumentNullException("buffer");
  105. OutStream.Write(buffer, 0, buffer.Length);
  106. }
  107. public virtual void Write(byte[] buffer, int index, int count) {
  108. if (disposed)
  109. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  110. if (buffer == null)
  111. throw new ArgumentNullException("buffer");
  112. OutStream.Write(buffer, index, count);
  113. }
  114. public virtual void Write(char ch) {
  115. if (disposed)
  116. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  117. char[] dec = new char[1];
  118. dec[0] = ch;
  119. byte[] enc = m_encoding.GetBytes(dec, 0, 1);
  120. OutStream.Write(enc, 0, enc.Length);
  121. }
  122. public virtual void Write(char[] chars) {
  123. if (disposed)
  124. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  125. if (chars == null)
  126. throw new ArgumentNullException("chars");
  127. byte[] enc = m_encoding.GetBytes(chars, 0, chars.Length);
  128. OutStream.Write(enc, 0, enc.Length);
  129. }
  130. public virtual void Write(char[] chars, int index, int count) {
  131. if (disposed)
  132. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  133. if (chars == null)
  134. throw new ArgumentNullException("chars");
  135. byte[] enc = m_encoding.GetBytes(chars, index, count);
  136. OutStream.Write(enc, 0, enc.Length);
  137. }
  138. unsafe public virtual void Write(decimal value) {
  139. if (disposed)
  140. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  141. byte* value_ptr = (byte *)&value;
  142. /*
  143. * decimal in stream is lo32, mi32, hi32, ss32
  144. * but its internal structure si ss32, hi32, lo32, mi32
  145. */
  146. if (BitConverter.IsLittleEndian) {
  147. for (int i = 0; i < 16; i++) {
  148. if (i < 4)
  149. buffer [i + 12] = value_ptr [i];
  150. else if (i < 8)
  151. buffer [i + 4] = value_ptr [i];
  152. else if (i < 12)
  153. buffer [i - 8] = value_ptr [i];
  154. else
  155. buffer [i - 8] = value_ptr [i];
  156. }
  157. } else {
  158. for (int i = 0; i < 16; i++) {
  159. if (i < 4)
  160. buffer [15 - i] = value_ptr [i];
  161. else if (i < 8)
  162. buffer [15 - i] = value_ptr [i];
  163. else if (i < 12)
  164. buffer [11 - i] = value_ptr [i];
  165. else
  166. buffer [19 - i] = value_ptr [i];
  167. }
  168. }
  169. OutStream.Write(buffer, 0, 16);
  170. }
  171. public virtual void Write(double value) {
  172. if (disposed)
  173. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  174. OutStream.Write(BitConverterLE.GetBytes(value), 0, 8);
  175. }
  176. public virtual void Write(short value) {
  177. if (disposed)
  178. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  179. buffer [0] = (byte) value;
  180. buffer [1] = (byte) (value >> 8);
  181. OutStream.Write(buffer, 0, 2);
  182. }
  183. public virtual void Write(int value) {
  184. if (disposed)
  185. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  186. buffer [0] = (byte) value;
  187. buffer [1] = (byte) (value >> 8);
  188. buffer [2] = (byte) (value >> 16);
  189. buffer [3] = (byte) (value >> 24);
  190. OutStream.Write(buffer, 0, 4);
  191. }
  192. public virtual void Write(long value) {
  193. if (disposed)
  194. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  195. for (int i = 0, sh = 0; i < 8; i++, sh += 8)
  196. buffer [i] = (byte) (value >> sh);
  197. OutStream.Write(buffer, 0, 8);
  198. }
  199. [CLSCompliant(false)]
  200. public virtual void Write(sbyte value) {
  201. if (disposed)
  202. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  203. buffer [0] = (byte) value;
  204. OutStream.Write(buffer, 0, 1);
  205. }
  206. public virtual void Write(float value) {
  207. if (disposed)
  208. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  209. OutStream.Write(BitConverterLE.GetBytes(value), 0, 4);
  210. }
  211. byte [] stringBuffer;
  212. int maxCharsPerRound;
  213. public virtual void Write(string value) {
  214. if (disposed)
  215. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  216. int len = m_encoding.GetByteCount (value);
  217. Write7BitEncodedInt (len);
  218. if (stringBuffer == null) {
  219. stringBuffer = new byte [512];
  220. maxCharsPerRound = 512 / m_encoding.GetMaxByteCount (1);
  221. }
  222. int chpos = 0;
  223. int chrem = value.Length;
  224. while (chrem > 0) {
  225. int cch = (chrem > maxCharsPerRound) ? maxCharsPerRound : chrem;
  226. int blen = m_encoding.GetBytes (value, chpos, cch, stringBuffer, 0);
  227. OutStream.Write (stringBuffer, 0, blen);
  228. chpos += cch;
  229. chrem -= cch;
  230. }
  231. }
  232. [CLSCompliant(false)]
  233. public virtual void Write(ushort value) {
  234. if (disposed)
  235. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  236. buffer [0] = (byte) value;
  237. buffer [1] = (byte) (value >> 8);
  238. OutStream.Write(buffer, 0, 2);
  239. }
  240. [CLSCompliant(false)]
  241. public virtual void Write(uint value) {
  242. if (disposed)
  243. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  244. buffer [0] = (byte) value;
  245. buffer [1] = (byte) (value >> 8);
  246. buffer [2] = (byte) (value >> 16);
  247. buffer [3] = (byte) (value >> 24);
  248. OutStream.Write(buffer, 0, 4);
  249. }
  250. [CLSCompliant(false)]
  251. public virtual void Write(ulong value) {
  252. if (disposed)
  253. throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
  254. for (int i = 0, sh = 0; i < 8; i++, sh += 8)
  255. buffer [i] = (byte) (value >> sh);
  256. OutStream.Write(buffer, 0, 8);
  257. }
  258. protected void Write7BitEncodedInt(int value) {
  259. do {
  260. int high = (value >> 7) & 0x01ffffff;
  261. byte b = (byte)(value & 0x7f);
  262. if (high != 0) {
  263. b = (byte)(b | 0x80);
  264. }
  265. Write(b);
  266. value = high;
  267. } while(value != 0);
  268. }
  269. }
  270. }