001 /*
002 * Copyright (c) Andrey Kuznetsov. All Rights Reserved.
003 *
004 * http://uio.imagero.com
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are met:
008 *
009 * o Redistributions of source code must retain the above copyright notice,
010 * this list of conditions and the following disclaimer.
011 *
012 * o Redistributions in binary form must reproduce the above copyright notice,
013 * this list of conditions and the following disclaimer in the documentation
014 * and/or other materials provided with the distribution.
015 *
016 * o Neither the name of Andrey Kuznetsov nor the names of
017 * its contributors may be used to endorse or promote products derived
018 * from this software without specific prior written permission.
019 *
020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
022 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
023 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
027 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
028 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
029 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
030 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031 */
032
033 package com.imagero.uio.io;
034
035 import com.imagero.uio.RandomAccessInput;
036 import com.imagero.uio.Sys;
037 import com.imagero.uio.RandomAccessOutput;
038 import com.imagero.uio.RandomAccessIO;
039
040 import java.io.BufferedReader;
041 import java.io.BufferedWriter;
042 import java.io.DataInput;
043 import java.io.DataOutput;
044 import java.io.File;
045 import java.io.FileInputStream;
046 import java.io.FileOutputStream;
047 import java.io.IOException;
048 import java.io.InputStream;
049 import java.io.OutputStream;
050 import java.io.RandomAccessFile;
051
052 /**
053 * IOutils.java
054 *
055 * @author Andrei Kouznetsov
056 */
057 public class IOutils {
058 private static final int BIG_ENDIAN = 0x4D4D;
059 private static final int LITTLE_ENDIAN = 0x4949;
060
061 /**
062 * close silently stream<br>
063 * no exception it thrown
064 *
065 * @param bw
066 */
067 public static void closeStream(BufferedWriter bw) {
068 try {
069 if (bw != null) {
070 bw.close();
071 }
072 } catch (IOException ex) {
073 }
074 }
075
076 /**
077 * close silently stream<br>
078 * no exception it thrown
079 *
080 * @param br
081 */
082 public static void closeStream(BufferedReader br) {
083 try {
084 if (br != null) {
085 br.close();
086 }
087 } catch (IOException ex) {
088 }
089 }
090
091 /**
092 * close silently stream<br>
093 * no exception it thrown
094 *
095 * @param is
096 */
097 public static void closeStream(InputStream is) {
098 try {
099 if (is != null) {
100 is.close();
101 }
102 } catch (IOException ex) {
103 }
104 }
105
106 /**
107 * close silently stream<br>
108 * no exception it thrown
109 *
110 * @param os
111 */
112 public static void closeStream(OutputStream os) {
113 try {
114 if (os != null) {
115 os.close();
116 }
117 } catch (IOException ex) {
118 }
119 }
120
121 /**
122 * close silently stream<br>
123 * no exception it thrown
124 *
125 * @param raf
126 */
127 public static void closeStream(RandomAccessFile raf) {
128 try {
129 if (raf != null) {
130 raf.close();
131 }
132 } catch (IOException ex) {
133 }
134 }
135
136 /**
137 * close silently stream<br>
138 * no exception it thrown
139 *
140 * @param ro
141 */
142 public static void closeStream(RandomAccessInput ro) {
143 try {
144 if (ro != null) {
145 ro.close();
146 }
147 } catch (IOException ex) {
148 }
149 }
150
151 public static void closeStream(RandomAccessOutput ro) {
152 try {
153 if (ro != null) {
154 ro.close();
155 }
156 } catch (IOException ex) {
157 }
158 }
159
160 public static void closeStream(RandomAccessIO ro) {
161 try {
162 if (ro != null) {
163 ro.close();
164 }
165 } catch (IOException ex) {
166 }
167 }
168
169 static final int[] mask = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
170 static byte b0 = (byte) '0';
171 static byte b1 = (byte) '1';
172
173 public static String toBinaryString(byte value) {
174 byte[] b = new byte[8];
175 int cnt = 0;
176 for (int i = 7; i > -1; i--) {
177 b[cnt++] = (value & mask[i]) == 0 ? b0 : b1;
178 }
179 return new String(b);
180 }
181
182 public static String toBinaryString(char value) {
183 byte[] b = new byte[16];
184 int cnt = 0;
185 for (int i = 15; i > -1; i--) {
186 b[cnt++] = (value & mask[i]) == 0 ? b0 : b1;
187 }
188 return new String(b);
189 }
190
191 public static String toBinaryString(int value, int length) {
192 byte[] b = new byte[length];
193 int cnt = 0;
194 for (int i = length - 1; i > -1; i--) {
195 if (((value >> i) & 1) == 1) {
196 b[cnt++] = b1;
197 } else {
198 b[cnt++] = b0;
199 }
200 }
201 return new String(b);
202 }
203
204 final static byte[] digits = {
205 (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5',
206 (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b',
207 (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f'
208 };
209
210 public static String toHexString(byte value) {
211 return toUnsignedString(value & 0xFF, 4);
212 }
213
214 private static String toUnsignedString(int i, int shift) {
215 byte[] buf = new byte[]{(byte) '0', (byte) '0'};
216 int charPos = 2;
217 int radix = 1 << shift;
218 int mask = radix - 1;
219 do {
220 buf[--charPos] = digits[i & mask];
221 i >>>= shift;
222 } while (i != 0);
223
224 return new String(buf);
225 }
226
227 public static void printHexByte(int value) {
228 printHexImpl(value & 0xFFFF, 2);
229 }
230
231 public static void printlnHexByte(int value) {
232 printHexImpl(value & 0xFFFF, 2);
233 Sys.out.println("");
234 }
235
236 public static void printHexShort(int value) {
237 printHexImpl(value & 0xFFFF, 4);
238 }
239
240 public static void printlnHexShort(int value) {
241 printHexImpl(value & 0xFFFF, 4);
242 Sys.out.println("");
243 }
244
245 public static void printHexInt(int value) {
246 printHexImpl(value & 0xFFFFFFFF, 8);
247 }
248
249 public static void printlnHexInt(int value) {
250 printHexImpl(value & 0xFFFFFFFF, 8);
251 Sys.out.println("");
252 }
253
254 public static void printHexLong(long value) {
255 printHexImpl(value & 0xFFFFFFFFFFFFFFFFL, 16);
256 }
257
258 public static void printlnHexLong(long value) {
259 printHexImpl(value & 0xFFFFFFFFFFFFFFFFL, 16);
260 Sys.out.println("");
261 }
262
263 static void printHexImpl(long value, int length) {
264 String s = Long.toHexString(value);
265 //Sys.out.println("***********************" + s + " " + value);
266 for (int i = 0, size = length - s.length(); i < size; i++) {
267 Sys.out.print("0");
268 }
269 Sys.out.print(s);
270 }
271
272 static void printHexImpl(int value, int length) {
273 String s = Integer.toHexString(value);
274 if (s.length() > length) {
275 s = s.substring(s.length() - length);
276 }
277 //Sys.out.println("***********************" + s + " " + value);
278 for (int i = 0, size = length - s.length(); i < size; i++) {
279 Sys.out.print("0");
280 }
281 Sys.out.print(s);
282 }
283
284 public static String getExtension(File f) {
285 String s = f.getName();
286 return s.substring(s.lastIndexOf(".") + 1).toUpperCase();
287 }
288
289 /**
290 * read little-endian short
291 */
292 public static int readShort4D(InputStream in) throws IOException {
293 return ((in.read() & 0xFF) << 8) + ((in.read() & 0xFF) << 0);
294 }
295
296 /**
297 * read little-endian short
298 */
299 public static int readShort4D(DataInput in) throws IOException {
300 return ((in.readByte() & 0xFF) << 8) + ((in.readByte() & 0xFF) << 0);
301 }
302
303 /**
304 * read big-endian short
305 */
306 public static int readShort49(InputStream in) throws IOException {
307 return ((in.read() & 0xFF) << 0) + ((in.read() & 0xFF) << 8);
308 }
309
310 /**
311 * read big-endian short
312 */
313 public static int readShort49(DataInput in) throws IOException {
314 return ((in.readByte() & 0xFF) << 0) + ((in.readByte() & 0xFF) << 8);
315 }
316
317 /**
318 * read little-endian int
319 */
320 public static int readInt4D(InputStream in) throws IOException {
321 return (((in.read() & 0xFF) << 24) + ((in.read() & 0xFF) << 16) + ((in.read() & 0xFF) << 8) + ((in.read() & 0xFF) << 0));
322 }
323
324 /**
325 * read big-endian int
326 */
327 public static int readInt4D(DataInput in) throws IOException {
328 int b0 = (in.readByte() & 0xFF);
329 int b1 = (in.readByte() & 0xFF);
330 int b2 = (in.readByte() & 0xFF);
331 int b3 = (in.readByte() & 0xFF);
332 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
333 }
334
335 /**
336 * read big-endian int
337 */
338 public static int readInt49(InputStream in) throws IOException {
339 return ((in.read() & 0xFF) << 0) + ((in.read() & 0xFF) << 8) + ((in.read() & 0xFF) << 16) + ((in.read() & 0xFF) << 24);
340 }
341
342 /**
343 * read big-endian int
344 */
345 public static int readInt49(DataInput in) throws IOException {
346 return ((in.readByte() & 0xFF) << 0) + ((in.readByte() & 0xFF) << 8) + ((in.readByte() & 0xFF) << 16) + ((in.readByte() & 0xFF) << 24);
347 }
348
349 /**
350 * read little-endian long
351 */
352 public static long readLong4D(InputStream in) throws IOException {
353 return ((long) (readInt4D(in)) << 32) + (readInt4D(in) & 0xFFFFFFFFL);
354 }
355
356 /**
357 * read little-endian long
358 */
359 public static long readLong4D(DataInput in) throws IOException {
360 return ((long) (readInt4D(in)) << 32) + (readInt4D(in) & 0xFFFFFFFFL);
361 }
362
363 /**
364 * read big-endian long
365 */
366 public static long readLong49(InputStream in) throws IOException {
367 return ((long) (readInt49(in)) & 0xFFFFFFFFL) + (readInt49(in) << 32);
368 }
369
370 /**
371 * read big-endian long
372 */
373 public static long readLong49(DataInput in) throws IOException {
374 return ((long) (readInt49(in)) & 0xFFFFFFFFL) + (readInt49(in) << 32);
375 }
376
377 public static byte readSByte(DataInput ro) throws IOException {
378 byte b = ro.readByte();
379 if (b < 0) {
380 b = (byte) -(~(b + 1));
381 }
382 return b;
383 }
384
385 public static short readSShort(DataInput ro) throws IOException {
386 short b = ro.readShort();
387 if (b < 0) {
388 b = (short) -(~(b + 1));
389 }
390 return b;
391 }
392
393 public static int readSInt(DataInput ro) throws IOException {
394 int b = ro.readInt();
395 if (b < 0) {
396 b = -(~(b + 1));
397 }
398 return b;
399 }
400
401 public static long readSLong(DataInput ro) throws IOException {
402 long b = ro.readLong();
403 if (b < 0) {
404 b = -(~(b + 1));
405 }
406 return b;
407 }
408
409 /**
410 * Read byte array and convert from 2's complement
411 * @param ro RandomAccessRO
412 * @param b0 byte array
413 * @throws IOException
414 */
415 public static void readFullyS(DataInput ro, byte[] b0) throws IOException {
416 ro.readFully(b0);
417 convertFrom2C(b0);
418 }
419
420 /**
421 * Convert byte array from 2's complement
422 */
423 public static final void convertFrom2C(byte[] b0) {
424 for (int i = 0; i < b0.length; i++) {
425 if (b0[i] < 0) {
426 b0[i] = (byte) -(~(b0[i] + 1));
427 }
428 }
429 }
430
431 /**
432 * Read short array and convert from 2's complement.
433 * @param ro RandomAccessRO
434 * @param b0 short array
435 * @throws IOException
436 */
437 public static void readFullyS(RandomAccessInput ro, short[] b0) throws IOException {
438 ro.readFully(b0);
439 convertFrom2C(b0);
440 }
441
442 /**
443 * Convert short array from 2's complement
444 */
445 public static final void convertFrom2C(short[] b0) {
446 for (int i = 0; i < b0.length; i++) {
447 if (b0[i] < 0) {
448 b0[i] = (short) -(~(b0[i] + 1));
449 }
450 }
451 }
452
453 /**
454 * Read int array and convert from 2's complement
455 * @param ro RandomAccessRO
456 * @param b0 int array
457 * @throws IOException
458 */
459 public static void readFullyS(RandomAccessInput ro, int[] b0) throws IOException {
460 ro.readFully(b0);
461 convertFrom2C(b0);
462 }
463
464 /**
465 * Convert int array from 2's complement
466 */
467 public static final void convertFrom2C(int[] b0) {
468 for (int i = 0; i < b0.length; i++) {
469 if (b0[i] < 0) {
470 b0[i] = -(~(b0[i] + 1));
471 }
472 }
473 }
474
475 /**
476 * Read short array and convert from 2's complement
477 * @param ro RandomAccessRO
478 * @param b0 long array
479 * @throws IOException
480 */
481 public static void readFullyS(RandomAccessInput ro, long[] b0) throws IOException {
482 ro.readFully(b0);
483 convertFrom2C(b0);
484 }
485
486 /**
487 * Convert long array from 2's complement
488 */
489 public static final void convertFrom2C(long[] b0) {
490 for (int i = 0; i < b0.length; i++) {
491 if (b0[i] < 0) {
492 b0[i] = -(~(b0[i] + 1));
493 }
494 }
495 }
496
497 public static void readFully(InputStream in, byte b[]) throws UnexpectedEOFException, IOException {
498 readFully(in, b, 0, b.length);
499 }
500
501 public static void readFully(InputStream in, byte b[], int off, int len) throws UnexpectedEOFException, IOException {
502 int n = 0;
503 do {
504 int count = in.read(b, off + n, len - n);
505 if (count < 0) {
506 throw new UnexpectedEOFException(n > 0 ? n : -1);
507 // return;
508 }
509 n += count;
510 } while (n < len);
511 }
512
513 /**
514 * this method is like readFully, but instead of throwing <code>EOFException</code> it returns count of read bytes
515 *
516 * @param in InputStream to read
517 * @param b byte array to fill
518 *
519 * @return number of bytes read into the buffer, or -1 if EOF was reached
520 *
521 * @throws IOException
522 *
523 */
524 public static int readFully2(InputStream in, byte b[]) throws IOException {
525 return readFully2(in, b, 0, b.length);
526 }
527
528 /**
529 * this method is like readFully, but instead of throwing <code>EOFException</code> it returns count of read bytes
530 *
531 * @param in InputStream to read
532 * @param b byte array to fill
533 * @param off start offset in byte array
534 * @param len number of bytes to read
535 *
536 * @return number of bytes read into the buffer, or -1 if EOF was reached
537 *
538 * @throws IOException
539 */
540 public static int readFully2(InputStream in, byte b[], int off, int len) throws IOException {
541 int n = 0;
542 int cnt0 = 0;
543 do {
544 int count = in.read(b, off + n, len - n);
545 if (count == 0) {
546 cnt0++;
547 if (cnt0 >= 3) {
548 break;
549 }
550 } else {
551 cnt0 = 0;
552 }
553 if (count < 0) {
554 return n == 0 ? -1 : n;
555 }
556 n += count;
557 } while (n < len);
558 return n;
559 }
560
561 /**
562 * copy <code>length</code> bytes from <code>in</code> to <code>out</code>
563 * @param length amount of bytes to copy
564 * @param in source InputStream
565 * @param out destination OutputStream
566 * @throws IOException
567 */
568 public static long copy(long length, InputStream in, OutputStream out) throws IOException {
569 long copy = 0;
570 byte[] buffer = new byte[2048];
571 while (length > 0) {
572 int read = in.read(buffer, 0, (int) Math.min(buffer.length, length));
573 if (read <= 0) {
574 break;
575 }
576 copy += read;
577 length -= read;
578 out.write(buffer, 0, read);
579 }
580 return copy;
581 }
582
583 /**
584 * copy <code>length</code> bytes from source to destination stream
585 * @param length amount of bytes to copy
586 * @param in source stream
587 * @param out destination stream
588 * @throws IOException
589 */
590 public static long copy(long length, InputStream in, DataOutput out) throws IOException {
591 long copy = 0;
592 byte[] buffer = new byte[2048];
593 while (length > 0) {
594 int read = in.read(buffer, 0, (int) Math.min(buffer.length, length));
595 if (read <= 0) {
596 break;
597 }
598 copy += read;
599 length -= read;
600 out.write(buffer, 0, read);
601 }
602 return copy;
603 }
604
605 /**
606 * Copy file.
607 * @param src source file
608 * @param dest destination file
609 * @return how much bytes were copied.
610 * @throws IOException
611 */
612 public static long copy(File src, File dest) throws IOException {
613 InputStream in = new FileInputStream(src);
614 OutputStream out = new FileOutputStream(dest);
615 try {
616 return copy(in, out);
617 } finally {
618 IOutils.closeStream(in);
619 IOutils.closeStream(out);
620 }
621 }
622
623 /**
624 * copy data from <code>in</code> to <code>out</code>
625 * @param in source InputStream
626 * @param out destination OutputStream
627 * @return how much bytes were copied.
628 * @throws IOException
629 */
630 public static long copy(InputStream in, OutputStream out) throws IOException {
631 long copy = 0;
632 byte[] buffer = new byte[2048];
633 while (true) {
634 int read = in.read(buffer);
635 if (read <= 0) {
636 break;
637 }
638 copy += read;
639 out.write(buffer, 0, read);
640 }
641 return copy;
642 }
643
644 /**
645 * copy data from source to destination stream
646 * @param in source stream
647 * @param out destination stream
648 * @throws IOException
649 * @return amount of copied bytes
650 */
651 public static long copy(InputStream in, DataOutput out) throws IOException {
652 long copy = 0;
653 byte[] buffer = new byte[2048];
654 while (true) {
655 int read = in.read(buffer);
656 if (read <= 0) {
657 break;
658 }
659 copy += read;
660 out.write(buffer, 0, read);
661 }
662 return copy;
663 }
664
665 /**
666 * copy data from <code>in</code> to <code>out</code>
667 * @param in source RandomAccessRO
668 * @param offset offset in <code>in</code>
669 * @param out destination OutputStream
670 * @throws IOException
671 */
672 public static long copy(RandomAccessInput in, long offset, OutputStream out) throws IOException {
673 long copy = 0;
674 byte[] buffer = new byte[2048];
675 in.seek(offset);
676 while (true) {
677 int read = in.read(buffer);
678 if (read <= 0) {
679 break;
680 }
681 copy += read;
682 out.write(buffer, 0, read);
683 }
684 return copy;
685 }
686
687 /**
688 * copy data from source to destination stream
689 * @param in source stream
690 * @param offset offset in source stream
691 * @param out destination stream
692 * @throws IOException
693 * @return how much bytes was copied
694 */
695 public static long copy(RandomAccessInput in, long offset, DataOutput out) throws IOException {
696 long copy = 0;
697 byte[] buffer = new byte[2048];
698 in.seek(offset);
699 while (true) {
700 int read = in.read(buffer);
701 if (read <= 0) {
702 break;
703 }
704 copy += read;
705 out.write(buffer, 0, read);
706 }
707 return copy;
708 }
709
710 /**
711 * copy data from source to destination stream
712 * @param offset offset in source stream
713 * @param length amount of bytes to copy
714 * @param in source stream
715 * @param out destination stream
716 * @throws IOException
717 */
718 public static long copy(long offset, long length, RandomAccessInput in, OutputStream out) throws IOException {
719 long copy = 0;
720 byte[] buffer = new byte[2048];
721 in.seek(offset);
722 while (length > 0) {
723 int read = in.read(buffer, 0, (int) Math.min(buffer.length, length));
724 if (read <= 0) {
725 break;
726 }
727 copy += read;
728 length -= read;
729 out.write(buffer, 0, read);
730 }
731 return copy;
732 }
733
734 /**
735 * copy data from source to destination stream
736 * @param offset offset in source stream
737 * @param length amount of bytes to copy
738 * @param in source stream
739 * @param out destination stream
740 * @throws IOException
741 */
742 public static long copy(long offset, long length, RandomAccessInput in, DataOutput out) throws IOException {
743 long copy = 0;
744 byte[] buffer = new byte[2048];
745 in.seek(offset);
746 while (length > 0) {
747 int read = in.read(buffer, 0, (int) Math.min(buffer.length, length));
748 if (read <= 0) {
749 break;
750 }
751 copy += read;
752 length -= read;
753 out.write(buffer, 0, read);
754 }
755 return copy;
756 }
757
758 /**
759 * read big/little-endian short
760 */
761 public static int readShort(InputStream in, int byteOrder) throws IOException {
762 switch (byteOrder) {
763 case BIG_ENDIAN:
764 return readShort4D(in);
765 case LITTLE_ENDIAN:
766 return readShort49(in);
767 default:
768 throw new IllegalArgumentException("" + byteOrder);
769 }
770 }
771
772 public static int readShort(DataInput in, int byteOrder) throws IOException {
773 switch (byteOrder) {
774 case BIG_ENDIAN:
775 return readShort4D(in);
776 case LITTLE_ENDIAN:
777 return readShort49(in);
778 default:
779 throw new IllegalArgumentException("" + byteOrder);
780 }
781 }
782
783 /**
784 * read big/little-endian int
785 */
786 public static int readInt(InputStream in, int byteOrder) throws IOException {
787 switch (byteOrder) {
788 case BIG_ENDIAN:
789 return readInt4D(in);
790 case LITTLE_ENDIAN:
791 return readInt49(in);
792 default:
793 throw new IllegalArgumentException("" + byteOrder);
794 }
795 }
796
797 /**
798 * read big/little-endian int
799 */
800 public static int readInt(DataInput in, int byteOrder) throws IOException {
801 switch (byteOrder) {
802 case BIG_ENDIAN:
803 return readInt4D(in);
804 case LITTLE_ENDIAN:
805 return readInt49(in);
806 default:
807 throw new IllegalArgumentException("" + byteOrder);
808 }
809 }
810
811
812 }