2011-11-06 9 views
10

Poniżej znajduje się mój kod, który zastępuje DataInputStream, aby owinąć InputStream, ale zapewnia dodatkowe metody do czytania małych typów danych endianowych oprócz normalnych metod odczytywania dużych typów endianów. Jeśli chcesz, możesz go użyć.Java: Zastąpienie DataInputStream dla endianness

Mam kilka zastrzeżeń w następujący sposób. Zwróć uwagę na metody, które nie zmieniają funkcjonalności (funkcje czytające duże typy endian). Nie ma możliwości wdrożenia DataInputStream jako klasy bazowej i użycia jego metod, takich jak read(), readInt(), readChar(), etc?

Moja hierarchia klasowa wydaje się tu trochę dziwna. Czy to jest właściwe?

Czy któryś z tych innych typów, takich jak readUTF() czy readLine(), potrzebuje trochę wersji endian? Czy jest to subiektywne dla konkretnych programów?

W jaki sposób Java przechowuje typy boolowskie? Czy to też jest subiektywne dla endianizmu?

Dzięki za spełniającą moje ciekawostki :)

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 ([email protected]) 
*/ 
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)); 
    } 
} 

Odpowiedz

7

readBoolean() czyta jeden bajt. readLine() czyta pojedyncze bajty i konwertuje je do char.

readUTF() odczytuje zmodyfikowany kodek UTF-8 (który ma jednostkę jednostki kodu o jednym oktecie). UTF-8 ma no endianness.

Nie ma obaw związanych z endianizmem w przypadku tych metod.

Jeśli chodzi o projekt, należy rozważyć, czy dany typ musi być typu InputStream i czy użyteczny może być ByteBuffer. Jeśli nie używali funkcji, takich jak znak/reset i Closeable nie może wystawiać nowy typ:

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

} 

Pragnę zauważyć, że popularne biblioteki Guava ma już LittleEndianDataInputStream.

+0

Dziękuję. Czy Guava jest dostępna jako standardowa platforma uruchomieniowa Java, którą większość ludzi ma już na swoich komputerach? –

+0

@ user1030796 - nie, [Guava] (http://code.google.com/p/guava-libraries/) to zewnętrzna biblioteka udostępniana przez Google. – McDowell

+0

Format ESRI shapefile łączy mały i duży endian w jednym formacie, więc chciałem udostępnić oba typy z jednej klasy, tak jak tutaj. –