ZlibStream.cs 28 KB

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