net.i2p.data

## Class DataHelper

- java.lang.Object
- - net.i2p.data.DataHelper

-     public class DataHelper
      extends Object

  Comprehensive utility class for I2P data structure serialization, encoding, and manipulation.

  DataHelper provides essential utilities for working with I2P data structures:

  - Serialization: Read/write primitive types to/from streams
  - Encoding: Base64 and Base32 encoding/decoding
  - Validation: Data format verification and bounds checking
  - Conversion: Between different data representations
  - Utilities: Common operations on collections and arrays

  Core Operations:

  - Primitive I/O: readLong(), writeLong(), readString(), writeString()
  - Base64: encode(), decode() with filesystem-safe variants
  - Base32: encodeBase32(), decodeBase32() for addresses
  - Properties: readProperties(), writeProperties() for metadata
  - Collections: toMap(), toString() for data structures

  Encoding Support:

  - Base64: Standard and URL-safe variants with/without padding
  - Base32: RFC 3548 compliant for .b32.i2p addresses
  - Hex: Hexadecimal encoding for debugging and display
  - UTF-8: String encoding with proper byte handling

  Data Structure Support:

  - Arrays: Efficient reading/writing of byte arrays
  - Collections: Map, List, and Set serialization
  - Dates: Timestamp handling with proper timezones
  - Properties: Key-value pair serialization

  Validation and Safety:

  - Bounds Checking: Prevent buffer overflows and underflows
  - Null Handling: Safe null value processing
  - Size Limits: Protection against excessive memory allocation
  - Format Validation: Data structure integrity checks

  Performance Features:

  - Buffer Reuse: ByteArrayStream for efficient operations
  - Caching: Frequently used constants and computations
  - Bulk Operations: Optimized for large data sets
  - Memory Management: Careful allocation and cleanup

  Common Use Cases:

  - Network Protocol: I2NP message serialization
  - Configuration: Properties file handling
  - Address Display: Base32 encoding for .b32.i2p
  - Data Storage: File format serialization
  - Debugging: Hex dumps and data inspection

  Thread Safety:

  - Static Methods: All operations are thread-safe
  - No State: Class maintains no mutable instance state
  - Immutable Data: Input data is not modified

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static int` | `DATE_LENGTH`
    `static int` | `HIGH_COMPRESSION` Appx.
    `static int` | `MAX_COMPRESSION` Appx.
    `static int` | `MAX_UNCOMPRESSED` Maximum uncompressed size.
    `static int` | `MEDIUM_COMPRESSION` New default as of 0.9.47
    `static int` | `NO_COMPRESSION`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `DataHelper()`

  - ### Method Summary

    All Methods Static Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `static int` | `compareTo(byte[] lhs, byte[] rhs)` Big endian compare, treats bytes as unsigned.
    `static byte[]` | `compress(byte[] orig)` Compress the data and return a new GZIP compressed byte array.
    `static byte[]` | `compress(byte[] orig, int offset, int size)` Compress the data and return a new GZIP compressed byte array.
    `static byte[]` | `compress(byte[] orig, int offset, int size, int level)` Compress the data and return a new GZIP compressed byte array.
    `static void` | `copy(InputStream in, OutputStream out)` Copy in to out.
    `static byte[]` | `decompress(byte[] orig)` Decompress the GZIP compressed data (returning null on error).
    `static byte[]` | `decompress(byte[] orig, int offset, int length)` Decompress the GZIP compressed data (returning null on error).
    `static boolean` | `eq(byte[] lhs, byte[] rhs)` Run a comparison on the byte arrays, byte by byte.
    `static boolean` | `eq(byte[] lhs, int offsetLeft, byte[] rhs, int offsetRight, int length)` Unlike eq(byte[], byte[]), this returns false if either lhs or rhs is null.
    `static boolean` | `eq(Collection<?> lhs, Collection<?> rhs)` Run a deep comparison across the two collections.
    `static boolean` | `eq(Object lhs, Object rhs)` Helper util to compare two objects, including null handling.
    `static boolean` | `eqCT(byte[] lhs, int offsetLeft, byte[] rhs, int offsetRight, int length)` Unlike eq(), this throws NPE if either lhs or rhs is null.
    `static String` | `escapeHTML(String unescaped)` Escape a string for inclusion in HTML
    `static String` | `formatDate(long now)` The default formatting for date, current locale, local time zone.
    `static String` | `formatDuration(long ms)` NOTE: formatDuration2() recommended in most cases for readability
    `static String` | `formatDuration2(double ms)` Like formatDuration2(long) but with microsec and nanosec also.
    `static String` | `formatDuration2(long ms)` Like formatDuration but with a non-breaking space after the number, 0 is unitless, and the unit is translated.
    `static String` | `formatSize(long bytes)` This is binary, i.e.
    `static String` | `formatSize2(long bytes)` This is binary, i.e.
    `static String` | `formatSize2(long bytes, boolean nonBreaking)` This is binary, i.e.
    `static String` | `formatSize2Decimal(long bytes)` This is decimal, i.e.
    `static String` | `formatSize2Decimal(long bytes, boolean nonBreaking)` This is decimal, i.e.
    `static String` | `formatTime(long now)` The default formatting for date/time, current locale, local time zone.
    `static Date` | `fromDate(byte[] src, int offset)`
    `static long` | `fromLong(byte[] src, int offset, int numBytes)` Big endian.
    `static long` | `fromLong8(byte[] src, int offset)` Big endian.
    `static long` | `fromLongLE(byte[] src, int offset, int numBytes)` Little endian, i.e.
    `static int` | `fromProperties(byte[] source, int offset, Properties target)` Reads the props from the byte array and puts them in the Properties target See readProperties() for the format.
    `static byte[]` | `getASCII(String orig)` Roughly the same as orig.getBytes("ISO-8859-1") but much faster and will not throw an exception.
    `static String` | `getUTF8(byte[] orig)` Same as new String(orig, "UTF-8") but throws an unchecked RuntimeException instead of an UnsupportedEncodingException if no UTF-8, for ease of use.
    `static String` | `getUTF8(byte[] orig, int offset, int len)` Same as new String(orig, "UTF-8") but throws an unchecked RuntimeException instead of an UnsupportedEncodingException if no UTF-8, for ease of use.
    `static byte[]` | `getUTF8(String orig)` Same as orig.getBytes("UTF-8") but throws an unchecked RuntimeException instead of an UnsupportedEncodingException if no UTF-8, for ease of use.
    `static int` | `hashCode(byte[] b)` Calculate the hashcode of the byte array, using 0 for null
    `static int` | `hashCode(Collection<?> col)` Calculate the hashcode of the collection, using 0 for null
    `static int` | `hashCode(Date obj)` Calculate the hashcode of the date, using 0 for null
    `static int` | `hashCode(Object obj)` Calculate the hashcode of the object, using 0 for null
    `static void` | `loadProps(Properties props, File file)` A more efficient Properties.load Some of the other differences: - UTF-8 encoding, not ISO-8859-1 - No escaping! This does not process or drop backslashes - '#' or ';' starts a comment line, but '!' does not - Leading whitespace is not trimmed - '=' is the only key-termination character (not ':' or whitespace) As of 0.9.10, an empty value is allowed.
    `static void` | `loadProps(Properties props, File file, boolean forceLowerCase)`
    `static void` | `loadProps(Properties props, InputStream inStr)`
    `static void` | `loadProps(Properties props, InputStream inStr, boolean forceLowerCase)`
    `static int` | `read(InputStream in, byte[] target)` This is different than InputStream.read(target), in that it does repeated reads until the full data is received.
    `static int` | `read(InputStream in, byte[] target, int offset, int length)` WARNING - This is different than InputStream.read(target, offset, length) for a nonzero offset, in that it returns the new offset (== old offset + length).
    `static Date` | `readDate(InputStream in)` Read in a date from the stream as specified by the I2P data structure spec.
    `static String` | `readLine(InputStream in)` Read a newline delimited line from the stream, returning the line (without the newline), or null if EOF reached on an empty line Warning - strips \n but not \r Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded Warning - not UTF-8
    `static String` | `readLine(InputStream in, MessageDigest hash)` update the hash along the way Warning - strips \n but not \r Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded Warning - not UTF-8
    `static boolean` | `readLine(InputStream in, StringBuilder buf)` Read in a line, placing it into the buffer (excluding the newline).
    `static boolean` | `readLine(InputStream in, StringBuilder buf, MessageDigest hash)` update the hash along the way Warning - strips \n but not \r Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded Warning - not UTF-8
    `static long` | `readLong(InputStream rawStream, int numBytes)` Read the stream for an integer as defined by the I2P data structure specification.
    `static Properties` | `readProperties(InputStream rawStream)` Read a mapping from the stream, as defined by the I2P data structure spec, and store it into a Properties object.
    `static Properties` | `readProperties(InputStream rawStream, Properties props)` Ditto, load into an existing properties As of 0.9.18, throws DataFormatException on duplicate key Does NOT enforce key ordering.
    `static Properties` | `readProperties(InputStream rawStream, Properties props, boolean enforceOrder)` Ditto, load into an existing properties As of 0.9.18, throws DataFormatException on duplicate key
    `static String` | `readString(InputStream in)` Read in a string from the stream as specified by the I2P data structure spec.
    `static void` | `replace(StringBuilder buf, String from, String to)` Replace all instances of "from" with "to" in the StringBuilder buf.
    `static void` | `skip(InputStream in, long n)` This is different than InputStream.skip(), in that it does repeated reads until the full amount is skipped.
    `static <T> void` | `sort(List<T> list, Comparator<? super T> c)` Same as Collections.sort(), but guaranteed not to throw an IllegalArgumentException if the sort is unstable.
    `static <T> void` | `sort(T[] a, Comparator<? super T> c)` Same as Arrays.sort(), but guaranteed not to throw an IllegalArgumentException if the sort is unstable.
    `static String[]` | `split(String s, String regex)` Same as s.split(regex) but caches the compiled pattern for speed.
    `static String[]` | `split(String s, String regex, int limit)` Same as s.split(regex, limit) but caches the compiled pattern for speed.
    `static void` | `storeProps(Properties props, File file)` Writes the props to the file, unsorted (unless props is an OrderedProperties) Note that this does not escape the \r or \n that are unescaped in loadProps() above.
    `static String` | `stripHTML(String orig)` Strip out any HTML (simply removing any less than / greater than symbols)
    `static void` | `toDate(byte[] target, int offset, long when)`
    `static String` | `toHexString(byte[] data)` Lower-case hex without leading zeros.
    `static void` | `toLong(byte[] target, int offset, int numBytes, long value)` Big endian.
    `static byte[]` | `toLong(int numBytes, long value)` Big endian.
    `static void` | `toLong8(byte[] target, int offset, long value)` Big endian.
    `static void` | `toLongLE(byte[] target, int offset, int numBytes, long value)` Little endian, i.e.
    `static int` | `toProperties(byte[] target, int offset, Properties props)`
    `static byte[]` | `toProperties(Properties opts)` Writes the props to returned byte array, not sorted (unless the opts param is an OrderedProperties) Strings will be UTF-8 encoded in the byte array.
    `static String` | `toString(byte[] buf)` Lower-case hex with leading zeros.
    `static String` | `toString(byte[] buf, int len)` Lower-case hex with leading zeros.
    `static String` | `toString(Collection<?> col)` Pretty print the collection
    `static String` | `toString(Map<?,?> options)` Pretty print the mapping, unsorted (unless the options param is an OrderedProperties)
    `static String` | `toString(Properties options)` Pretty print the mapping, unsorted (unless the options param is an OrderedProperties)
    `static void` | `write(OutputStream out, byte[] data, MessageDigest hash)` update the hash along the way
    `static void` | `writeDate(OutputStream out, Date date)` Write out a date to the stream as specified by the I2P data structure spec.
    `static void` | `writeLong(OutputStream rawStream, int numBytes, long value)` Write an integer as defined by the I2P data structure specification to the stream.
    `static void` | `writeProperties(OutputStream rawStream, Properties props)` Write a mapping to the stream, as defined by the I2P data structure spec, and store it into a Properties object.
    `static void` | `writeProperties(OutputStream rawStream, Properties props, boolean utf8)` Writes the props to the stream, sorted by property name.
    `static void` | `writeProperties(OutputStream rawStream, Properties props, boolean utf8, boolean sort)` Writes the props to the stream, sorted by property name if sort == true or if props is an OrderedProperties.
    `static void` | `writeString(OutputStream out, String string)` Write out a string to the stream as specified by the I2P data structure spec.
    `static void` | `writeStringUTF8(OutputStream out, String string)` Write out a string to the stream as specified by the I2P data structure spec.
    `static byte[]` | `xor(byte[] lhs, byte[] rhs)`
    `static void` | `xor(byte[] lhs, int startLeft, byte[] rhs, int startRight, byte[] out, int startOut, int len)` xor the lhs with the rhs, storing the result in out.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### DATE_LENGTH

          public static final int DATE_LENGTH

      See Also:
        Constant Field Values

    - #### HIGH_COMPRESSION

          public static final int HIGH_COMPRESSION

      Appx. 15% slower, 1.5% smaller than MEDIUM_COMPRESSION
      See Also:
        Constant Field Values

    - #### MAX_COMPRESSION

          public static final int MAX_COMPRESSION

      Appx. 30% slower, 2.5% smaller than MEDIUM_COMPRESSION
      See Also:
        Constant Field Values

    - #### MAX_UNCOMPRESSED

          public static final int MAX_UNCOMPRESSED

      Maximum uncompressed size.
      See Also:
        Constant Field Values

    - #### MEDIUM_COMPRESSION

          public static final int MEDIUM_COMPRESSION

      New default as of 0.9.47
      See Also:
        Constant Field Values

    - #### NO_COMPRESSION

          public static final int NO_COMPRESSION

      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### DataHelper

          public DataHelper()

  - ### Method Detail

    - #### compareTo

          public static final int compareTo(byte[] lhs,
                                            byte[] rhs)

      Big endian compare, treats bytes as unsigned. Shorter arg is lesser. Args may be null, null is less than non-null. Variable time.

    - #### compress

          public static byte[] compress(byte[] orig)

      Compress the data and return a new GZIP compressed byte array. The compressed data conforms to RFC 1952, with a 10-byte gzip header and a 8-byte gzip checksum footer. Prior to 0.9.29, this would return a zero-length output for a zero-length input. As of 0.9.29, output is valid for a zero-length input also. As of 0.9.47, this uses a level of MEDIUM_COMPRESSION, which is a good space/speed tradeoff. Prior to that, it used MAX_COMPRESSION.
      Returns:
        null if orig is null
      Throws:
        `IllegalArgumentException` - if input size is over 40KB
        `IllegalStateException` - on compression failure, as of 0.9.29

    - #### compress

          public static byte[] compress(byte[] orig,
                                        int offset,
                                        int size)

      Compress the data and return a new GZIP compressed byte array. The compressed data conforms to RFC 1952, with a 10-byte gzip header and a 8-byte gzip checksum footer. Prior to 0.9.29, this would return a zero-length output for a zero-length input. As of 0.9.29, output is valid for a zero-length input also. As of 0.9.47, this uses a level of MEDIUM_COMPRESSION, which is a good space/speed tradeoff. Prior to that, it used MAX_COMPRESSION.
      Returns:
        null if orig is null
      Throws:
        `IllegalArgumentException` - if size is over 40KB
        `IllegalStateException` - on compression failure, as of 0.9.29

    - #### compress

          public static byte[] compress(byte[] orig,
                                        int offset,
                                        int size,
                                        int level)

      Compress the data and return a new GZIP compressed byte array. The compressed data conforms to RFC 1952, with a 10-byte gzip header and a 8-byte gzip checksum footer. Prior to 0.9.29, this would return a zero-length output for a zero-length input. As of 0.9.29, output is valid for a zero-length input also.
      Parameters:
        `level` - the compression level, 0 to 9
      Returns:
        null if orig is null
      Throws:
        `IllegalArgumentException` - if size is over 40KB
        `IllegalStateException` - on compression failure, as of 0.9.29

    - #### copy

          public static void copy(InputStream in,
                                  OutputStream out)
                           throws IOException

      Copy in to out. Caller MUST close the streams.
      Parameters:
        `in` - non-null
        `out` - non-null
      Throws:
        `IOException`

    - #### decompress

          public static byte[] decompress(byte[] orig)
                                   throws IOException

      Decompress the GZIP compressed data (returning null on error).
      Returns:
        null if orig is null
      Throws:
        `IOException` - if uncompressed is over 40 KB, or on a decompression error

    - #### decompress

          public static byte[] decompress(byte[] orig,
                                          int offset,
                                          int length)
                                   throws IOException

      Decompress the GZIP compressed data (returning null on error).
      Returns:
        null if orig is null
      Throws:
        `IOException` - if uncompressed is over 40 KB, or on a decompression error

    - #### eq

          public static final boolean eq(byte[] lhs,
                                         byte[] rhs)

      Run a comparison on the byte arrays, byte by byte.

      This treats (null == null) as true, (null == (!null)) as false, and unequal length arrays as false. Variable time.

      Returns:
        Arrays.equals(lhs, rhs)

    - #### eq

          public static final boolean eq(byte[] lhs,
                                         int offsetLeft,
                                         byte[] rhs,
                                         int offsetRight,
                                         int length)

      Unlike eq(byte[], byte[]), this returns false if either lhs or rhs is null. Variable time.
      Throws:
        `ArrayIndexOutOfBoundsException` - if either array isn't long enough

    - #### eq

          public static final boolean eq(Collection<?> lhs,
                                         Collection<?> rhs)

      Run a deep comparison across the two collections.

      This treats (null == null) as true, (null == (!null)) as false, and then comparing each element via eq(object, object).

      If the size of the collections are not equal, the comparison returns false. The collection order should be consistent, as this simply iterates across both and compares based on the value of each at each step along the way.

    - #### eq

          public static final boolean eq(Object lhs,
                                         Object rhs)

      Helper util to compare two objects, including null handling.

      This treats (null == null) as true, and (null == (!null)) as false.

    - #### eqCT

          public static final boolean eqCT(byte[] lhs,
                                           int offsetLeft,
                                           byte[] rhs,
                                           int offsetRight,
                                           int length)

      Unlike eq(), this throws NPE if either lhs or rhs is null. Constant time.
      Throws:
        `NullPointerException` - if lhs or rhs is null
        `ArrayIndexOutOfBoundsException` - if either array isn't long enough

    - #### escapeHTML

          public static String escapeHTML(String unescaped)

      Escape a string for inclusion in HTML
      Parameters:
        `unescaped` - the unescaped string, may be null
      Returns:
        the escaped string, or null if null is passed in

    - #### formatDate

          public static String formatDate(long now)

      The default formatting for date, current locale, local time zone. Warning - NOT UTC! Examples: en: Aug 30, 2019 de: 30.08.2019

    - #### formatDuration

          public static String formatDuration(long ms)

      NOTE: formatDuration2() recommended in most cases for readability

    - #### formatDuration2

          public static String formatDuration2(double ms)

      Like formatDuration2(long) but with microsec and nanosec also.

    - #### formatDuration2

          public static String formatDuration2(long ms)

      Like formatDuration but with a non-breaking space after the number, 0 is unitless, and the unit is translated. This seems consistent with most style guides out there. Use only in HTML. Thresholds are a little lower than in formatDuration() also, as precision is less important in the GUI than in logging. Negative numbers handled correctly.

    - #### formatSize

          public static String formatSize(long bytes)

      This is binary, i.e. multiples of 1024. For decimal, see formatSize2Decimal(). Caller should append 'B' or 'b' as appropriate. No space between the number and the letter. NOTE: formatSize2() recommended in most cases for readability
      Returns:
        e.g. "123.05Ki"

    - #### formatSize2

          public static String formatSize2(long bytes)

      This is binary, i.e. multiples of 1024. For decimal, see formatSize2Decimal(). Caller should append 'B' or 'b' as appropriate. Like formatSize but with a non-breaking space after the number This seems consistent with most style guides out there. Use only in HTML, and not inside form values (use formatSize2(bytes, false) there instead).
      Returns:
        e.g. "123.05&#8239;Ki"

    - #### formatSize2

          public static String formatSize2(long bytes,
                                           boolean nonBreaking)

      This is binary, i.e. multiples of 1024. For decimal, see formatSize2Decimal(). Caller should append 'B' or 'b' as appropriate, Like formatSize but with a space after the number This seems consistent with most style guides out there.
      Parameters:
        `nonBreaking` - use an HTML thin non-breaking space (&#8239;)
      Returns:
        e.g. "123.05&#8239;Ki" or "123.05 Ki"

    - #### formatSize2Decimal

          public static String formatSize2Decimal(long bytes)

      This is decimal, i.e. multiples of 1000. For binary, see formatSize2(). Caller should append 'B' or 'b' as appropriate. Like formatSize but with a space after the number This seems consistent with most style guides out there.
      Returns:
        e.g. "123.05&#8239;K"

    - #### formatSize2Decimal

          public static String formatSize2Decimal(long bytes,
                                                  boolean nonBreaking)

      This is decimal, i.e. multiples of 1000. For binary, see formatSize2(). Caller should append 'B' or 'b' as appropriate. Like formatSize but with a space after the number This seems consistent with most style guides out there.
      Parameters:
        `nonBreaking` - use an HTML thin non-breaking space (&#8239;)
      Returns:
        e.g. "123.05&#8239;K" or "123.05 K"

    - #### formatTime

          public static String formatTime(long now)

      The default formatting for date/time, current locale, local time zone. Warning - NOT UTC! Examples: en: Aug 30, 2019 12:38 PM de: 30.08.2019 12:38

    - #### fromDate

          public static Date fromDate(byte[] src,
                                      int offset)
                               throws DataFormatException

      Parameters:
        `src` - the source byte array
        `offset` - the starting offset
      Returns:
        the date, or null if the time is zero or negative
      Throws:
        `DataFormatException` - if there is not enough data

    - #### fromLong

          public static long fromLong(byte[] src,
                                      int offset,
                                      int numBytes)

      Big endian.
      Parameters:
        `src` - if null returns 0
        `numBytes` - 1-8
      Returns:
        non-negative
      Throws:
        `ArrayIndexOutOfBoundsException`
        `IllegalArgumentException` - if negative (only possible if numBytes = 8)

    - #### fromLong8

          public static long fromLong8(byte[] src,
                                       int offset)

      Big endian. Same as fromLong(src, offset, 8) but allows negative result
      Throws:
        `ArrayIndexOutOfBoundsException`

    - #### fromLongLE

          public static long fromLongLE(byte[] src,
                                        int offset,
                                        int numBytes)

      Little endian, i.e. backwards. Not for use in I2P protocols.
      Parameters:
        `numBytes` - 1-8
      Returns:
        non-negative
      Throws:
        `ArrayIndexOutOfBoundsException`
        `IllegalArgumentException` - if negative (only possible if numBytes = 8)

    - #### fromProperties

          public static int fromProperties(byte[] source,
                                           int offset,
                                           Properties target)
                                    throws DataFormatException

      Reads the props from the byte array and puts them in the Properties target See readProperties() for the format. Warning - confusing method name, Properties is the target. Strings must be UTF-8 encoded in the byte array. As of 0.9.18, throws DataFormatException on duplicate key
      Parameters:
        `source` - source
        `target` - returned Properties
      Returns:
        new offset
      Throws:
        `DataFormatException` - if the data is malformed

    - #### getASCII

          public static byte[] getASCII(String orig)

      Roughly the same as orig.getBytes("ISO-8859-1") but much faster and will not throw an exception. Warning - misnamed, converts to ISO-8859-1.
      Parameters:
        `orig` - non-null, truncates to 8-bit chars

    - #### getUTF8

          public static String getUTF8(byte[] orig)

      Same as new String(orig, "UTF-8") but throws an unchecked RuntimeException instead of an UnsupportedEncodingException if no UTF-8, for ease of use. Used by Syndie.
      Returns:
        null if orig is null
      Throws:
        `RuntimeException`

    - #### getUTF8

          public static String getUTF8(byte[] orig,
                                       int offset,
                                       int len)

      Same as new String(orig, "UTF-8") but throws an unchecked RuntimeException instead of an UnsupportedEncodingException if no UTF-8, for ease of use.
      Returns:
        null if orig is null
      Throws:
        `RuntimeException`

    - #### getUTF8

          public static byte[] getUTF8(String orig)

      Same as orig.getBytes("UTF-8") but throws an unchecked RuntimeException instead of an UnsupportedEncodingException if no UTF-8, for ease of use.
      Returns:
        null if orig is null
      Throws:
        `RuntimeException`

    - #### hashCode

          public static int hashCode(byte[] b)

      Calculate the hashcode of the byte array, using 0 for null

    - #### hashCode

          public static int hashCode(Collection<?> col)

      Calculate the hashcode of the collection, using 0 for null

    - #### hashCode

          public static int hashCode(Date obj)

      Calculate the hashcode of the date, using 0 for null

    - #### hashCode

          public static int hashCode(Object obj)

      Calculate the hashcode of the object, using 0 for null

    - #### loadProps

          public static void loadProps(Properties props,
                                       File file)
                                throws IOException

      A more efficient Properties.load Some of the other differences: - UTF-8 encoding, not ISO-8859-1 - No escaping! This does not process or drop backslashes - '#' or ';' starts a comment line, but '!' does not - Leading whitespace is not trimmed - '=' is the only key-termination character (not ':' or whitespace) As of 0.9.10, an empty value is allowed. As in Java Properties, duplicate keys are allowed, last one wins.
      Throws:
        `IOException`

    - #### loadProps

          public static void loadProps(Properties props,
                                       File file,
                                       boolean forceLowerCase)
                                throws IOException

      Parameters:
        `forceLowerCase` - if true forces the keys to lower case (not the values)
      Throws:
        `IOException`

    - #### loadProps

          public static void loadProps(Properties props,
                                       InputStream inStr)
                                throws IOException

      Throws:
        `IOException`

    - #### loadProps

          public static void loadProps(Properties props,
                                       InputStream inStr,
                                       boolean forceLowerCase)
                                throws IOException

      Parameters:
        `forceLowerCase` - if true forces the keys to lower case (not the values)
      Throws:
        `IOException`

    - #### read

          public static int read(InputStream in,
                                 byte[] target)
                          throws IOException

      This is different than InputStream.read(target), in that it does repeated reads until the full data is received. As of 0.9.27, throws EOFException if the full length is not read.
      Returns:
        target.length
      Throws:
        `EOFException` - if the full length is not read (since 0.9.27)
        `IOException`

    - #### read

          public static int read(InputStream in,
                                 byte[] target,
                                 int offset,
                                 int length)
                          throws IOException

      WARNING - This is different than InputStream.read(target, offset, length) for a nonzero offset, in that it returns the new offset (== old offset + length). It also does repeated reads until the full data is received. WARNING - Broken for nonzero offset before 0.9.27. As of 0.9.27, throws EOFException if the full length is not read.
      Returns:
        the new offset (== old offset + length)
      Throws:
        `EOFException` - if the full length is not read (since 0.9.27)
        `IOException`

    - #### readDate

          public static Date readDate(InputStream in)
                               throws DataFormatException,
                                      IOException

      Read in a date from the stream as specified by the I2P data structure spec. A date is an 8 byte unsigned integer in network byte order specifying the number of milliseconds since midnight on January 1, 1970 in the GMT timezone. If the number is 0, the date is undefined or null. (yes, this means you can't represent midnight on 1/1/1970)
      Parameters:
        `in` - stream to read from
      Returns:
        date read, or null
      Throws:
        `DataFormatException` - if the stream doesn't contain a validly formatted date
        `IOException` - if there is an IO error reading the date

    - #### readLine

          public static String readLine(InputStream in)
                                 throws IOException

      Read a newline delimited line from the stream, returning the line (without the newline), or null if EOF reached on an empty line Warning - strips \n but not \r Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded Warning - not UTF-8
      Returns:
        null on EOF
      Throws:
        `IOException`

    - #### readLine

          public static String readLine(InputStream in,
                                        MessageDigest hash)
                                 throws IOException

      update the hash along the way Warning - strips \n but not \r Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded Warning - not UTF-8
      Parameters:
        `hash` - null OK
      Returns:
        null on EOF
      Throws:
        `IOException`

    - #### readLine

          public static boolean readLine(InputStream in,
                                         StringBuilder buf)
                                  throws IOException

      Read in a line, placing it into the buffer (excluding the newline). Warning - strips \n but not \r Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded Warning - not UTF-8
      Returns:
        true if the line was read, false if eof was reached on an empty line (returns true for non-empty last line without a newline)
      Throws:
        `IOException`

    - #### readLine

          public static boolean readLine(InputStream in,
                                         StringBuilder buf,
                                         MessageDigest hash)
                                  throws IOException

      update the hash along the way Warning - strips \n but not \r Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded Warning - not UTF-8
      Parameters:
        `hash` - null OK
      Returns:
        true if the line was read, false if eof was reached on an empty line (returns true for non-empty last line without a newline)
      Throws:
        `IOException`

    - #### readLong

          public static long readLong(InputStream rawStream,
                                      int numBytes)
                               throws DataFormatException,
                                      IOException

      Read the stream for an integer as defined by the I2P data structure specification. Integers are a fixed number of bytes (numBytes), stored as unsigned integers in network byte order.
      Parameters:
        `rawStream` - stream to read from
        `numBytes` - number of bytes to read and format into a number, 1 to 8
      Returns:
        number
      Throws:
        `DataFormatException` - if negative (only possible if numBytes = 8) (since 0.8.12)
        `EOFException` - since 0.8.2, if there aren't enough bytes to read the number
        `IOException` - if there is an IO error reading the number

    - #### readProperties

          public static Properties readProperties(InputStream rawStream)
                                           throws DataFormatException,
                                                  IOException

      Read a mapping from the stream, as defined by the I2P data structure spec, and store it into a Properties object. A mapping is a set of key / value pairs. It starts with a 2 byte Integer (ala readLong(rawStream, 2)) defining how many bytes make up the mapping. After that comes that many bytes making up a set of UTF-8 encoded characters. The characters are organized as key=value;. The key is a String (ala readString(rawStream)) unique as a key within the current mapping that does not include the UTF-8 characters '=' or ';'. After the key comes the literal UTF-8 character '='. After that comes a String (ala readString(rawStream)) for the value. Finally after that comes the literal UTF-8 character ';'. This key=value; is repeated until there are no more bytes (not characters!) left as defined by the first two byte integer. As of 0.9.18, throws DataFormatException on duplicate key
      Parameters:
        `rawStream` - stream to read the mapping from
      Returns:
        an OrderedProperties
      Throws:
        `DataFormatException` - if the format is invalid
        `IOException` - if there is a problem reading the data

    - #### readProperties

          public static Properties readProperties(InputStream rawStream,
                                                  Properties props)
                                           throws DataFormatException,
                                                  IOException

      Ditto, load into an existing properties As of 0.9.18, throws DataFormatException on duplicate key Does NOT enforce key ordering.
      Parameters:
        `props` - The Properties to load into. As of 0.9.38, if null, a new OrderedProperties will be created.
        `rawStream` - stream to read the mapping from
      Returns:
        the parameter props, or (as of 0.9.38) a new OrderedProperties if props is null, and an immutable EmptyProperties if empty.
      Throws:
        `DataFormatException` - if the format is invalid
        `IOException` - if there is a problem reading the data

    - #### readProperties

          public static Properties readProperties(InputStream rawStream,
                                                  Properties props,
                                                  boolean enforceOrder)
                                           throws DataFormatException,
                                                  IOException

      Ditto, load into an existing properties As of 0.9.18, throws DataFormatException on duplicate key
      Parameters:
        `props` - The Properties to load into. As of 0.9.38, if null, a new OrderedProperties will be created.
        `rawStream` - stream to read the mapping from
        `enforceOrder` - if true, throw DataFormatException if keys are not ordered
      Returns:
        the parameter props, or (as of 0.9.38) a new OrderedProperties if props is null, and an immutable EmptyProperties if empty.
      Throws:
        `DataFormatException` - if the format is invalid
        `IOException` - if there is a problem reading the data

    - #### readString

          public static String readString(InputStream in)
                                   throws DataFormatException,
                                          IOException

      Read in a string from the stream as specified by the I2P data structure spec. A string is 1 or more bytes where the first byte is the number of bytes (not characters!) in the string and the remaining 0-255 bytes are the non-null terminated UTF-8 encoded character array.
      Parameters:
        `in` - stream to read from
      Returns:
        UTF-8 string
      Throws:
        `DataFormatException` - if the stream doesn't contain a validly formatted string
        `EOFException` - since 0.8.2, if there aren't enough bytes to read the string
        `IOException` - if there is an IO error reading the string

    - #### replace

          public static void replace(StringBuilder buf,
                                     String from,
                                     String to)

      Replace all instances of "from" with "to" in the StringBuilder buf. Same as String.replace(), but in-memory with no object churn, as long as "to" is equal size or smaller than "from", or buf has capacity. Use for large Strings or for multiple replacements in a row.
      Parameters:
        `buf` - contains the string to be searched
        `from` - the string to be replaced
        `to` - the replacement string

    - #### skip

          public static void skip(InputStream in,
                                  long n)
                           throws IOException

      This is different than InputStream.skip(), in that it does repeated reads until the full amount is skipped. To fix findbugs issues with skip(). Guaranteed to skip exactly n bytes or throw an IOE. http://stackoverflow.com/questions/14057720/robust-skipping-of-data-in-a-java-io-inputstream-and-its-subtypes http://stackoverflow.com/questions/11511093/java-inputstream-skip-return-value-near-end-of-file
      Parameters:
        `in` - the input stream
        `n` - the number of bytes to skip
      Throws:
        `IOException` - if an I/O error occurs or EOF is reached before all bytes are skipped
        `IllegalArgumentException` - if n is negative

    - #### sort

          public static <T> void sort(List<T> list,
                                      Comparator<? super T> c)

      Same as Collections.sort(), but guaranteed not to throw an IllegalArgumentException if the sort is unstable. As of Java 7, TimSort will throw an IAE if the underlying sort order changes during the sort. This catches the IAE, retries once, and then returns. If an IAE is thrown twice, this method will return, with the list possibly unsorted.
      Parameters:
        `list` - the list to be sorted.
        `c` - the comparator to determine the order of the list. A null value indicates that the elements' natural ordering should be used.

    - #### sort

          public static <T> void sort(T[] a,
                                      Comparator<? super T> c)

      Same as Arrays.sort(), but guaranteed not to throw an IllegalArgumentException if the sort is unstable. As of Java 7, TimSort will throw an IAE if the underlying sort order changes during the sort. This catches the IAE, retries once, and then returns. If an IAE is thrown twice, this method will return, with the array possibly unsorted.
      Parameters:
        `a` - the array to be sorted.
        `c` - the comparator to determine the order of the array. A null value indicates that the elements' natural ordering should be used.

    - #### split

          public static String[] split(String s,
                                       String regex)

      Same as s.split(regex) but caches the compiled pattern for speed. This saves about 10 microseconds (Bulldozer) on subsequent invocations. Note: For an input "" this returns [""], not a zero-length array. This is the same behavior as String.split().
      Parameters:
        `s` - non-null
        `regex` - non-null, don't forget to enclose multiple choices with []
      Throws:
        `PatternSyntaxException` - unchecked

    - #### split

          public static String[] split(String s,
                                       String regex,
                                       int limit)

      Same as s.split(regex, limit) but caches the compiled pattern for speed. This saves about 10 microseconds (Bulldozer) on subsequent invocations. Note: For an input "" this returns [""], not a zero-length array. This is the same behavior as String.split().
      Parameters:
        `s` - non-null
        `regex` - non-null, don't forget to enclose multiple choices with []
        `limit` - result threshold
      Throws:
        `PatternSyntaxException` - unchecked

    - #### storeProps

          public static void storeProps(Properties props,
                                        File file)
                                 throws IOException

      Writes the props to the file, unsorted (unless props is an OrderedProperties) Note that this does not escape the \r or \n that are unescaped in loadProps() above. As of 0.8.1, file will be mode 600. Properties from the defaults table of props (if any) are not written out by this method. Leading or trailing whitespace in values is not checked but will be trimmed by loadProps()
      Throws:
        `IllegalArgumentException` - if a key contains any of "#=\n" or starts with ';', or a value contains '#' or '\n'
        `IOException`

    - #### stripHTML

          public static String stripHTML(String orig)

      Strip out any HTML (simply removing any less than / greater than symbols)
      Parameters:
        `orig` - may be null, returns empty string if null

    - #### toDate

          public static void toDate(byte[] target,
                                    int offset,
                                    long when)
                             throws IllegalArgumentException

      Parameters:
        `target` - the target byte array
        `offset` - the starting offset
        `when` - the time in milliseconds since epoch
      Throws:
        `IllegalArgumentException` - if the offset is invalid

    - #### toHexString

          public static final String toHexString(byte[] data)

      Lower-case hex without leading zeros. Use toString(byte[]) to get leading zeros
      Parameters:
        `data` - may be null (returns "00")

    - #### toLong

          public static void toLong(byte[] target,
                                    int offset,
                                    int numBytes,
                                    long value)
                             throws IllegalArgumentException

      Big endian.
      Parameters:
        `numBytes` - 1-8
        `value` - non-negative
      Throws:
        `IllegalArgumentException` - if numBytes is out of range or value is negative

    - #### toLong

          public static byte[] toLong(int numBytes,
                                      long value)
                               throws IllegalArgumentException

      Big endian.
      Parameters:
        `numBytes` - 1-8
        `value` - non-negative
      Returns:
        an array of length numBytes
      Throws:
        `IllegalArgumentException` - if numBytes is out of range or value is negative

    - #### toLong8

          public static void toLong8(byte[] target,
                                     int offset,
                                     long value)

      Big endian. Same as toLong(target, offset, 8, value) but allows negative value
      Throws:
        `ArrayIndexOutOfBoundsException`

    - #### toLongLE

          public static void toLongLE(byte[] target,
                                      int offset,
                                      int numBytes,
                                      long value)

      Little endian, i.e. backwards. Not for use in I2P protocols.
      Parameters:
        `numBytes` - 1-8
        `value` - non-negative

    - #### toProperties

          public static int toProperties(byte[] target,
                                         int offset,
                                         Properties props)
                                  throws DataFormatException,
                                         IOException

      Throws:
        `DataFormatException`
        `IOException`

    - #### toProperties

          public static byte[] toProperties(Properties opts)
                                     throws DataFormatException

      Writes the props to returned byte array, not sorted (unless the opts param is an OrderedProperties) Strings will be UTF-8 encoded in the byte array. See readProperties() for the format. Property keys and values must not contain '=' or ';', this is not checked and they are not escaped Keys and values must be 255 bytes or less, Formatted length must not exceed 65535 bytes Warning - confusing method name, Properties is the source. Properties from the defaults table of props (if any) are not written out by this method.
      Throws:
        `DataFormatException` - if key, value, or total is too long

    - #### toString

          public static String toString(byte[] buf)

      Lower-case hex with leading zeros. Use toHexString(byte[]) to not get leading zeros
      Parameters:
        `buf` - may be null (returns "")
      Returns:
        String of length 2*buf.length

    - #### toString

          public static String toString(byte[] buf,
                                        int len)

      Lower-case hex with leading zeros. Use toHexString(byte[]) to not get leading zeros
      Parameters:
        `buf` - may be null
        `len` - number of bytes. If greater than buf.length, additional zeros will be prepended
      Returns:
        String of length 2*len

    - #### toString

          public static String toString(Collection<?> col)

      Pretty print the collection

    - #### toString

          public static String toString(Map<?,?> options)

      Pretty print the mapping, unsorted (unless the options param is an OrderedProperties)

    - #### toString

          public static String toString(Properties options)

      Pretty print the mapping, unsorted (unless the options param is an OrderedProperties)

    - #### write

          public static void write(OutputStream out,
                                   byte[] data,
                                   MessageDigest hash)
                            throws IOException

      update the hash along the way
      Throws:
        `IOException`

    - #### writeDate

          public static void writeDate(OutputStream out,
                                       Date date)
                                throws DataFormatException,
                                       IOException

      Write out a date to the stream as specified by the I2P data structure spec.
      Parameters:
        `out` - stream to write to
        `date` - date to write (can be null)
      Throws:
        `DataFormatException` - if the date is not valid
        `IOException` - if there is an IO error writing the date

    - #### writeLong

          public static void writeLong(OutputStream rawStream,
                                       int numBytes,
                                       long value)
                                throws DataFormatException,
                                       IOException

      Write an integer as defined by the I2P data structure specification to the stream. Integers are a fixed number of bytes (numBytes), stored as unsigned integers in network byte order.
      Parameters:
        `value` - value to write out, non-negative
        `rawStream` - stream to write to
        `numBytes` - number of bytes to write the number into, 1-8 (padding as necessary)
      Throws:
        `DataFormatException` - if value is negative or if numBytes not 1-8
        `IOException` - if there is an IO error writing to the stream

    - #### writeProperties

          public static void writeProperties(OutputStream rawStream,
                                             Properties props)
                                      throws DataFormatException,
                                             IOException

      Write a mapping to the stream, as defined by the I2P data structure spec, and store it into a Properties object. See readProperties for the format. Output is sorted by property name. Property keys and values must not contain '=' or ';', this is not checked and they are not escaped Keys and values must be 255 bytes or less, Formatted length must not exceed 65535 bytes Properties from the defaults table of props (if any) are not written out by this method.
      Parameters:
        `rawStream` - stream to write to
        `props` - properties to write out, may be null
      Throws:
        `DataFormatException` - if there is not enough valid data to write out, or a length limit is exceeded
        `IOException` - if there is an IO error writing out the data

    - #### writeProperties

          public static void writeProperties(OutputStream rawStream,
                                             Properties props,
                                             boolean utf8)
                                      throws DataFormatException,
                                             IOException

      Writes the props to the stream, sorted by property name. See readProperties() for the format. Property keys and values must not contain '=' or ';', this is not checked and they are not escaped Keys and values must be 255 bytes or less, Formatted length must not exceed 65535 bytes Properties from the defaults table of props (if any) are not written out by this method. jrandom disabled UTF-8 in mid-2004, for performance reasons, i.e. slow foo.getBytes("UTF-8") Re-enable it so we can pass UTF-8 tunnel names through the I2CP SessionConfig. Use utf8 = false for RouterAddress (fast, non UTF-8) Use utf8 = true for SessionConfig (slow, UTF-8)
      Parameters:
        `props` - source may be null
      Throws:
        `DataFormatException` - if a length limit is exceeded
        `IOException`

    - #### writeProperties

          public static void writeProperties(OutputStream rawStream,
                                             Properties props,
                                             boolean utf8,
                                             boolean sort)
                                      throws DataFormatException,
                                             IOException

      Writes the props to the stream, sorted by property name if sort == true or if props is an OrderedProperties. See readProperties() for the format. Property keys and values must not contain '=' or ';', this is not checked and they are not escaped Keys and values must be 255 bytes or less, Formatted length must not exceed 65535 bytes Properties from the defaults table of props (if any) are not written out by this method. jrandom disabled UTF-8 in mid-2004, for performance reasons, i.e. slow foo.getBytes("UTF-8") Re-enable it so we can pass UTF-8 tunnel names through the I2CP SessionConfig. Use utf8 = false for RouterAddress (fast, non UTF-8) Use utf8 = true for SessionConfig (slow, UTF-8)
      Parameters:
        `props` - source may be null
        `sort` - should we sort the properties? (set to false if already sorted, e.g. OrderedProperties)
      Throws:
        `DataFormatException` - if any string is over 255 bytes long, or if the total length (not including the two length bytes) is greater than 65535 bytes.
        `IOException`

    - #### writeString

          public static void writeString(OutputStream out,
                                         String string)
                                  throws DataFormatException,
                                         IOException

      Write out a string to the stream as specified by the I2P data structure spec. Note that the max size for a string allowed by the spec is 255 bytes. WARNING - this method destroys the encoding, and therefore violates the data structure spec.
      Parameters:
        `out` - stream to write string
        `string` - string to write out: null strings are perfectly valid, but strings of excess length will cause a DataFormatException to be thrown
      Throws:
        `DataFormatException` - if the string is not valid
        `IOException` - if there is an IO error writing the string

    - #### writeStringUTF8

          public static void writeStringUTF8(OutputStream out,
                                             String string)
                                      throws DataFormatException,
                                             IOException

      Write out a string to the stream as specified by the I2P data structure spec. Note that the max size for a string allowed by the spec is 255 bytes. This method correctly uses UTF-8
      Parameters:
        `out` - stream to write string
        `string` - UTF-8 string to write out: null strings are perfectly valid, but strings of excess length will cause a DataFormatException to be thrown
      Throws:
        `DataFormatException` - if the string is not valid
        `IOException` - if there is an IO error writing the string

    - #### xor

          public static final byte[] xor(byte[] lhs,
                                         byte[] rhs)

      Returns:
        null if either arg is null or the args are not equal length

    - #### xor

          public static final void xor(byte[] lhs,
                                       int startLeft,
                                       byte[] rhs,
                                       int startRight,
                                       byte[] out,
                                       int startOut,
                                       int len)

      xor the lhs with the rhs, storing the result in out.
      Parameters:
        `lhs` - one of the source arrays
        `startLeft` - starting index in the lhs array to begin the xor
        `rhs` - the other source array
        `startRight` - starting index in the rhs array to begin the xor
        `out` - output array
        `startOut` - starting index in the out array to store the result
        `len` - how many bytes into the various arrays to xor