Beispiel #1
0
		/// <summary>
		/// Similar to
		/// <see cref="EncodeBytes(byte[], int, int, int)">EncodeBytes(byte[], int, int, int)
		/// 	</see>
		/// but returns
		/// a byte array instead of instantiating a String. This is more efficient
		/// if you're working with I/O streams and have large data sets to encode.
		/// </summary>
		/// <param name="source">The data to convert</param>
		/// <param name="off">Offset in array where conversion should begin</param>
		/// <param name="len">Length of data to convert</param>
		/// <param name="options">Specified options</param>
		/// <returns>The Base64-encoded data as a String</returns>
		/// <seealso cref="Gzip">Gzip</seealso>
		/// <seealso cref="DoBreakLines">DoBreakLines</seealso>
		/// <exception cref="System.IO.IOException">if there is an error</exception>
		/// <exception cref="System.ArgumentNullException">if source array is null</exception>
		/// <exception cref="System.ArgumentException">if source array, offset, or length are invalid
		/// 	</exception>
		/// <since>2.3.1</since>
		public static byte[] EncodeBytesToBytes(byte[] source, int off, int len, int options
			)
		{
			if (source == null)
			{
				throw new ArgumentNullException("Cannot serialize a null array.");
			}
			// end if: null
			if (off < 0)
			{
				throw new ArgumentException("Cannot have negative offset: " + off);
			}
			// end if: off < 0
			if (len < 0)
			{
				throw new ArgumentException("Cannot have length offset: " + len);
			}
			// end if: len < 0
			if (off + len > source.Length)
			{
				throw new ArgumentException(string.Format("Cannot have offset of %d and length of %d with array of length %d"
					, off, len, source.Length));
			}
			// end if: off < 0
			// Compress?
			if ((options & Gzip) != 0)
			{
				ByteArrayOutputStream baos = null;
				GZIPOutputStream gzos = null;
				Base64.OutputStream b64os = null;
				try
				{
					// GZip -> Base64 -> ByteArray
					baos = new ByteArrayOutputStream();
					b64os = new Base64.OutputStream(baos, Encode | options);
					gzos = new GZIPOutputStream(b64os);
					gzos.Write(source, off, len);
					gzos.Close();
				}
				catch (IOException e)
				{
					// end try
					// Catch it and then throw it immediately so that
					// the finally{} block is called for cleanup.
					throw;
				}
				finally
				{
					// end catch
					try
					{
						gzos.Close();
					}
					catch (Exception)
					{
					}
					try
					{
						b64os.Close();
					}
					catch (Exception)
					{
					}
					try
					{
						baos.Close();
					}
					catch (Exception)
					{
					}
				}
				// end finally
				return baos.ToByteArray();
			}
			else
			{
				// end if: compress
				// Else, don't compress. Better not to use streams at all then.
				bool breakLines = (options & DoBreakLines) != 0;
				//int    len43   = len * 4 / 3;
				//byte[] outBuff = new byte[   ( len43 )                      // Main 4:3
				//                           + ( (len % 3) > 0 ? 4 : 0 )      // Account for padding
				//                           + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines
				// Try to determine more precisely how big the array needs to be.
				// If we get it right, we don't have to do an array copy, and
				// we save a bunch of memory.
				int encLen = (len / 3) * 4 + (len % 3 > 0 ? 4 : 0);
				// Bytes needed for actual encoding
				if (breakLines)
				{
					encLen += encLen / MaxLineLength;
				}
				// Plus extra newline characters
				byte[] outBuff = new byte[encLen];
				int d = 0;
				int e = 0;
				int len2 = len - 2;
				int lineLength = 0;
				for (; d < len2; d += 3, e += 4)
				{
					Encode3to4(source, d + off, 3, outBuff, e, options);
					lineLength += 4;
					if (breakLines && lineLength >= MaxLineLength)
					{
						outBuff[e + 4] = NewLine;
						e++;
						lineLength = 0;
					}
				}
				// end if: end of line
				// en dfor: each piece of array
				if (d < len)
				{
					Encode3to4(source, d + off, len - d, outBuff, e, options);
					e += 4;
				}
				// end if: some padding needed
				// Only resize array if we didn't guess it right.
				if (e <= outBuff.Length - 1)
				{
					// If breaking lines and the last byte falls right at
					// the line length (76 bytes per line), there will be
					// one extra byte, and the array will need to be resized.
					// Not too bad of an estimate on array size, I'd say.
					byte[] finalOut = new byte[e];
					System.Array.Copy(outBuff, 0, finalOut, 0, e);
					//System.err.println("Having to resize array from " + outBuff.length + " to " + e );
					return finalOut;
				}
				else
				{
					//System.err.println("No need to resize array.");
					return outBuff;
				}
			}
		}