001 /* 002 Copyright (c) 2003, The Regents of the University of California, through 003 Lawrence Berkeley National Laboratory (subject to receipt of any required 004 approvals from the U.S. Dept. of Energy). All rights reserved. 005 */ 006 package gov.lbl.dsd.sea.nio.util; 007 008 /** 009 Efficient big endian array conversions for high performance I/O through bulk data 010 transfer rather than piece-wise transfer. (You may want to disregard this class in 011 favour of the conversion facilities in the {@link java.nio.ByteBuffer} family of classes). 012 <p> 013 Avoids deep non-inlined synchronized 014 call chains in the java.io package. The following conversions are supported: 015 <ul> 016 <li>for all primitive data types: <tt>type[] --> byte[]</tt>, as well as <tt>type --> byte[]</tt></li> 017 <li>for all primitive data types: <tt>byte[] --> type[]</tt>, as well as <tt>byte[] --> type</tt></li> 018 </ul> 019 This <b>exactly mimics</b> the semantics of {@link java.io.DataInputStream} and 020 {@link java.io.DataOutputStream}. In fact, this is a copy&paste of the JDK 1.4.2 021 source code of these two classes, with efficient loops written around. 022 Not only for disk I/O, but also for other kinds of serialization, e.g. high bandwidth networking. 023 <h3>Fast writing:</h3> 024 <ul> 025 <li>Convert your data into a byte[] using 026 <ul> 027 <li>for all primitive data types: type[] --> byte[]: Example: <tt>write(double[] 028 src, int srcPos, byte[] dest, int destPos, int length)</tt></li> 029 <li>for all primitive data types: type --> byte[]: Example: <tt>writeDouble(double 030 src, byte[] dest, int destPos)</tt></li> 031 </ul> 032 <li>then write it with a single call {@link java.io.FileOutputStream#write(byte[], int, int)}, perhaps buffered.</li> 033 </ul> 034 <h3>Fast reading:</h3> 035 <ul> 036 <li>Read your data into a byte[] with a single call {@link java.io.FileInputStream#read(byte[], int, int)}, perhaps buffered. 037 <li>Then convert it into the desired data type using 038 <ul> 039 <li>for all primitive data types: byte[] --> type[]: Example: <tt>read(byte[] 040 src, int srcPos, double[] dest, int destPos, int length)</tt></li> 041 <li>for all primitive data types: byte[] --> type: Example: <tt>readInt(byte[] 042 src, int srcPos)</tt></li> 043 </ul> 044 </li> 045 </ul> 046 The method arguments are exactly as used in {@link System#arraycopy}, except for 047 the <tt>length</tt> argument which is always given in primitive element units! 048 Please don't flame for not writing redundant javadoc for each and every method. 049 050 @author whoschek@lbl.gov 051 @author $Author: hoschek3 $ 052 @version $Revision: 1.12 $, $Date: 2004/07/28 01:53:13 $ 053 */ 054 055 public class ByteConverter { 056 // TODO: Consider rewriting this class using java.nio.ByteBuffer !? 057 058 protected ByteConverter() {} 059 060 // number of bytes occupied for each primitive data type: 061 public static final int SIZE_OF_BOOLEAN = 1; 062 public static final int SIZE_OF_BYTE = 1; 063 public static final int SIZE_OF_CHAR = 2; 064 public static final int SIZE_OF_SHORT = 2; 065 public static final int SIZE_OF_INT = 4; 066 public static final int SIZE_OF_FLOAT = 4; 067 public static final int SIZE_OF_LONG = 8; 068 public static final int SIZE_OF_DOUBLE = 8; 069 070 public static byte readByte(byte[] src, int srcPos) { 071 return src[srcPos]; 072 } 073 074 public static boolean readBoolean(byte[] src, int srcPos) { 075 return (src[srcPos] & 0xFF) != 0; 076 } 077 078 public static char readChar(byte[] src, int srcPos) { 079 int b0 = src[srcPos ] & 0xFF; 080 int b1 = src[srcPos+1] & 0xFF; 081 return (char)((b0 << 8) + (b1 << 0)); 082 } 083 084 public static short readShort(byte[] src, int srcPos) { 085 int b0 = src[srcPos ] & 0xFF; 086 int b1 = src[srcPos+1] & 0xFF; 087 return (short)((b0 << 8) + (b1 << 0)); 088 } 089 090 public static int readInt(byte[] src, int srcPos) { 091 int b0 = src[srcPos ] & 0xFF; 092 int b1 = src[srcPos+1] & 0xFF; 093 int b2 = src[srcPos+2] & 0xFF; 094 int b3 = src[srcPos+3] & 0xFF; 095 return (b0 << 24) + (b1 << 16) + (b2 << 8) + (b3 << 0); 096 } 097 098 public static float readFloat(byte[] src, int srcPos) { 099 return Float.intBitsToFloat(readInt(src,srcPos)); 100 } 101 102 public static long readLong(byte[] src, int srcPos) { 103 return (((long)src[srcPos] << 56) + 104 ((long)(src[srcPos+1] & 255) << 48) + 105 ((long)(src[srcPos+2] & 255) << 40) + 106 ((long)(src[srcPos+3] & 255) << 32) + 107 ((long)(src[srcPos+4] & 255) << 24) + 108 ((src[srcPos+5] & 255) << 16) + 109 ((src[srcPos+6] & 255) << 8) + 110 ((src[srcPos+7] & 255) << 0)); 111 } 112 113 public static double readDouble(byte[] src, int srcPos) { 114 return Double.longBitsToDouble(readLong(src,srcPos)); 115 } 116 117 public static int readUnsignedByte(byte[] src, int srcPos) { 118 return src[srcPos] & 0xFF; 119 } 120 121 public static int readUnsignedShort(byte[] src, int srcPos) { 122 int b0 = src[srcPos ] & 0xFF; 123 int b1 = src[srcPos+1] & 0xFF; 124 return (b0 << 8) + (b1 << 0); 125 } 126 127 public static long readUnsignedInt(byte[]src, int srcPos) { 128 return ((src[srcPos ] & 0xFFL) << 24) 129 + ((src[srcPos+1] & 0xFF) << 16) 130 + ((src[srcPos+2] & 0xFF) << 8) 131 + ( src[srcPos+3] & 0xFF); 132 } 133 134 /** 135 * Returns the integer value gained when interpreting the value v as an <em>unsigned byte</em>. 136 * Example: readUnsignedByte(0xFF) == 255, rather than -1. 137 */ 138 public static int readUnsignedByte(byte v) { 139 return v & 0xFF; 140 } 141 142 /** 143 * Returns the integer value gained when interpreting the value v as an <em>unsigned short</em>. 144 */ 145 public static int readUnsignedShort(short v) { 146 return v & 0xFFFF; 147 } 148 149 /** 150 * Returns the long value gained when interpreting the value v as an <em>unsigned int</em>. 151 */ 152 public static long readUnsignedInt(int v) { 153 return v & 0xFFFFFFFFL; 154 } 155 156 public static void read(byte[] src, int srcPos, byte[] dest, int destPos, int length) { 157 System.arraycopy(src, srcPos, dest, destPos, length); 158 } 159 160 public static void read(byte[] src, int srcPos, boolean[] dest, int destPos, int length) { 161 while (--length >= 0) { 162 dest[destPos++] = readBoolean(src,srcPos); 163 srcPos += SIZE_OF_BOOLEAN; 164 } 165 } 166 167 public static void read(byte[] src, int srcPos, char[] dest, int destPos, int length) { 168 while (--length >= 0) { 169 dest[destPos++] = readChar(src,srcPos); 170 srcPos += SIZE_OF_CHAR; 171 } 172 } 173 174 public static void read(byte[] src, int srcPos, short[] dest, int destPos, int length) { 175 while (--length >= 0) { 176 dest[destPos++] = readShort(src,srcPos); 177 srcPos += SIZE_OF_SHORT; 178 } 179 } 180 181 public static void read(byte[] src, int srcPos, int[] dest, int destPos, int length) { 182 while (--length >= 0) { 183 dest[destPos++] = readInt(src,srcPos); 184 srcPos += SIZE_OF_INT; 185 } 186 } 187 188 public static void read(byte[] src, int srcPos, float[] dest, int destPos, int length) { 189 while (--length >= 0) { 190 dest[destPos++] = readFloat(src,srcPos); 191 srcPos += SIZE_OF_FLOAT; 192 } 193 } 194 195 public static void read(byte[] src, int srcPos, long[] dest, int destPos, int length) { 196 while (--length >= 0) { 197 dest[destPos++] = readLong(src,srcPos); 198 srcPos += SIZE_OF_LONG; 199 } 200 } 201 202 public static void read(byte[] src, int srcPos, double[] dest, int destPos, int length) { 203 while (--length >= 0) { 204 dest[destPos++] = readDouble(src,srcPos); 205 srcPos += SIZE_OF_DOUBLE; 206 } 207 } 208 209 // /** 210 // * The inverse to {@link #writeBytes(String, int, byte[], int, int)}; each single byte is converted to a 2 byte char. 211 // */ 212 // public static String readBytes(byte[] src, int srcPos, char[] buffer, int destPos, int length) { 213 // int len = length; 214 // int pos = destPos; 215 // while (--length >= 0) { 216 // buffer[destPos++] = (char) readByte(src,srcPos); 217 // srcPos += SIZE_OF_BYTE; 218 // } 219 // return new String(buffer,pos,len); 220 // } 221 // 222 // public static String readChars(byte[] src, int srcPos, char[] buffer, int destPos, int length) { 223 // int len = length; 224 // int pos = destPos; 225 // while (--length >= 0) { 226 // buffer[destPos++] = readChar(src,srcPos); 227 // srcPos += SIZE_OF_CHAR; 228 // } 229 // return new String(buffer,pos,len); 230 // } 231 232 public static void writeByte(byte v, byte[] dest, int destPos) { 233 dest[destPos] = v; 234 } 235 236 public static void writeBoolean(boolean v, byte[] dest, int destPos) { 237 dest[destPos] = (byte) (v ? 1 : 0); 238 } 239 240 public static void writeChar(char v, byte[] dest, int destPos) { 241 dest[destPos ] = (byte) ((v >>> 8) & 0xFF); 242 dest[destPos+1] = (byte) ((v >>> 0) & 0xFF); 243 } 244 245 public static void writeShort(short v, byte[] dest, int destPos) { 246 dest[destPos ] = (byte) ((v >>> 8) & 0xFF); 247 dest[destPos+1] = (byte) ((v >>> 0) & 0xFF); 248 } 249 250 public static void writeFloat(float v, byte[] dest, int destPos) { 251 writeInt(Float.floatToIntBits(v),dest,destPos); 252 } 253 254 public static void writeInt(int v, byte[] dest, int destPos) { 255 dest[destPos ] = (byte) ((v >>> 24) & 0xFF); 256 dest[destPos+1] = (byte) ((v >>> 16) & 0xFF); 257 dest[destPos+2] = (byte) ((v >>> 8) & 0xFF); 258 dest[destPos+3] = (byte) ((v >>> 0) & 0xFF); 259 } 260 261 public static void writeLong(long v, byte[] dest, int destPos) { 262 dest[destPos ] = (byte) ((int)(v >>> 56) & 0xFF); 263 dest[destPos+1] = (byte) ((int)(v >>> 48) & 0xFF); 264 dest[destPos+2] = (byte) ((int)(v >>> 40) & 0xFF); 265 dest[destPos+3] = (byte) ((int)(v >>> 32) & 0xFF); 266 dest[destPos+4] = (byte) ((int)(v >>> 24) & 0xFF); 267 dest[destPos+5] = (byte) ((int)(v >>> 16) & 0xFF); 268 dest[destPos+6] = (byte) ((int)(v >>> 8) & 0xFF); 269 dest[destPos+7] = (byte) ((int)(v >>> 0) & 0xFF); 270 } 271 272 public static void writeDouble(double src, byte[] dest, int destPos) { 273 writeLong(Double.doubleToLongBits(src),dest,destPos); 274 } 275 276 public static void writeUnsignedShort(int v, byte[] dest, int destPos) { 277 if (v < 0 || v > 65535) // (int) Math.pow(2.0, 16) - 1 278 throw new IllegalArgumentException( 279 "unsigned short: " + v + " must be in the range [0,65535]"); 280 dest[destPos ] = (byte) ((v >>> 8) & 0xFF); 281 dest[destPos+1] = (byte) ((v >>> 0) & 0xFF); 282 } 283 284 public static void writeUnsignedInt(long v, byte[] dest, int destPos) { // from karlo 285 if (v < 0 || v > 4294967295L) // (long) Math.pow(2.0, 32) - 1 286 throw new IllegalArgumentException( 287 "unsigned int: " + v + " must be in the range [0,4294967295]"); 288 dest[destPos ] = (byte) ((v >>> 24) & 0xFF); 289 dest[destPos+1] = (byte) ((v >>> 16) & 0xFF); 290 dest[destPos+2] = (byte) ((v >>> 8) & 0xFF); 291 dest[destPos+3] = (byte) ((v >>> 0) & 0xFF); 292 } 293 294 public static void write(byte[] src, int srcPos, byte[] dest, int destPos, int length) { 295 System.arraycopy(src,srcPos,dest,destPos,length); 296 } 297 298 public static void write(boolean[] src, int srcPos, byte[] dest, int destPos, int length) { 299 while (--length >= 0) { 300 writeBoolean(src[srcPos++],dest,destPos); 301 destPos += SIZE_OF_BOOLEAN; 302 } 303 } 304 305 public static void write(char[] src, int srcPos, byte[] dest, int destPos, int length) { 306 while (--length >= 0) { 307 writeChar(src[srcPos++],dest,destPos); 308 destPos += SIZE_OF_CHAR; 309 } 310 } 311 312 public static void write(short[] src, int srcPos, byte[] dest, int destPos, int length) { 313 while (--length >= 0) { 314 writeShort(src[srcPos++],dest,destPos); 315 destPos += SIZE_OF_SHORT; 316 } 317 } 318 319 public static void write(int[] src, int srcPos, byte[] dest, int destPos, int length) { 320 while (--length >= 0) { 321 writeInt(src[srcPos++],dest,destPos); 322 destPos += SIZE_OF_INT; 323 } 324 } 325 326 public static void write(float[] src, int srcPos, byte[] dest, int destPos, int length) { 327 while (--length >= 0) { 328 writeFloat(src[srcPos++],dest,destPos); 329 destPos += SIZE_OF_FLOAT; 330 } 331 } 332 333 public static void write(long[] src, int srcPos, byte[] dest, int destPos, int length) { 334 while (--length >= 0) { 335 writeLong(src[srcPos++],dest,destPos); 336 destPos += SIZE_OF_LONG; 337 } 338 } 339 340 public static void write(double[] src, int srcPos, byte[] dest, int destPos, int length) { 341 while (--length >= 0) { 342 writeDouble(src[srcPos++],dest,destPos); 343 destPos += SIZE_OF_DOUBLE; 344 } 345 } 346 347 // /** 348 // * Writes out the string to the underlying byte array as a 349 // * sequence of bytes. Warning: Each character in the string is written out, in 350 // * sequence, by ignoring its high eight bits. 351 // */ 352 // public static void writeBytes(String src, int srcPos, byte[] dest, int destPos, int length) { 353 // byte v; 354 // while (--length >= 0) { 355 // v = (byte) src.charAt(srcPos++); 356 // dest[destPos] = v; 357 // destPos += SIZE_OF_BYTE; 358 // } 359 // } 360 // 361 // public static void writeChars(String src, int srcPos, byte[] dest, int destPos, int length) { 362 // char v; 363 // while (--length >= 0) { 364 // v = src.charAt(srcPos++); 365 // writeChar(v, dest, destPos); 366 // destPos += SIZE_OF_CHAR; 367 // } 368 // } 369 370 }