root/trunk/Updater/ICSharpCode.SharpZipLib/GZip/GzipOutputStream.cs @ 597

Wersja 597, 7.8 KB (wprowadzona przez marek, 17 years temu)

re #165

Line 
1// GZipOutputStream.cs
2//
3// Copyright (C) 2001 Mike Krueger
4//
5// This file was translated from java, it was part of the GNU Classpath
6// Copyright (C) 2001 Free Software Foundation, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21//
22// Linking this library statically or dynamically with other modules is
23// making a combined work based on this library.  Thus, the terms and
24// conditions of the GNU General Public License cover the whole
25// combination.
26//
27// As a special exception, the copyright holders of this library give you
28// permission to link this library with independent modules to produce an
29// executable, regardless of the license terms of these independent
30// modules, and to copy and distribute the resulting executable under
31// terms of your choice, provided that you also meet, for each linked
32// independent module, the terms and conditions of the license of that
33// module.  An independent module is a module which is not derived from
34// or based on this library.  If you modify this library, you may extend
35// this exception to your version of the library, but you are not
36// obligated to do so.  If you do not wish to do so, delete this
37// exception statement from your version.
38
39using System;
40using System.IO;
41
42using ICSharpCode.SharpZipLib.Checksums;
43using ICSharpCode.SharpZipLib.Zip.Compression;
44using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
45
46namespace ICSharpCode.SharpZipLib.GZip
47{
48       
49        /// <summary>
50        /// This filter stream is used to compress a stream into a "GZIP" stream.
51        /// The "GZIP" format is described in RFC 1952.
52        ///
53        /// author of the original java version : John Leuner
54        /// </summary>
55        /// <example> This sample shows how to gzip a file
56        /// <code>
57        /// using System;
58        /// using System.IO;
59        ///
60        /// using ICSharpCode.SharpZipLib.GZip;
61        /// using ICSharpCode.SharpZipLib.Core;
62        ///
63        /// class MainClass
64        /// {
65        ///     public static void Main(string[] args)
66        ///     {
67        ///                     using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz")))
68        ///                     using (FileStream fs = File.OpenRead(args[0])) {
69        ///                             byte[] writeData = new byte[4096];
70        ///                             Streamutils.Copy(s, fs, writeData);
71        ///                     }
72        ///             }
73        ///     }
74        /// }   
75        /// </code>
76        /// </example>
77        public class GZipOutputStream : DeflaterOutputStream
78        {
79        enum OutputState
80        {
81            Header,
82            Footer,
83            Finished,
84            Closed,
85        };
86
87                #region Instance Fields
88                /// <summary>
89                /// CRC-32 value for uncompressed data
90                /// </summary>
91                protected Crc32 crc = new Crc32();
92        OutputState state_ = OutputState.Header;
93                #endregion
94
95                #region Constructors
96                /// <summary>
97                /// Creates a GzipOutputStream with the default buffer size
98                /// </summary>
99                /// <param name="baseOutputStream">
100                /// The stream to read data (to be compressed) from
101                /// </param>
102                public GZipOutputStream(Stream baseOutputStream)
103                        : this(baseOutputStream, 4096)
104                {
105                }
106               
107                /// <summary>
108                /// Creates a GZipOutputStream with the specified buffer size
109                /// </summary>
110                /// <param name="baseOutputStream">
111                /// The stream to read data (to be compressed) from
112                /// </param>
113                /// <param name="size">
114                /// Size of the buffer to use
115                /// </param>
116                public GZipOutputStream(Stream baseOutputStream, int size) : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size)
117                {
118                }
119                #endregion
120       
121                #region Public API
122                /// <summary>
123                /// Sets the active compression level (1-9).  The new level will be activated
124                /// immediately.
125                /// </summary>
126                /// <param name="level">The compression level to set.</param>
127                /// <exception cref="ArgumentOutOfRangeException">
128                /// Level specified is not supported.
129                /// </exception>
130                /// <see cref="Deflater"/>
131                public void SetLevel(int level)
132                {
133                        if (level < Deflater.BEST_SPEED) {
134                                throw new ArgumentOutOfRangeException("level");
135                        }
136                        deflater_.SetLevel(level);
137                }
138               
139                /// <summary>
140                /// Get the current compression level.
141                /// </summary>
142                /// <returns>The current compression level.</returns>
143                public int GetLevel()
144                {
145                        return deflater_.GetLevel();
146                }
147                #endregion
148               
149                #region Stream overrides
150                /// <summary>
151                /// Write given buffer to output updating crc
152                /// </summary>
153                /// <param name="buffer">Buffer to write</param>
154                /// <param name="offset">Offset of first byte in buf to write</param>
155                /// <param name="count">Number of bytes to write</param>
156                public override void Write(byte[] buffer, int offset, int count)
157                {
158                        if ( state_ == OutputState.Header ) {
159                                WriteHeader();
160                        }
161
162            if( state_!=OutputState.Footer )
163            {
164                throw new InvalidOperationException("Write not permitted in current state");
165            }
166
167                        crc.Update(buffer, offset, count);
168                        base.Write(buffer, offset, count);
169                }
170               
171                /// <summary>
172                /// Writes remaining compressed output data to the output stream
173                /// and closes it.
174                /// </summary>
175                public override void Close()
176                {
177                        try {
178                                Finish();
179                        }
180                        finally {
181                if ( state_ != OutputState.Closed ) {
182                    state_ = OutputState.Closed;
183                                    if( IsStreamOwner ) {
184                                            baseOutputStream_.Close();
185                                    }
186                }
187                        }
188                }
189                #endregion
190               
191                #region DeflaterOutputStream overrides
192                /// <summary>
193                /// Finish compression and write any footer information required to stream
194                /// </summary>
195                public override void Finish()
196                {
197                        // If no data has been written a header should be added.
198                        if ( state_ == OutputState.Header ) {
199                                WriteHeader();
200                        }
201
202            if( state_ == OutputState.Footer)
203            {
204                state_=OutputState.Finished;
205                base.Finish();
206
207                uint totalin=(uint)(deflater_.TotalIn&0xffffffff);
208                uint crcval=(uint)(crc.Value&0xffffffff);
209
210                byte[] gzipFooter;
211
212                unchecked
213                {
214                    gzipFooter=new byte[] {
215                                        (byte) crcval, (byte) (crcval >> 8),
216                                        (byte) (crcval >> 16), (byte) (crcval >> 24),
217                                       
218                                        (byte) totalin, (byte) (totalin >> 8),
219                                        (byte) (totalin >> 16), (byte) (totalin >> 24)
220                                };
221                }
222
223                baseOutputStream_.Write(gzipFooter, 0, gzipFooter.Length);
224            }
225                }
226                #endregion
227               
228                #region Support Routines
229                void WriteHeader()
230                {
231                        if ( state_ == OutputState.Header )
232                        {
233                state_=OutputState.Footer;
234
235                                int mod_time = (int)((DateTime.Now.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000L);  // Ticks give back 100ns intervals
236                                byte[] gzipHeader = {
237                                        // The two magic bytes
238                                        (byte) (GZipConstants.GZIP_MAGIC >> 8), (byte) (GZipConstants.GZIP_MAGIC & 0xff),
239
240                                        // The compression type
241                                        (byte) Deflater.DEFLATED,
242
243                                        // The flags (not set)
244                                        0,
245
246                                        // The modification time
247                                        (byte) mod_time, (byte) (mod_time >> 8),
248                                        (byte) (mod_time >> 16), (byte) (mod_time >> 24),
249
250                                        // The extra flags
251                                        0,
252
253                                        // The OS type (unknown)
254                                        (byte) 255
255                                };
256                                baseOutputStream_.Write(gzipHeader, 0, gzipHeader.Length);
257                        }
258                }
259                #endregion
260        }
261}
Notatka: Zobacz TracBrowser aby uzyskać więcej informacji.