2011-11-06 14 views
10

Di seguito è riportato il mio codice che sostituisce DataInputStream per includere un InputStream, ma fornisce metodi aggiuntivi per leggere i tipi di dati little endian oltre ai normali metodi che leggono i tipi big endian. Sentiti libero di usarlo se vuoi.Java: sostituzione DataInputStream per endianness

Ho alcune prenotazioni come segue. Notare i metodi che non cambiano la funzionalità (le funzioni che leggono i tipi big endian). Non è possibile implementare DataInputStream come classe base e utilizzare i suoi metodi, come read(), readInt(), readChar(), etc?

La mia gerarchia di classe sembra un po 'strana qui. È appropriato?

Qualcuno di questi altri tipi come readUTF() o readLine() ha bisogno di una versione little endian? O è soggettivo a programmi specifici?

In che modo Java memorizza i tipi booleani? Anche questo è soggettivo all'endianesimo?

Grazie per soddisfare le mie curiosità :)

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

risposta

7

readBoolean() legge un singolo byte. readLine() legge byte singoli e converte ciascuno in un char.

readUTF() legge UTF-8 modificato (che ha una dimensione dell'unità di codice di un ottetto). UTF-8 ha no endianness.

Non ci sono problemi di endianità con questi metodi.

Per quanto riguarda la progettazione, considerare se il tipo deve essere un InputStream e se il ByteBuffer potrebbe essere utile. Se non si sta utilizzando funzioni come segno/reset e Closeable non si potrebbe esporre il nuovo tipo:

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

} 

faccio notare che la biblioteca Guava popolare ha già LittleEndianDataInputStream.

+0

Grazie. Guava è disponibile come parte della piattaforma di runtime Java standard che la maggior parte delle persone ha già sul proprio computer? –

+0

@ user1030796 - no, [Guava] (http://code.google.com/p/guava-libraries/) è una libreria di terze parti fornita da Google. – McDowell

+0

Il formato shapefile di ESRI miscela sia little che big endian in un unico formato, quindi ho voluto fornire entrambi i tipi da una singola classe come ho fatto qui. –