com.feilong.lib.compress.utils.ByteUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of feilong Show documentation
Show all versions of feilong Show documentation
feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.
/*
* 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 com.feilong.lib.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
*/
public final class ByteUtils{
private ByteUtils(){
/* no instances */ }
/**
* Used to supply bytes.
*
* @since 1.14
*/
public interface ByteSupplier{
/**
* 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
*/
public interface ByteConsumer{
/**
* 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.
*
* @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.
*
* @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.
*
* @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.
*
*
* @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.
*
* @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.
*
* @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.
*
* @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.
*
* @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.
*
* @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;
}
}
/**
* {@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();
}
}
/**
* {@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");
}
}
}