Java:DataInputStream替换字节序

Wil*_*rer 10 java endianness

下面是我的代码替换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, 0, refBuffer.length);
    }

    @Override
    public final void readFully(byte refBuffer[], int offset, int readLen) throws IOException {
        dataInStream.readFully(refBuffer, offset, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 2);
        return ((byteBuffer[1] & 0xff) << 8 | (byteBuffer[0] & 0xff));
    }
}
Run Code Online (Sandbox Code Playgroud)

McD*_*ell 7

readBoolean()读取一个字节.readLine()读取单个字节并将每个字节转换为a char.

readUTF()读取修改后的UTF-8(代码单元大小为一个八位字节).UTF-8 没有字节顺序.

这些方法没有字节顺序.

至于设计,考虑类型是否需要是一个InputStream以及是否ByteBuffer有用.如果您没有使用标记/重置等功能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();
  }

}
Run Code Online (Sandbox Code Playgroud)

我注意到流行的Guava库已经有了LittleEndianDataInputStream.