// end encodeObject /// <summary> /// Serializes an object and returns the Base64-encoded /// version of that serialized object. /// </summary> /// <remarks> /// Serializes an object and returns the Base64-encoded /// version of that serialized object. /// <p>As of v 2.3, if the object /// cannot be serialized or there is another error, /// the method will throw an java.io.IOException. <b>This is new to v2.3!</b> /// In earlier versions, it just returned a null value, but /// in retrospect that's a pretty poor way to handle it.</p> /// The object is not GZip-compressed before being encoded. /// <p> /// Example options:<pre> /// GZIP: gzip-compresses object before encoding it. /// DO_BREAK_LINES: break lines at 76 characters /// </pre> /// <p> /// Example: <code>encodeObject( myObj, Base64.GZIP )</code> or /// <p> /// Example: <code>encodeObject( myObj, Base64.GZIP | Base64.DO_BREAK_LINES )</code> /// </remarks> /// <param name="serializableObject">The object to encode</param> /// <param name="options">Specified options</param> /// <returns>The Base64-encoded object</returns> /// <seealso cref="Gzip">Gzip</seealso> /// <seealso cref="DoBreakLines">DoBreakLines</seealso> /// <exception cref="System.IO.IOException">if there is an error</exception> /// <since>2.0</since> public static string EncodeObject(Serializable serializableObject, int options) { if (serializableObject == null) { throw new ArgumentNullException("Cannot serialize a null object."); } // end if: null // Streams ByteArrayOutputStream baos = null; OutputStream b64os = null; GZIPOutputStream gzos = null; ObjectOutputStream oos = null; try { // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream baos = new ByteArrayOutputStream(); b64os = new Base64.OutputStream(baos, Encode | options); if ((options & Gzip) != 0) { // Gzip gzos = new GZIPOutputStream(b64os); oos = new ObjectOutputStream(gzos); } else { // Not gzipped oos = new ObjectOutputStream(b64os); } oos.WriteObject(serializableObject); } 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 { oos.Close(); } catch (Exception) { } try { gzos.Close(); } catch (Exception) { } try { b64os.Close(); } catch (Exception) { } try { baos.Close(); } catch (Exception) { } } // end finally // Return value according to relevant encoding. try { return Sharpen.Runtime.GetStringForBytes(baos.ToByteArray(), PreferredEncoding); } catch (UnsupportedEncodingException) { // end try // Fall back to some Java default return Sharpen.Runtime.GetStringForBytes(baos.ToByteArray()); } }
/// <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; } } }