/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.apache.commons.compress.utils;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

Utility methods for reading and writing bytes.
Since:1.14
/** * Utility methods for reading and writing bytes. * @since 1.14 */
public final class ByteUtils { private ByteUtils() { /* no instances */ }
Used to supply bytes.
Since:1.14
/** * Used to supply bytes. * @since 1.14 */
public interface ByteSupplier {
The contract is similar to InputStream.read(), return the byte as an unsigned int, -1 if there are no more bytes.
Throws:
Returns:the supplied byte or -1 if there are no more bytes
/** * The contract is similar to {@link InputStream#read()}, return * the byte as an unsigned int, -1 if there are no more bytes. * @return the supplied byte or -1 if there are no more bytes * @throws IOException if supplying fails */
int getAsByte() throws IOException; }
Used to consume bytes.
Since:1.14
/** * Used to consume bytes. * @since 1.14 */
public interface ByteConsumer {
The contract is similar to OutputStream.write(int), consume the lower eight bytes of the int as a byte.
Params:
  • b – the byte to consume
Throws:
/** * The contract is similar to {@link OutputStream#write(int)}, * consume the lower eight bytes of the int as a byte. * @param b the byte to consume * @throws IOException if consuming fails */
void accept(int b) throws IOException; }
Reads the given byte array as a little endian long.
Params:
  • bytes – the byte array to convert
Returns:the number read
/** * Reads the given byte array as a little endian long. * @param bytes the byte array to convert * @return the number read */
public static long fromLittleEndian(byte[] bytes) { return fromLittleEndian(bytes, 0, bytes.length); }
Reads the given byte array as a little endian long.
Params:
  • bytes – the byte array to convert
  • off – the offset into the array that starts the value
  • length – the number of bytes representing the value
Throws:
Returns:the number read
/** * Reads the given byte array as a little endian long. * @param bytes the byte array to convert * @param off the offset into the array that starts the value * @param length the number of bytes representing the value * @return the number read * @throws IllegalArgumentException if len is bigger than eight */
public static long fromLittleEndian(byte[] bytes, final int off, final int length) { checkReadLength(length); long l = 0; for (int i = 0; i < length; i++) { l |= (bytes[off + i] & 0xffL) << (8 * i); } return l; }
Reads the given number of bytes from the given stream as a little endian long.
Params:
  • in – the stream to read from
  • length – the number of bytes representing the value
Throws:
Returns:the number read
/** * Reads the given number of bytes from the given stream as a little endian long. * @param in the stream to read from * @param length the number of bytes representing the value * @return the number read * @throws IllegalArgumentException if len is bigger than eight * @throws IOException if reading fails or the stream doesn't * contain the given number of bytes anymore */
public static long fromLittleEndian(InputStream in, int length) throws IOException { // somewhat duplicates the ByteSupplier version in order to save the creation of a wrapper object checkReadLength(length); long l = 0; for (int i = 0; i < length; i++) { long b = in.read(); if (b == -1) { throw new IOException("Premature end of data"); } l |= (b << (i * 8)); } return l; }
Reads the given number of bytes from the given supplier as a little endian long.

Typically used by our InputStreams that need to count the bytes read as well.

Params:
  • supplier – the supplier for bytes
  • length – the number of bytes representing the value
Throws:
Returns:the number read
/** * Reads the given number of bytes from the given supplier as a little endian long. * * <p>Typically used by our InputStreams that need to count the * bytes read as well.</p> * * @param supplier the supplier for bytes * @param length the number of bytes representing the value * @return the number read * @throws IllegalArgumentException if len is bigger than eight * @throws IOException if the supplier fails or doesn't supply the * given number of bytes anymore */
public static long fromLittleEndian(ByteSupplier supplier, final int length) throws IOException { checkReadLength(length); long l = 0; for (int i = 0; i < length; i++) { long b = supplier.getAsByte(); if (b == -1) { throw new IOException("Premature end of data"); } l |= (b << (i * 8)); } return l; }
Reads the given number of bytes from the given input as little endian long.
Params:
  • in – the input to read from
  • length – the number of bytes representing the value
Throws:
Returns:the number read
/** * Reads the given number of bytes from the given input as little endian long. * @param in the input to read from * @param length the number of bytes representing the value * @return the number read * @throws IllegalArgumentException if len is bigger than eight * @throws IOException if reading fails or the stream doesn't * contain the given number of bytes anymore */
public static long fromLittleEndian(DataInput in, int length) throws IOException { // somewhat duplicates the ByteSupplier version in order to save the creation of a wrapper object checkReadLength(length); long l = 0; for (int i = 0; i < length; i++) { long b = in.readUnsignedByte(); l |= (b << (i * 8)); } return l; }
Inserts the given value into the array as a little endian sequence of the given length starting at the given offset.
Params:
  • b – the array to write into
  • value – the value to insert
  • off – the offset into the array that receives the first byte
  • length – the number of bytes to use to represent the value
/** * Inserts the given value into the array as a little endian * sequence of the given length starting at the given offset. * @param b the array to write into * @param value the value to insert * @param off the offset into the array that receives the first byte * @param length the number of bytes to use to represent the value */
public static void toLittleEndian(final byte[] b, final long value, final int off, final int length) { long num = value; for (int i = 0; i < length; i++) { b[off + i] = (byte) (num & 0xff); num >>= 8; } }
Writes the given value to the given stream as a little endian array of the given length.
Params:
  • out – the stream to write to
  • value – the value to write
  • length – the number of bytes to use to represent the value
Throws:
/** * Writes the given value to the given stream as a little endian * array of the given length. * @param out the stream to write to * @param value the value to write * @param length the number of bytes to use to represent the value * @throws IOException if writing fails */
public static void toLittleEndian(OutputStream out, final long value, final int length) throws IOException { // somewhat duplicates the ByteConsumer version in order to save the creation of a wrapper object long num = value; for (int i = 0; i < length; i++) { out.write((int) (num & 0xff)); num >>= 8; } }
Provides the given value to the given consumer as a little endian sequence of the given length.
Params:
  • consumer – the consumer to provide the bytes to
  • value – the value to provide
  • length – the number of bytes to use to represent the value
Throws:
/** * Provides the given value to the given consumer as a little endian * sequence of the given length. * @param consumer the consumer to provide the bytes to * @param value the value to provide * @param length the number of bytes to use to represent the value * @throws IOException if writing fails */
public static void toLittleEndian(ByteConsumer consumer, final long value, final int length) throws IOException { long num = value; for (int i = 0; i < length; i++) { consumer.accept((int) (num & 0xff)); num >>= 8; } }
Writes the given value to the given stream as a little endian array of the given length.
Params:
  • out – the output to write to
  • value – the value to write
  • length – the number of bytes to use to represent the value
Throws:
/** * Writes the given value to the given stream as a little endian * array of the given length. * @param out the output to write to * @param value the value to write * @param length the number of bytes to use to represent the value * @throws IOException if writing fails */
public static void toLittleEndian(DataOutput out, final long value, final int length) throws IOException { // somewhat duplicates the ByteConsumer version in order to save the creation of a wrapper object long num = value; for (int i = 0; i < length; i++) { out.write((int) (num & 0xff)); num >>= 8; } }
Since:1.14
/** * {@link ByteSupplier} based on {@link InputStream}. * @since 1.14 */
public static class InputStreamByteSupplier implements ByteSupplier { private final InputStream is; public InputStreamByteSupplier(InputStream is) { this.is = is; } @Override public int getAsByte() throws IOException { return is.read(); } }
Since:1.14
/** * {@link ByteConsumer} based on {@link OutputStream}. * @since 1.14 */
public static class OutputStreamByteConsumer implements ByteConsumer { private final OutputStream os; public OutputStreamByteConsumer(OutputStream os) { this.os = os; } @Override public void accept(int b) throws IOException { os.write(b); } } private static final void checkReadLength(int length) { if (length > 8) { throw new IllegalArgumentException("Can't read more than eight bytes into a long value"); } } }