001/* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.io; 016 017import com.google.common.annotations.Beta; 018import com.google.common.annotations.GwtIncompatible; 019import com.google.common.base.Preconditions; 020import com.google.common.primitives.Ints; 021import com.google.common.primitives.Longs; 022import com.google.errorprone.annotations.CanIgnoreReturnValue; 023import java.io.DataInput; 024import java.io.DataInputStream; 025import java.io.EOFException; 026import java.io.FilterInputStream; 027import java.io.IOException; 028import java.io.InputStream; 029 030/** 031 * An implementation of {@link DataInput} that uses little-endian byte ordering for reading {@code 032 * short}, {@code int}, {@code float}, {@code double}, and {@code long} values. 033 * 034 * <p><b>Note:</b> This class intentionally violates the specification of its supertype {@code 035 * DataInput}, which explicitly requires big-endian byte order. 036 * 037 * @author Chris Nokleberg 038 * @author Keith Bottner 039 * @since 8.0 040 */ 041@Beta 042@GwtIncompatible 043public final class LittleEndianDataInputStream extends FilterInputStream implements DataInput { 044 045 /** 046 * Creates a {@code LittleEndianDataInputStream} that wraps the given stream. 047 * 048 * @param in the stream to delegate to 049 */ 050 public LittleEndianDataInputStream(InputStream in) { 051 super(Preconditions.checkNotNull(in)); 052 } 053 054 /** This method will throw an {@link UnsupportedOperationException}. */ 055 @CanIgnoreReturnValue // to skip a line 056 @Override 057 public String readLine() { 058 throw new UnsupportedOperationException("readLine is not supported"); 059 } 060 061 @Override 062 public void readFully(byte[] b) throws IOException { 063 ByteStreams.readFully(this, b); 064 } 065 066 @Override 067 public void readFully(byte[] b, int off, int len) throws IOException { 068 ByteStreams.readFully(this, b, off, len); 069 } 070 071 @Override 072 public int skipBytes(int n) throws IOException { 073 return (int) in.skip(n); 074 } 075 076 @CanIgnoreReturnValue // to skip a byte 077 @Override 078 public int readUnsignedByte() throws IOException { 079 int b1 = in.read(); 080 if (0 > b1) { 081 throw new EOFException(); 082 } 083 084 return b1; 085 } 086 087 /** 088 * Reads an unsigned {@code short} as specified by {@link DataInputStream#readUnsignedShort()}, 089 * except using little-endian byte order. 090 * 091 * @return the next two bytes of the input stream, interpreted as an unsigned 16-bit integer in 092 * little-endian byte order 093 * @throws IOException if an I/O error occurs 094 */ 095 @CanIgnoreReturnValue // to skip some bytes 096 @Override 097 public int readUnsignedShort() throws IOException { 098 byte b1 = readAndCheckByte(); 099 byte b2 = readAndCheckByte(); 100 101 return Ints.fromBytes((byte) 0, (byte) 0, b2, b1); 102 } 103 104 /** 105 * Reads an integer as specified by {@link DataInputStream#readInt()}, except using little-endian 106 * byte order. 107 * 108 * @return the next four bytes of the input stream, interpreted as an {@code int} in little-endian 109 * byte order 110 * @throws IOException if an I/O error occurs 111 */ 112 @CanIgnoreReturnValue // to skip some bytes 113 @Override 114 public int readInt() throws IOException { 115 byte b1 = readAndCheckByte(); 116 byte b2 = readAndCheckByte(); 117 byte b3 = readAndCheckByte(); 118 byte b4 = readAndCheckByte(); 119 120 return Ints.fromBytes(b4, b3, b2, b1); 121 } 122 123 /** 124 * Reads a {@code long} as specified by {@link DataInputStream#readLong()}, except using 125 * little-endian byte order. 126 * 127 * @return the next eight bytes of the input stream, interpreted as a {@code long} in 128 * little-endian byte order 129 * @throws IOException if an I/O error occurs 130 */ 131 @CanIgnoreReturnValue // to skip some bytes 132 @Override 133 public long readLong() throws IOException { 134 byte b1 = readAndCheckByte(); 135 byte b2 = readAndCheckByte(); 136 byte b3 = readAndCheckByte(); 137 byte b4 = readAndCheckByte(); 138 byte b5 = readAndCheckByte(); 139 byte b6 = readAndCheckByte(); 140 byte b7 = readAndCheckByte(); 141 byte b8 = readAndCheckByte(); 142 143 return Longs.fromBytes(b8, b7, b6, b5, b4, b3, b2, b1); 144 } 145 146 /** 147 * Reads a {@code float} as specified by {@link DataInputStream#readFloat()}, except using 148 * little-endian byte order. 149 * 150 * @return the next four bytes of the input stream, interpreted as a {@code float} in 151 * little-endian byte order 152 * @throws IOException if an I/O error occurs 153 */ 154 @CanIgnoreReturnValue // to skip some bytes 155 @Override 156 public float readFloat() throws IOException { 157 return Float.intBitsToFloat(readInt()); 158 } 159 160 /** 161 * Reads a {@code double} as specified by {@link DataInputStream#readDouble()}, except using 162 * little-endian byte order. 163 * 164 * @return the next eight bytes of the input stream, interpreted as a {@code double} in 165 * little-endian byte order 166 * @throws IOException if an I/O error occurs 167 */ 168 @CanIgnoreReturnValue // to skip some bytes 169 @Override 170 public double readDouble() throws IOException { 171 return Double.longBitsToDouble(readLong()); 172 } 173 174 @CanIgnoreReturnValue // to skip a field 175 @Override 176 public String readUTF() throws IOException { 177 return new DataInputStream(in).readUTF(); 178 } 179 180 /** 181 * Reads a {@code short} as specified by {@link DataInputStream#readShort()}, except using 182 * little-endian byte order. 183 * 184 * @return the next two bytes of the input stream, interpreted as a {@code short} in little-endian 185 * byte order. 186 * @throws IOException if an I/O error occurs. 187 */ 188 @CanIgnoreReturnValue // to skip some bytes 189 @Override 190 public short readShort() throws IOException { 191 return (short) readUnsignedShort(); 192 } 193 194 /** 195 * Reads a char as specified by {@link DataInputStream#readChar()}, except using little-endian 196 * byte order. 197 * 198 * @return the next two bytes of the input stream, interpreted as a {@code char} in little-endian 199 * byte order 200 * @throws IOException if an I/O error occurs 201 */ 202 @CanIgnoreReturnValue // to skip some bytes 203 @Override 204 public char readChar() throws IOException { 205 return (char) readUnsignedShort(); 206 } 207 208 @CanIgnoreReturnValue // to skip a byte 209 @Override 210 public byte readByte() throws IOException { 211 return (byte) readUnsignedByte(); 212 } 213 214 @CanIgnoreReturnValue // to skip a byte 215 @Override 216 public boolean readBoolean() throws IOException { 217 return readUnsignedByte() != 0; 218 } 219 220 /** 221 * Reads a byte from the input stream checking that the end of file (EOF) has not been 222 * encountered. 223 * 224 * @return byte read from input 225 * @throws IOException if an error is encountered while reading 226 * @throws EOFException if the end of file (EOF) is encountered. 227 */ 228 private byte readAndCheckByte() throws IOException, EOFException { 229 int b1 = in.read(); 230 231 if (-1 == b1) { 232 throw new EOFException(); 233 } 234 235 return (byte) b1; 236 } 237}