下面是我的代码替换DataInputStream来包装一个InputStream,但是除了读取大尾数类型的普通方法之外,还提供了额外的方法来读取小端数据类型.如果你愿意,随意使用它.
我有几点保留如下.注意不改变功能的方法(读取大尾数类型的函数).没有办法我可以实现DataInputStream作为基类,并使用它的方法,如read(),readInt(),readChar()等等?
我的班级层次似乎有点奇怪.这是否合适?
像readUTF()或readLine()这样的其他类型的其他类型需要一个小的endian版本吗?还是主观具体方案?
Java如何存储布尔类型?这是否也是主观的?
感谢您的满足我的好奇心:)
import java.io.*; /** * Replacement for a DataInputStream that provides both little and big endian reading capabilities for convenience without need to implement a ByteBuffer * @author Bill (unspecified.specification@gmail.com) */ public class EndianInputStream extends InputStream implements DataInput { private DataInputStream dataInStream; private InputStream inStream; private byte byteBuffer[]; /** * Constructor to wrap InputStream for little and big endian data * @param refInStream Inputstream to wrap */ public EndianInputStream(InputStream refInStream) { inStream = refInStream; dataInStream = new DataInputStream(inStream); byteBuffer = new byte[8]; // Largest data type is 64-bits (8 bytes) } @Override public int available() throws IOException { return dataInStream.available(); } @Override public final int read(byte refBuffer[],int offset,int readLen) throws IOException { return inStream.read(refBuffer,offset,readLen); } @Override public int read() throws IOException { return inStream.read(); } @Override public final int readUnsignedByte() throws IOException { return dataInStream.readUnsignedByte(); } @Deprecated @Override public final String readLine() throws IOException { return dataInStream.readLine(); } @Override public final String readUTF() throws IOException { return dataInStream.readUTF(); } @Override public final void close() throws IOException { dataInStream.close(); } @Override public final void readFully(byte refBuffer[]) throws IOException { dataInStream.readFully(refBuffer,refBuffer.length); } @Override public final void readFully(byte refBuffer[],int readLen) throws IOException { dataInStream.readFully(refBuffer,readLen); } @Override public final int skipBytes(int n) throws IOException { return dataInStream.skipBytes(n); } @Override public final boolean readBoolean() throws IOException { return dataInStream.readBoolean(); } @Override public final byte readByte() throws IOException { return dataInStream.readByte(); } @Override public final float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); } @Override public final double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); } @Override public final short readShort() throws IOException { return dataInStream.readShort(); } @Override public final int readUnsignedShort() throws IOException { return dataInStream.readUnsignedShort(); } @Override public final long readLong() throws IOException { return dataInStream.readLong(); } @Override public final char readChar() throws IOException { return dataInStream.readChar(); } @Override public final int readInt() throws IOException { return dataInStream.readInt(); } /** * Reads floating point type stored in little endian (see readFloat() for big endian) * @return float value translated from little endian * @throws IOException if an IO error occurs */ public final float readLittleFloat() throws IOException { return Float.intBitsToFloat(readLittleInt()); } /** * Reads double precision floating point type stored in little endian (see readDouble() for big endian) * @return double precision float value translated from little endian * @throws IOException if an IO error occurs */ public final double readLittleDouble() throws IOException { return Double.longBitsToDouble(readLittleLong()); } /** * Reads short type stored in little endian (see readShort() for big endian) * @return short value translated from little endian * @throws IOException if an IO error occurs */ public final short readLittleShort() throws IOException { dataInStream.readFully(byteBuffer,2); return (short)((byteBuffer[1] & 0xff) << 8 | (byteBuffer[0] & 0xff)); } /** * Reads char (16-bits) type stored in little endian (see readChar() for big endian) * @return char value translated from little endian * @throws IOException if an IO error occurs */ public final char readLittleChar() throws IOException { dataInStream.readFully(byteBuffer,2); return (char)((byteBuffer[1] & 0xff) << 8 | (byteBuffer[0] & 0xff)); } /** * Reads integer type stored in little endian (see readInt() for big endian) * @return integer value translated from little endian * @throws IOException if an IO error occurs */ public final int readLittleInt() throws IOException { dataInStream.readFully(byteBuffer,4); return (byteBuffer[3]) << 24 | (byteBuffer[2] & 0xff) << 16 | (byteBuffer[1] & 0xff) << 8 | (byteBuffer[0] & 0xff); } /** * Reads long type stored in little endian (see readLong() for big endian) * @return long value translated from little endian * @throws IOException if an IO error occurs */ public final long readLittleLong() throws IOException { dataInStream.readFully(byteBuffer,8); return (long)(byteBuffer[7]) << 56 | (long)(byteBuffer[6]&0xff) << 48 | (long)(byteBuffer[5] & 0xff) << 40 | (long)(byteBuffer[4] & 0xff) << 32 | (long)(byteBuffer[3] & 0xff) << 24 | (long)(byteBuffer[2] & 0xff) << 16 | (long)(byteBuffer[1] & 0xff) << 8 | (long)(byteBuffer[0] & 0xff); } /** * Reads unsigned short type stored in little endian (see readUnsignedShort() for big endian) * @return integer value representing unsigned short value translated from little endian * @throws IOException if an IO error occurs */ public final int readLittleUnsignedShort() throws IOException { dataInStream.readFully(byteBuffer,2); return ((byteBuffer[1] & 0xff) << 8 | (byteBuffer[0] & 0xff)); } }
解决方法
readBoolean()
读取一个字节.
readLine()
读取单个字节并将其转换为char.
readUTF()
读取修改的UTF-8(其代码单元大小为一个八位位组). UTF-8有no endianness.
这些方法没有任何关注.
关于设计,请考虑该类型是否需要InputStream,以及ByteBuffer
是否有用.如果您没有使用像mark / reset和Closeable
这样的功能,您可能不会公开新的类型:
public class Bytes { public static DataInput littleEndian(final DataInput decorated) { class LittleInput implements DataInput { private ByteBuffer buffer = ByteBuffer.allocate(8); public int readInt() throws IOException { buffer.clear(); buffer.order(ByteOrder.BIG_ENDIAN) .putInt(decorated.readInt()) .flip(); return buffer.order(ByteOrder.LITTLE_ENDIAN) .getInt(); } //TODO: other methods } return new LittleInput(); } }
我注意到,流行的番石榴图书馆已经有LittleEndianDataInputStream.