1/* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33package com.jme3.export.binary; 34 35import java.io.ByteArrayOutputStream; 36import java.io.IOException; 37import java.io.InputStream; 38import java.io.OutputStream; 39 40/** 41 * <code>ByteUtils</code> is a helper class for converting numeric primitives 42 * to and from byte representations. 43 * 44 * @author Joshua Slack 45 */ 46public class ByteUtils { 47 48 /** 49 * Takes an InputStream and returns the complete byte content of it 50 * 51 * @param inputStream 52 * The input stream to read from 53 * @return The byte array containing the data from the input stream 54 * @throws java.io.IOException 55 * thrown if there is a problem reading from the input stream 56 * provided 57 */ 58 public static byte[] getByteContent(InputStream inputStream) 59 throws IOException { 60 ByteArrayOutputStream outputStream = new ByteArrayOutputStream( 61 16 * 1024); 62 byte[] buffer = new byte[1024]; 63 int byteCount = -1; 64 byte[] data = null; 65 66 // Read the byte content into the output stream first 67 while ((byteCount = inputStream.read(buffer)) > 0) { 68 outputStream.write(buffer, 0, byteCount); 69 } 70 71 // Set data with byte content from stream 72 data = outputStream.toByteArray(); 73 74 // Release resources 75 outputStream.close(); 76 77 return data; 78 } 79 80 81 // ********** byte <> short METHODS ********** 82 83 /** 84 * Writes a short out to an OutputStream. 85 * 86 * @param outputStream 87 * The OutputStream the short will be written to 88 * @param value 89 * The short to write 90 * @throws IOException 91 * Thrown if there is a problem writing to the OutputStream 92 */ 93 public static void writeShort(OutputStream outputStream, short value) 94 throws IOException { 95 byte[] byteArray = convertToBytes(value); 96 97 outputStream.write(byteArray); 98 99 return; 100 } 101 102 public static byte[] convertToBytes(short value) { 103 byte[] byteArray = new byte[2]; 104 105 byteArray[0] = (byte) (value >> 8); 106 byteArray[1] = (byte) value; 107 return byteArray; 108 } 109 110 /** 111 * Read in a short from an InputStream 112 * 113 * @param inputStream 114 * The InputStream used to read the short 115 * @return A short, which is the next 2 bytes converted from the InputStream 116 * @throws IOException 117 * Thrown if there is a problem reading from the InputStream 118 */ 119 public static short readShort(InputStream inputStream) throws IOException { 120 byte[] byteArray = new byte[2]; 121 122 // Read in the next 2 bytes 123 inputStream.read(byteArray); 124 125 short number = convertShortFromBytes(byteArray); 126 127 return number; 128 } 129 130 public static short convertShortFromBytes(byte[] byteArray) { 131 return convertShortFromBytes(byteArray, 0); 132 } 133 134 public static short convertShortFromBytes(byte[] byteArray, int offset) { 135 // Convert it to a short 136 short number = (short) ((byteArray[offset+1] & 0xFF) + ((byteArray[offset+0] & 0xFF) << 8)); 137 return number; 138 } 139 140 141 // ********** byte <> int METHODS ********** 142 143 /** 144 * Writes an integer out to an OutputStream. 145 * 146 * @param outputStream 147 * The OutputStream the integer will be written to 148 * @param integer 149 * The integer to write 150 * @throws IOException 151 * Thrown if there is a problem writing to the OutputStream 152 */ 153 public static void writeInt(OutputStream outputStream, int integer) 154 throws IOException { 155 byte[] byteArray = convertToBytes(integer); 156 157 outputStream.write(byteArray); 158 159 return; 160 } 161 162 public static byte[] convertToBytes(int integer) { 163 byte[] byteArray = new byte[4]; 164 165 byteArray[0] = (byte) (integer >> 24); 166 byteArray[1] = (byte) (integer >> 16); 167 byteArray[2] = (byte) (integer >> 8); 168 byteArray[3] = (byte) integer; 169 return byteArray; 170 } 171 172 /** 173 * Read in an integer from an InputStream 174 * 175 * @param inputStream 176 * The InputStream used to read the integer 177 * @return An int, which is the next 4 bytes converted from the InputStream 178 * @throws IOException 179 * Thrown if there is a problem reading from the InputStream 180 */ 181 public static int readInt(InputStream inputStream) throws IOException { 182 byte[] byteArray = new byte[4]; 183 184 // Read in the next 4 bytes 185 inputStream.read(byteArray); 186 187 int number = convertIntFromBytes(byteArray); 188 189 return number; 190 } 191 192 public static int convertIntFromBytes(byte[] byteArray) { 193 return convertIntFromBytes(byteArray, 0); 194 } 195 196 public static int convertIntFromBytes(byte[] byteArray, int offset) { 197 // Convert it to an int 198 int number = ((byteArray[offset] & 0xFF) << 24) 199 + ((byteArray[offset+1] & 0xFF) << 16) + ((byteArray[offset+2] & 0xFF) << 8) 200 + (byteArray[offset+3] & 0xFF); 201 return number; 202 } 203 204 205 // ********** byte <> long METHODS ********** 206 207 /** 208 * Writes a long out to an OutputStream. 209 * 210 * @param outputStream 211 * The OutputStream the long will be written to 212 * @param value 213 * The long to write 214 * @throws IOException 215 * Thrown if there is a problem writing to the OutputStream 216 */ 217 public static void writeLong(OutputStream outputStream, long value) 218 throws IOException { 219 byte[] byteArray = convertToBytes(value); 220 221 outputStream.write(byteArray); 222 223 return; 224 } 225 226 public static byte[] convertToBytes(long n) { 227 byte[] bytes = new byte[8]; 228 229 bytes[7] = (byte) (n); 230 n >>>= 8; 231 bytes[6] = (byte) (n); 232 n >>>= 8; 233 bytes[5] = (byte) (n); 234 n >>>= 8; 235 bytes[4] = (byte) (n); 236 n >>>= 8; 237 bytes[3] = (byte) (n); 238 n >>>= 8; 239 bytes[2] = (byte) (n); 240 n >>>= 8; 241 bytes[1] = (byte) (n); 242 n >>>= 8; 243 bytes[0] = (byte) (n); 244 245 return bytes; 246 } 247 248 /** 249 * Read in a long from an InputStream 250 * 251 * @param inputStream 252 * The InputStream used to read the long 253 * @return A long, which is the next 8 bytes converted from the InputStream 254 * @throws IOException 255 * Thrown if there is a problem reading from the InputStream 256 */ 257 public static long readLong(InputStream inputStream) throws IOException { 258 byte[] byteArray = new byte[8]; 259 260 // Read in the next 8 bytes 261 inputStream.read(byteArray); 262 263 long number = convertLongFromBytes(byteArray); 264 265 return number; 266 } 267 268 public static long convertLongFromBytes(byte[] bytes) { 269 return convertLongFromBytes(bytes, 0); 270 } 271 272 public static long convertLongFromBytes(byte[] bytes, int offset) { 273 // Convert it to an long 274 return ((((long) bytes[offset+7]) & 0xFF) 275 + ((((long) bytes[offset+6]) & 0xFF) << 8) 276 + ((((long) bytes[offset+5]) & 0xFF) << 16) 277 + ((((long) bytes[offset+4]) & 0xFF) << 24) 278 + ((((long) bytes[offset+3]) & 0xFF) << 32) 279 + ((((long) bytes[offset+2]) & 0xFF) << 40) 280 + ((((long) bytes[offset+1]) & 0xFF) << 48) 281 + ((((long) bytes[offset+0]) & 0xFF) << 56)); 282 } 283 284 285 // ********** byte <> double METHODS ********** 286 287 /** 288 * Writes a double out to an OutputStream. 289 * 290 * @param outputStream 291 * The OutputStream the double will be written to 292 * @param value 293 * The double to write 294 * @throws IOException 295 * Thrown if there is a problem writing to the OutputStream 296 */ 297 public static void writeDouble(OutputStream outputStream, double value) 298 throws IOException { 299 byte[] byteArray = convertToBytes(value); 300 301 outputStream.write(byteArray); 302 303 return; 304 } 305 306 public static byte[] convertToBytes(double n) { 307 long bits = Double.doubleToLongBits(n); 308 return convertToBytes(bits); 309 } 310 311 /** 312 * Read in a double from an InputStream 313 * 314 * @param inputStream 315 * The InputStream used to read the double 316 * @return A double, which is the next 8 bytes converted from the InputStream 317 * @throws IOException 318 * Thrown if there is a problem reading from the InputStream 319 */ 320 public static double readDouble(InputStream inputStream) throws IOException { 321 byte[] byteArray = new byte[8]; 322 323 // Read in the next 8 bytes 324 inputStream.read(byteArray); 325 326 double number = convertDoubleFromBytes(byteArray); 327 328 return number; 329 } 330 331 public static double convertDoubleFromBytes(byte[] bytes) { 332 return convertDoubleFromBytes(bytes, 0); 333 } 334 335 public static double convertDoubleFromBytes(byte[] bytes, int offset) { 336 // Convert it to a double 337 long bits = convertLongFromBytes(bytes, offset); 338 return Double.longBitsToDouble(bits); 339 } 340 341 // ********** byte <> float METHODS ********** 342 343 /** 344 * Writes an float out to an OutputStream. 345 * 346 * @param outputStream 347 * The OutputStream the float will be written to 348 * @param fVal 349 * The float to write 350 * @throws IOException 351 * Thrown if there is a problem writing to the OutputStream 352 */ 353 public static void writeFloat(OutputStream outputStream, float fVal) 354 throws IOException { 355 byte[] byteArray = convertToBytes(fVal); 356 357 outputStream.write(byteArray); 358 359 return; 360 } 361 362 public static byte[] convertToBytes(float f) { 363 int temp = Float.floatToIntBits(f); 364 return convertToBytes(temp); 365 } 366 367 /** 368 * Read in a float from an InputStream 369 * 370 * @param inputStream 371 * The InputStream used to read the float 372 * @return A float, which is the next 4 bytes converted from the InputStream 373 * @throws IOException 374 * Thrown if there is a problem reading from the InputStream 375 */ 376 public static float readFloat(InputStream inputStream) throws IOException { 377 byte[] byteArray = new byte[4]; 378 379 // Read in the next 4 bytes 380 inputStream.read(byteArray); 381 382 float number = convertFloatFromBytes(byteArray); 383 384 return number; 385 } 386 387 public static float convertFloatFromBytes(byte[] byteArray) { 388 return convertFloatFromBytes(byteArray, 0); 389 } 390 public static float convertFloatFromBytes(byte[] byteArray, int offset) { 391 // Convert it to an int 392 int number = convertIntFromBytes(byteArray, offset); 393 return Float.intBitsToFloat(number); 394 } 395 396 397 398 // ********** byte <> boolean METHODS ********** 399 400 /** 401 * Writes a boolean out to an OutputStream. 402 * 403 * @param outputStream 404 * The OutputStream the boolean will be written to 405 * @param bVal 406 * The boolean to write 407 * @throws IOException 408 * Thrown if there is a problem writing to the OutputStream 409 */ 410 public static void writeBoolean(OutputStream outputStream, boolean bVal) 411 throws IOException { 412 byte[] byteArray = convertToBytes(bVal); 413 414 outputStream.write(byteArray); 415 416 return; 417 } 418 419 public static byte[] convertToBytes(boolean b) { 420 byte[] rVal = new byte[1]; 421 rVal[0] = b ? (byte)1 : (byte)0; 422 return rVal; 423 } 424 425 /** 426 * Read in a boolean from an InputStream 427 * 428 * @param inputStream 429 * The InputStream used to read the boolean 430 * @return A boolean, which is the next byte converted from the InputStream (iow, byte != 0) 431 * @throws IOException 432 * Thrown if there is a problem reading from the InputStream 433 */ 434 public static boolean readBoolean(InputStream inputStream) throws IOException { 435 byte[] byteArray = new byte[1]; 436 437 // Read in the next byte 438 inputStream.read(byteArray); 439 440 return convertBooleanFromBytes(byteArray); 441 } 442 443 public static boolean convertBooleanFromBytes(byte[] byteArray) { 444 return convertBooleanFromBytes(byteArray, 0); 445 } 446 public static boolean convertBooleanFromBytes(byte[] byteArray, int offset) { 447 return byteArray[offset] != 0; 448 } 449 450 451 /** 452 * Properly reads in data from the given stream until the specified number 453 * of bytes have been read. 454 * 455 * @param store 456 * the byte array to store in. Should have a length > bytes 457 * @param bytes 458 * the number of bytes to read. 459 * @param is 460 * the stream to read from 461 * @return the store array for chaining purposes 462 * @throws IOException 463 * if an error occurs while reading from the stream 464 * @throws ArrayIndexOutOfBoundsException 465 * if bytes greater than the length of the store. 466 */ 467 public static byte[] readData(byte[] store, int bytes, InputStream is) throws IOException { 468 for (int i = 0; i < bytes; i++) { 469 store[i] = (byte)is.read(); 470 } 471 return store; 472 } 473 474 public static byte[] rightAlignBytes(byte[] bytes, int width) { 475 if (bytes.length != width) { 476 byte[] rVal = new byte[width]; 477 for (int x = width - bytes.length; x < width; x++) { 478 rVal[x] = bytes[x - (width - bytes.length)]; 479 } 480 return rVal; 481 } 482 483 return bytes; 484 } 485 486} 487