DeflateStream.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. // DeflateStream.cs
  2. // ------------------------------------------------------------------
  3. //
  4. // Copyright (c) 2009-2010 Dino Chiesa.
  5. // All rights reserved.
  6. //
  7. // This code module is part of DotNetZip, a zipfile class library.
  8. //
  9. // ------------------------------------------------------------------
  10. //
  11. // This code is licensed under the Microsoft Public License.
  12. // See the file License.txt for the license details.
  13. // More info on: http://dotnetzip.codeplex.com
  14. //
  15. // ------------------------------------------------------------------
  16. //
  17. // last saved (in emacs):
  18. // Time-stamp: <2011-July-31 14:48:11>
  19. //
  20. // ------------------------------------------------------------------
  21. //
  22. // This module defines the DeflateStream class, which can be used as a replacement for
  23. // the System.IO.Compression.DeflateStream class in the .NET BCL.
  24. //
  25. // ------------------------------------------------------------------
  26. using System;
  27. namespace BestHTTP.Decompression.Zlib
  28. {
  29. /// <summary>
  30. /// A class for compressing and decompressing streams using the Deflate algorithm.
  31. /// </summary>
  32. ///
  33. /// <remarks>
  34. ///
  35. /// <para>
  36. /// The DeflateStream is a <see
  37. /// href="http://en.wikipedia.org/wiki/Decorator_pattern">Decorator</see> on a <see
  38. /// cref="System.IO.Stream"/>. It adds DEFLATE compression or decompression to any
  39. /// stream.
  40. /// </para>
  41. ///
  42. /// <para>
  43. /// Using this stream, applications can compress or decompress data via stream
  44. /// <c>Read</c> and <c>Write</c> operations. Either compresssion or decompression
  45. /// can occur through either reading or writing. The compression format used is
  46. /// DEFLATE, which is documented in <see
  47. /// href="http://www.ietf.org/rfc/rfc1951.txt">IETF RFC 1951</see>, "DEFLATE
  48. /// Compressed Data Format Specification version 1.3.".
  49. /// </para>
  50. ///
  51. /// </remarks>
  52. ///
  53. /// <seealso cref="GZipStream" />
  54. internal class DeflateStream : System.IO.Stream
  55. {
  56. internal ZlibBaseStream _baseStream;
  57. internal System.IO.Stream _innerStream;
  58. bool _disposed;
  59. /// <summary>
  60. /// Create a DeflateStream using the specified CompressionMode.
  61. /// </summary>
  62. ///
  63. /// <remarks>
  64. /// When mode is <c>CompressionMode.Compress</c>, the DeflateStream will use
  65. /// the default compression level. The "captive" stream will be closed when
  66. /// the DeflateStream is closed.
  67. /// </remarks>
  68. ///
  69. /// <example>
  70. /// This example uses a DeflateStream to compress data from a file, and writes
  71. /// the compressed data to another file.
  72. /// <code>
  73. /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress))
  74. /// {
  75. /// using (var raw = System.IO.File.Create(fileToCompress + ".deflated"))
  76. /// {
  77. /// using (Stream compressor = new DeflateStream(raw, CompressionMode.Compress))
  78. /// {
  79. /// byte[] buffer = new byte[WORKING_BUFFER_SIZE];
  80. /// int n;
  81. /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0)
  82. /// {
  83. /// compressor.Write(buffer, 0, n);
  84. /// }
  85. /// }
  86. /// }
  87. /// }
  88. /// </code>
  89. ///
  90. /// <code lang="VB">
  91. /// Using input As Stream = File.OpenRead(fileToCompress)
  92. /// Using raw As FileStream = File.Create(fileToCompress &amp; ".deflated")
  93. /// Using compressor As Stream = New DeflateStream(raw, CompressionMode.Compress)
  94. /// Dim buffer As Byte() = New Byte(4096) {}
  95. /// Dim n As Integer = -1
  96. /// Do While (n &lt;&gt; 0)
  97. /// If (n &gt; 0) Then
  98. /// compressor.Write(buffer, 0, n)
  99. /// End If
  100. /// n = input.Read(buffer, 0, buffer.Length)
  101. /// Loop
  102. /// End Using
  103. /// End Using
  104. /// End Using
  105. /// </code>
  106. /// </example>
  107. /// <param name="stream">The stream which will be read or written.</param>
  108. /// <param name="mode">Indicates whether the DeflateStream will compress or decompress.</param>
  109. public DeflateStream(System.IO.Stream stream, CompressionMode mode)
  110. : this(stream, mode, CompressionLevel.Default, false)
  111. {
  112. }
  113. /// <summary>
  114. /// Create a DeflateStream using the specified CompressionMode and the specified CompressionLevel.
  115. /// </summary>
  116. ///
  117. /// <remarks>
  118. ///
  119. /// <para>
  120. /// When mode is <c>CompressionMode.Decompress</c>, the level parameter is
  121. /// ignored. The "captive" stream will be closed when the DeflateStream is
  122. /// closed.
  123. /// </para>
  124. ///
  125. /// </remarks>
  126. ///
  127. /// <example>
  128. ///
  129. /// This example uses a DeflateStream to compress data from a file, and writes
  130. /// the compressed data to another file.
  131. ///
  132. /// <code>
  133. /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress))
  134. /// {
  135. /// using (var raw = System.IO.File.Create(fileToCompress + ".deflated"))
  136. /// {
  137. /// using (Stream compressor = new DeflateStream(raw,
  138. /// CompressionMode.Compress,
  139. /// CompressionLevel.BestCompression))
  140. /// {
  141. /// byte[] buffer = new byte[WORKING_BUFFER_SIZE];
  142. /// int n= -1;
  143. /// while (n != 0)
  144. /// {
  145. /// if (n &gt; 0)
  146. /// compressor.Write(buffer, 0, n);
  147. /// n= input.Read(buffer, 0, buffer.Length);
  148. /// }
  149. /// }
  150. /// }
  151. /// }
  152. /// </code>
  153. ///
  154. /// <code lang="VB">
  155. /// Using input As Stream = File.OpenRead(fileToCompress)
  156. /// Using raw As FileStream = File.Create(fileToCompress &amp; ".deflated")
  157. /// Using compressor As Stream = New DeflateStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression)
  158. /// Dim buffer As Byte() = New Byte(4096) {}
  159. /// Dim n As Integer = -1
  160. /// Do While (n &lt;&gt; 0)
  161. /// If (n &gt; 0) Then
  162. /// compressor.Write(buffer, 0, n)
  163. /// End If
  164. /// n = input.Read(buffer, 0, buffer.Length)
  165. /// Loop
  166. /// End Using
  167. /// End Using
  168. /// End Using
  169. /// </code>
  170. /// </example>
  171. /// <param name="stream">The stream to be read or written while deflating or inflating.</param>
  172. /// <param name="mode">Indicates whether the <c>DeflateStream</c> will compress or decompress.</param>
  173. /// <param name="level">A tuning knob to trade speed for effectiveness.</param>
  174. public DeflateStream(System.IO.Stream stream, CompressionMode mode, CompressionLevel level)
  175. : this(stream, mode, level, false)
  176. {
  177. }
  178. /// <summary>
  179. /// Create a <c>DeflateStream</c> using the specified
  180. /// <c>CompressionMode</c>, and explicitly specify whether the
  181. /// stream should be left open after Deflation or Inflation.
  182. /// </summary>
  183. ///
  184. /// <remarks>
  185. ///
  186. /// <para>
  187. /// This constructor allows the application to request that the captive stream
  188. /// remain open after the deflation or inflation occurs. By default, after
  189. /// <c>Close()</c> is called on the stream, the captive stream is also
  190. /// closed. In some cases this is not desired, for example if the stream is a
  191. /// memory stream that will be re-read after compression. Specify true for
  192. /// the <paramref name="leaveOpen"/> parameter to leave the stream open.
  193. /// </para>
  194. ///
  195. /// <para>
  196. /// The <c>DeflateStream</c> will use the default compression level.
  197. /// </para>
  198. ///
  199. /// <para>
  200. /// See the other overloads of this constructor for example code.
  201. /// </para>
  202. /// </remarks>
  203. ///
  204. /// <param name="stream">
  205. /// The stream which will be read or written. This is called the
  206. /// "captive" stream in other places in this documentation.
  207. /// </param>
  208. ///
  209. /// <param name="mode">
  210. /// Indicates whether the <c>DeflateStream</c> will compress or decompress.
  211. /// </param>
  212. ///
  213. /// <param name="leaveOpen">true if the application would like the stream to
  214. /// remain open after inflation/deflation.</param>
  215. public DeflateStream(System.IO.Stream stream, CompressionMode mode, bool leaveOpen)
  216. : this(stream, mode, CompressionLevel.Default, leaveOpen)
  217. {
  218. }
  219. /// <summary>
  220. /// Create a <c>DeflateStream</c> using the specified <c>CompressionMode</c>
  221. /// and the specified <c>CompressionLevel</c>, and explicitly specify whether
  222. /// the stream should be left open after Deflation or Inflation.
  223. /// </summary>
  224. ///
  225. /// <remarks>
  226. ///
  227. /// <para>
  228. /// When mode is <c>CompressionMode.Decompress</c>, the level parameter is ignored.
  229. /// </para>
  230. ///
  231. /// <para>
  232. /// This constructor allows the application to request that the captive stream
  233. /// remain open after the deflation or inflation occurs. By default, after
  234. /// <c>Close()</c> is called on the stream, the captive stream is also
  235. /// closed. In some cases this is not desired, for example if the stream is a
  236. /// <see cref="System.IO.MemoryStream"/> that will be re-read after
  237. /// compression. Specify true for the <paramref name="leaveOpen"/> parameter
  238. /// to leave the stream open.
  239. /// </para>
  240. ///
  241. /// </remarks>
  242. ///
  243. /// <example>
  244. ///
  245. /// This example shows how to use a <c>DeflateStream</c> to compress data from
  246. /// a file, and store the compressed data into another file.
  247. ///
  248. /// <code>
  249. /// using (var output = System.IO.File.Create(fileToCompress + ".deflated"))
  250. /// {
  251. /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress))
  252. /// {
  253. /// using (Stream compressor = new DeflateStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, true))
  254. /// {
  255. /// byte[] buffer = new byte[WORKING_BUFFER_SIZE];
  256. /// int n= -1;
  257. /// while (n != 0)
  258. /// {
  259. /// if (n &gt; 0)
  260. /// compressor.Write(buffer, 0, n);
  261. /// n= input.Read(buffer, 0, buffer.Length);
  262. /// }
  263. /// }
  264. /// }
  265. /// // can write additional data to the output stream here
  266. /// }
  267. /// </code>
  268. ///
  269. /// <code lang="VB">
  270. /// Using output As FileStream = File.Create(fileToCompress &amp; ".deflated")
  271. /// Using input As Stream = File.OpenRead(fileToCompress)
  272. /// Using compressor As Stream = New DeflateStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, True)
  273. /// Dim buffer As Byte() = New Byte(4096) {}
  274. /// Dim n As Integer = -1
  275. /// Do While (n &lt;&gt; 0)
  276. /// If (n &gt; 0) Then
  277. /// compressor.Write(buffer, 0, n)
  278. /// End If
  279. /// n = input.Read(buffer, 0, buffer.Length)
  280. /// Loop
  281. /// End Using
  282. /// End Using
  283. /// ' can write additional data to the output stream here.
  284. /// End Using
  285. /// </code>
  286. /// </example>
  287. /// <param name="stream">The stream which will be read or written.</param>
  288. /// <param name="mode">Indicates whether the DeflateStream will compress or decompress.</param>
  289. /// <param name="leaveOpen">true if the application would like the stream to remain open after inflation/deflation.</param>
  290. /// <param name="level">A tuning knob to trade speed for effectiveness.</param>
  291. public DeflateStream(System.IO.Stream stream, CompressionMode mode, CompressionLevel level, bool leaveOpen)
  292. {
  293. _innerStream = stream;
  294. _baseStream = new ZlibBaseStream(stream, mode, level, ZlibStreamFlavor.DEFLATE, leaveOpen);
  295. }
  296. /// <summary>
  297. /// Create a <c>DeflateStream</c> using the specified <c>CompressionMode</c>
  298. /// and the specified <c>CompressionLevel</c>, and explicitly specify whether
  299. /// the stream should be left open after Deflation or Inflation.
  300. /// </summary>
  301. ///
  302. /// <remarks>
  303. ///
  304. /// <para>
  305. /// When mode is <c>CompressionMode.Decompress</c>, the level parameter is ignored.
  306. /// </para>
  307. ///
  308. /// <para>
  309. /// This constructor allows the application to request that the captive stream
  310. /// remain open after the deflation or inflation occurs. By default, after
  311. /// <c>Close()</c> is called on the stream, the captive stream is also
  312. /// closed. In some cases this is not desired, for example if the stream is a
  313. /// <see cref="System.IO.MemoryStream"/> that will be re-read after
  314. /// compression. Specify true for the <paramref name="leaveOpen"/> parameter
  315. /// to leave the stream open.
  316. /// </para>
  317. ///
  318. /// </remarks>
  319. ///
  320. /// <example>
  321. ///
  322. /// This example shows how to use a <c>DeflateStream</c> to compress data from
  323. /// a file, and store the compressed data into another file.
  324. ///
  325. /// <code>
  326. /// using (var output = System.IO.File.Create(fileToCompress + ".deflated"))
  327. /// {
  328. /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress))
  329. /// {
  330. /// using (Stream compressor = new DeflateStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, true))
  331. /// {
  332. /// byte[] buffer = new byte[WORKING_BUFFER_SIZE];
  333. /// int n= -1;
  334. /// while (n != 0)
  335. /// {
  336. /// if (n &gt; 0)
  337. /// compressor.Write(buffer, 0, n);
  338. /// n= input.Read(buffer, 0, buffer.Length);
  339. /// }
  340. /// }
  341. /// }
  342. /// // can write additional data to the output stream here
  343. /// }
  344. /// </code>
  345. ///
  346. /// <code lang="VB">
  347. /// Using output As FileStream = File.Create(fileToCompress &amp; ".deflated")
  348. /// Using input As Stream = File.OpenRead(fileToCompress)
  349. /// Using compressor As Stream = New DeflateStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, True)
  350. /// Dim buffer As Byte() = New Byte(4096) {}
  351. /// Dim n As Integer = -1
  352. /// Do While (n &lt;&gt; 0)
  353. /// If (n &gt; 0) Then
  354. /// compressor.Write(buffer, 0, n)
  355. /// End If
  356. /// n = input.Read(buffer, 0, buffer.Length)
  357. /// Loop
  358. /// End Using
  359. /// End Using
  360. /// ' can write additional data to the output stream here.
  361. /// End Using
  362. /// </code>
  363. /// </example>
  364. /// <param name="stream">The stream which will be read or written.</param>
  365. /// <param name="mode">Indicates whether the DeflateStream will compress or decompress.</param>
  366. /// <param name="leaveOpen">true if the application would like the stream to remain open after inflation/deflation.</param>
  367. /// <param name="level">A tuning knob to trade speed for effectiveness.</param>
  368. /// <param name="windowBits">Desired window bits.</param>
  369. public DeflateStream(System.IO.Stream stream, CompressionMode mode, CompressionLevel level, bool leaveOpen, int windowBits)
  370. {
  371. _innerStream = stream;
  372. _baseStream = new ZlibBaseStream(stream, mode, level, ZlibStreamFlavor.DEFLATE, leaveOpen, windowBits);
  373. }
  374. #region Zlib properties
  375. /// <summary>
  376. /// This property sets the flush behavior on the stream.
  377. /// </summary>
  378. /// <remarks> See the ZLIB documentation for the meaning of the flush behavior.
  379. /// </remarks>
  380. virtual public FlushType FlushMode
  381. {
  382. get { return (this._baseStream._flushMode); }
  383. set
  384. {
  385. if (_disposed) throw new ObjectDisposedException("DeflateStream");
  386. this._baseStream._flushMode = value;
  387. }
  388. }
  389. /// <summary>
  390. /// The size of the working buffer for the compression codec.
  391. /// </summary>
  392. ///
  393. /// <remarks>
  394. /// <para>
  395. /// The working buffer is used for all stream operations. The default size is
  396. /// 1024 bytes. The minimum size is 128 bytes. You may get better performance
  397. /// with a larger buffer. Then again, you might not. You would have to test
  398. /// it.
  399. /// </para>
  400. ///
  401. /// <para>
  402. /// Set this before the first call to <c>Read()</c> or <c>Write()</c> on the
  403. /// stream. If you try to set it afterwards, it will throw.
  404. /// </para>
  405. /// </remarks>
  406. public int BufferSize
  407. {
  408. get
  409. {
  410. return this._baseStream._bufferSize;
  411. }
  412. set
  413. {
  414. if (_disposed) throw new ObjectDisposedException("DeflateStream");
  415. if (this._baseStream._workingBuffer != null)
  416. throw new ZlibException("The working buffer is already set.");
  417. if (value < ZlibConstants.WorkingBufferSizeMin)
  418. throw new ZlibException(String.Format("Don't be silly. {0} bytes?? Use a bigger buffer, at least {1}.", value, ZlibConstants.WorkingBufferSizeMin));
  419. this._baseStream._bufferSize = value;
  420. }
  421. }
  422. /// <summary>
  423. /// The ZLIB strategy to be used during compression.
  424. /// </summary>
  425. ///
  426. /// <remarks>
  427. /// By tweaking this parameter, you may be able to optimize the compression for
  428. /// data with particular characteristics.
  429. /// </remarks>
  430. public CompressionStrategy Strategy
  431. {
  432. get
  433. {
  434. return this._baseStream.Strategy;
  435. }
  436. set
  437. {
  438. if (_disposed) throw new ObjectDisposedException("DeflateStream");
  439. this._baseStream.Strategy = value;
  440. }
  441. }
  442. /// <summary> Returns the total number of bytes input so far.</summary>
  443. virtual public long TotalIn
  444. {
  445. get
  446. {
  447. return this._baseStream._z.TotalBytesIn;
  448. }
  449. }
  450. /// <summary> Returns the total number of bytes output so far.</summary>
  451. virtual public long TotalOut
  452. {
  453. get
  454. {
  455. return this._baseStream._z.TotalBytesOut;
  456. }
  457. }
  458. #endregion
  459. #region System.IO.Stream methods
  460. /// <summary>
  461. /// Dispose the stream.
  462. /// </summary>
  463. /// <remarks>
  464. /// <para>
  465. /// This may or may not result in a <c>Close()</c> call on the captive
  466. /// stream. See the constructors that have a <c>leaveOpen</c> parameter
  467. /// for more information.
  468. /// </para>
  469. /// <para>
  470. /// Application code won't call this code directly. This method may be
  471. /// invoked in two distinct scenarios. If disposing == true, the method
  472. /// has been called directly or indirectly by a user's code, for example
  473. /// via the public Dispose() method. In this case, both managed and
  474. /// unmanaged resources can be referenced and disposed. If disposing ==
  475. /// false, the method has been called by the runtime from inside the
  476. /// object finalizer and this method should not reference other objects;
  477. /// in that case only unmanaged resources must be referenced or
  478. /// disposed.
  479. /// </para>
  480. /// </remarks>
  481. /// <param name="disposing">
  482. /// true if the Dispose method was invoked by user code.
  483. /// </param>
  484. protected override void Dispose(bool disposing)
  485. {
  486. try
  487. {
  488. if (!_disposed)
  489. {
  490. if (disposing && (this._baseStream != null))
  491. this._baseStream.Close();
  492. _disposed = true;
  493. }
  494. }
  495. finally
  496. {
  497. base.Dispose(disposing);
  498. }
  499. }
  500. /// <summary>
  501. /// Indicates whether the stream can be read.
  502. /// </summary>
  503. /// <remarks>
  504. /// The return value depends on whether the captive stream supports reading.
  505. /// </remarks>
  506. public override bool CanRead
  507. {
  508. get
  509. {
  510. if (_disposed) throw new ObjectDisposedException("DeflateStream");
  511. return _baseStream._stream.CanRead;
  512. }
  513. }
  514. /// <summary>
  515. /// Indicates whether the stream supports Seek operations.
  516. /// </summary>
  517. /// <remarks>
  518. /// Always returns false.
  519. /// </remarks>
  520. public override bool CanSeek
  521. {
  522. get { return false; }
  523. }
  524. /// <summary>
  525. /// Indicates whether the stream can be written.
  526. /// </summary>
  527. /// <remarks>
  528. /// The return value depends on whether the captive stream supports writing.
  529. /// </remarks>
  530. public override bool CanWrite
  531. {
  532. get
  533. {
  534. if (_disposed) throw new ObjectDisposedException("DeflateStream");
  535. return _baseStream._stream.CanWrite;
  536. }
  537. }
  538. /// <summary>
  539. /// Flush the stream.
  540. /// </summary>
  541. public override void Flush()
  542. {
  543. if (_disposed) throw new ObjectDisposedException("DeflateStream");
  544. _baseStream.Flush();
  545. }
  546. /// <summary>
  547. /// Reading this property always throws a <see cref="NotImplementedException"/>.
  548. /// </summary>
  549. public override long Length
  550. {
  551. get { throw new NotImplementedException(); }
  552. }
  553. /// <summary>
  554. /// The position of the stream pointer.
  555. /// </summary>
  556. ///
  557. /// <remarks>
  558. /// Setting this property always throws a <see
  559. /// cref="NotImplementedException"/>. Reading will return the total bytes
  560. /// written out, if used in writing, or the total bytes read in, if used in
  561. /// reading. The count may refer to compressed bytes or uncompressed bytes,
  562. /// depending on how you've used the stream.
  563. /// </remarks>
  564. public override long Position
  565. {
  566. get
  567. {
  568. if (this._baseStream._streamMode == BestHTTP.Decompression.Zlib.ZlibBaseStream.StreamMode.Writer)
  569. return this._baseStream._z.TotalBytesOut;
  570. if (this._baseStream._streamMode == BestHTTP.Decompression.Zlib.ZlibBaseStream.StreamMode.Reader)
  571. return this._baseStream._z.TotalBytesIn;
  572. return 0;
  573. }
  574. set { throw new NotImplementedException(); }
  575. }
  576. /// <summary>
  577. /// Read data from the stream.
  578. /// </summary>
  579. /// <remarks>
  580. ///
  581. /// <para>
  582. /// If you wish to use the <c>DeflateStream</c> to compress data while
  583. /// reading, you can create a <c>DeflateStream</c> with
  584. /// <c>CompressionMode.Compress</c>, providing an uncompressed data stream.
  585. /// Then call Read() on that <c>DeflateStream</c>, and the data read will be
  586. /// compressed as you read. If you wish to use the <c>DeflateStream</c> to
  587. /// decompress data while reading, you can create a <c>DeflateStream</c> with
  588. /// <c>CompressionMode.Decompress</c>, providing a readable compressed data
  589. /// stream. Then call Read() on that <c>DeflateStream</c>, and the data read
  590. /// will be decompressed as you read.
  591. /// </para>
  592. ///
  593. /// <para>
  594. /// A <c>DeflateStream</c> can be used for <c>Read()</c> or <c>Write()</c>, but not both.
  595. /// </para>
  596. ///
  597. /// </remarks>
  598. /// <param name="buffer">The buffer into which the read data should be placed.</param>
  599. /// <param name="offset">the offset within that data array to put the first byte read.</param>
  600. /// <param name="count">the number of bytes to read.</param>
  601. /// <returns>the number of bytes actually read</returns>
  602. public override int Read(byte[] buffer, int offset, int count)
  603. {
  604. if (_disposed) throw new ObjectDisposedException("DeflateStream");
  605. return _baseStream.Read(buffer, offset, count);
  606. }
  607. /// <summary>
  608. /// Calling this method always throws a <see cref="NotImplementedException"/>.
  609. /// </summary>
  610. /// <param name="offset">this is irrelevant, since it will always throw!</param>
  611. /// <param name="origin">this is irrelevant, since it will always throw!</param>
  612. /// <returns>irrelevant!</returns>
  613. public override long Seek(long offset, System.IO.SeekOrigin origin)
  614. {
  615. throw new NotImplementedException();
  616. }
  617. /// <summary>
  618. /// Will call the base stream's SetLength method.
  619. /// </summary>
  620. public override void SetLength(long value)
  621. {
  622. _baseStream.SetLength(value);
  623. }
  624. /// <summary>
  625. /// Write data to the stream.
  626. /// </summary>
  627. /// <remarks>
  628. ///
  629. /// <para>
  630. /// If you wish to use the <c>DeflateStream</c> to compress data while
  631. /// writing, you can create a <c>DeflateStream</c> with
  632. /// <c>CompressionMode.Compress</c>, and a writable output stream. Then call
  633. /// <c>Write()</c> on that <c>DeflateStream</c>, providing uncompressed data
  634. /// as input. The data sent to the output stream will be the compressed form
  635. /// of the data written. If you wish to use the <c>DeflateStream</c> to
  636. /// decompress data while writing, you can create a <c>DeflateStream</c> with
  637. /// <c>CompressionMode.Decompress</c>, and a writable output stream. Then
  638. /// call <c>Write()</c> on that stream, providing previously compressed
  639. /// data. The data sent to the output stream will be the decompressed form of
  640. /// the data written.
  641. /// </para>
  642. ///
  643. /// <para>
  644. /// A <c>DeflateStream</c> can be used for <c>Read()</c> or <c>Write()</c>,
  645. /// but not both.
  646. /// </para>
  647. ///
  648. /// </remarks>
  649. ///
  650. /// <param name="buffer">The buffer holding data to write to the stream.</param>
  651. /// <param name="offset">the offset within that data array to find the first byte to write.</param>
  652. /// <param name="count">the number of bytes to write.</param>
  653. public override void Write(byte[] buffer, int offset, int count)
  654. {
  655. if (_disposed) throw new ObjectDisposedException("DeflateStream");
  656. _baseStream.Write(buffer, offset, count);
  657. }
  658. #endregion
  659. /// <summary>
  660. /// Compress a string into a byte array using DEFLATE (RFC 1951).
  661. /// </summary>
  662. ///
  663. /// <remarks>
  664. /// Uncompress it with <see cref="DeflateStream.UncompressString(byte[])"/>.
  665. /// </remarks>
  666. ///
  667. /// <seealso cref="DeflateStream.UncompressString(byte[])">DeflateStream.UncompressString(byte[])</seealso>
  668. /// <seealso cref="DeflateStream.CompressBuffer(byte[])">DeflateStream.CompressBuffer(byte[])</seealso>
  669. /// <seealso cref="GZipStream.CompressString(string)">GZipStream.CompressString(string)</seealso>
  670. ///
  671. /// <param name="s">
  672. /// A string to compress. The string will first be encoded
  673. /// using UTF8, then compressed.
  674. /// </param>
  675. ///
  676. /// <returns>The string in compressed form</returns>
  677. public static byte[] CompressString(String s)
  678. {
  679. using (var ms = new System.IO.MemoryStream())
  680. {
  681. System.IO.Stream compressor =
  682. new DeflateStream(ms, CompressionMode.Compress, CompressionLevel.BestCompression);
  683. ZlibBaseStream.CompressString(s, compressor);
  684. return ms.ToArray();
  685. }
  686. }
  687. /// <summary>
  688. /// Compress a byte array into a new byte array using DEFLATE.
  689. /// </summary>
  690. ///
  691. /// <remarks>
  692. /// Uncompress it with <see cref="DeflateStream.UncompressBuffer(byte[])"/>.
  693. /// </remarks>
  694. ///
  695. /// <seealso cref="DeflateStream.CompressString(string)">DeflateStream.CompressString(string)</seealso>
  696. /// <seealso cref="DeflateStream.UncompressBuffer(byte[])">DeflateStream.UncompressBuffer(byte[])</seealso>
  697. /// <seealso cref="GZipStream.CompressBuffer(byte[])">GZipStream.CompressBuffer(byte[])</seealso>
  698. ///
  699. /// <param name="b">
  700. /// A buffer to compress.
  701. /// </param>
  702. ///
  703. /// <returns>The data in compressed form</returns>
  704. public static byte[] CompressBuffer(byte[] b)
  705. {
  706. using (var ms = new System.IO.MemoryStream())
  707. {
  708. System.IO.Stream compressor =
  709. new DeflateStream( ms, CompressionMode.Compress, CompressionLevel.BestCompression );
  710. ZlibBaseStream.CompressBuffer(b, compressor);
  711. return ms.ToArray();
  712. }
  713. }
  714. /// <summary>
  715. /// Uncompress a DEFLATE'd byte array into a single string.
  716. /// </summary>
  717. ///
  718. /// <seealso cref="DeflateStream.CompressString(String)">DeflateStream.CompressString(String)</seealso>
  719. /// <seealso cref="DeflateStream.UncompressBuffer(byte[])">DeflateStream.UncompressBuffer(byte[])</seealso>
  720. /// <seealso cref="GZipStream.UncompressString(byte[])">GZipStream.UncompressString(byte[])</seealso>
  721. ///
  722. /// <param name="compressed">
  723. /// A buffer containing DEFLATE-compressed data.
  724. /// </param>
  725. ///
  726. /// <returns>The uncompressed string</returns>
  727. public static String UncompressString(byte[] compressed)
  728. {
  729. using (var input = new System.IO.MemoryStream(compressed))
  730. {
  731. System.IO.Stream decompressor =
  732. new DeflateStream(input, CompressionMode.Decompress);
  733. return ZlibBaseStream.UncompressString(compressed, decompressor);
  734. }
  735. }
  736. /// <summary>
  737. /// Uncompress a DEFLATE'd byte array into a byte array.
  738. /// </summary>
  739. ///
  740. /// <seealso cref="DeflateStream.CompressBuffer(byte[])">DeflateStream.CompressBuffer(byte[])</seealso>
  741. /// <seealso cref="DeflateStream.UncompressString(byte[])">DeflateStream.UncompressString(byte[])</seealso>
  742. /// <seealso cref="GZipStream.UncompressBuffer(byte[])">GZipStream.UncompressBuffer(byte[])</seealso>
  743. ///
  744. /// <param name="compressed">
  745. /// A buffer containing data that has been compressed with DEFLATE.
  746. /// </param>
  747. ///
  748. /// <returns>The data in uncompressed form</returns>
  749. public static byte[] UncompressBuffer(byte[] compressed)
  750. {
  751. using (var input = new System.IO.MemoryStream(compressed))
  752. {
  753. System.IO.Stream decompressor = new DeflateStream( input, CompressionMode.Decompress );
  754. return ZlibBaseStream.UncompressBuffer(compressed, decompressor);
  755. }
  756. }
  757. }
  758. }