Java:DataInputStream替换字节序 [英] Java : DataInputStream replacement for endianness

查看:191
本文介绍了Java:DataInputStream替换字节序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的代码,它替换了DataInputStream以包装InputStream,但除了读取大端类型的常规方法之外,还提供了读取小端数据类型的额外方法。如果您愿意,请随意使用。

Below is my code that replaces the DataInputStream to wrap an InputStream, but provides extra methods to read little endian data types in addition to the normal methods that read big endian types. Feel free to use it if you'd like.

我有一些保留如下。请注意不改变功能的方法(读取大端类型的函数)。我无法将DataInputStream实现为基类并使用其方法,如read(),readInt(),readChar()等?

I have a few reservations as follows. Notice the methods that do not change functionality (the functions that read big endian types). There is no way I could implement the DataInputStream as the base class and use its methods, like read(), readInt(), readChar(), etc?

我的班级层次结构在这里看起来有点奇怪。这是否合适?

My class hierarchy seems a little odd here. Is this appropriate?

这些其他类型如readUTF()或readLine()是否需要一个小的endian版本?或者对特定程序是主观的?

Do any of these other types like readUTF() or readLine() need a little endian version? Or is that subjective to specific programs?

Java如何存储布尔类型?这对于字节顺序是否也是主观的?

How does Java store boolean types? Is that subjective to endianness also?

感谢您满足我的好奇心:))

Thanks for satisfying my curiosities :)

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));
    }
}


推荐答案

< a href =http://download.oracle.com/javase/7/docs/api/java/io/DataInput.html#readBoolean%28%29> readBoolean() 读取单个字节。 readLine() 读取单个字节并将每个字节转换为 char

的readUTF() 读取修改后的UTF-8(代码单元大小为一个八位字节)。 UTF-8有 no endianness

这些方法没有字节序问题。

There are no endianness concerns with these methods.

关于设计,请考虑类型是否需要是 InputStream 以及是否 ByteBuffer 可能有用。如果您没有使用标记/重置和 等功能您可能不会公开新类型

As to the design, consider whether the type needs to be an InputStream and whether the ByteBuffer might be useful. If you weren't using features like mark/reset and Closeable you might not expose the new type:

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();
  }

}

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

I note that the popular Guava library already has LittleEndianDataInputStream.

这篇关于Java:DataInputStream替换字节序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆