Index: main/classes/core/src/com/ibm/icu/impl/ICUBinary.java |
=================================================================== |
--- main/classes/core/src/com/ibm/icu/impl/ICUBinary.java (revision 36665) |
+++ main/classes/core/src/com/ibm/icu/impl/ICUBinary.java (working copy) |
@@ -519,32 +519,52 @@ |
*/ |
public static ByteBuffer getByteBufferFromInputStream(InputStream is) throws IOException { |
try { |
+ // is.available() may return 0, or 1, or the total number of bytes in the stream, |
+ // or some other number. |
+ // Do not try to use is.available() == 0 to find the end of the stream! |
+ byte[] bytes; |
int avail = is.available(); |
- byte[] bytes = new byte[avail]; |
- readFully(is, bytes, 0, avail); |
- while((avail = is.available()) != 0) { |
- // TODO Java 6 replace new byte[] and arraycopy(): byte[] newBytes = Arrays.copyOf(bytes, bytes.length + avail); |
- byte[] newBytes = new byte[bytes.length + avail]; |
- System.arraycopy(bytes, 0, newBytes, 0, bytes.length); |
- readFully(is, newBytes, bytes.length, avail); |
- bytes = newBytes; |
+ if (avail > 32) { |
+ // There are more bytes available than just the ICU data header length. |
+ // With luck, it is the total number of bytes. |
+ bytes = new byte[avail]; |
+ } else { |
+ bytes = new byte[128]; // empty .res files are even smaller |
} |
- return ByteBuffer.wrap(bytes); |
+ // Call is.read(...) until one returns a negative value. |
+ int length = 0; |
+ for(;;) { |
+ if (length < bytes.length) { |
+ int numRead = is.read(bytes, length, bytes.length - length); |
+ if (numRead < 0) { |
+ break; // end of stream |
+ } |
+ length += numRead; |
+ } else { |
+ // See if we are at the end of the stream before we grow the array. |
+ int nextByte = is.read(); |
+ if (nextByte < 0) { |
+ break; |
+ } |
+ int capacity = 2 * bytes.length; |
+ if (capacity < 128) { |
+ capacity = 128; |
+ } else if (capacity < 0x4000) { |
+ capacity *= 2; // Grow faster until we reach 16kB. |
+ } |
+ // TODO Java 6 replace new byte[] and arraycopy(): bytes = Arrays.copyOf(bytes, capacity); |
+ byte[] newBytes = new byte[capacity]; |
+ System.arraycopy(bytes, 0, newBytes, 0, length); |
+ bytes = newBytes; |
+ bytes[length++] = (byte) nextByte; |
+ } |
+ } |
+ return ByteBuffer.wrap(bytes, 0, length); |
} finally { |
is.close(); |
} |
} |
- private static void readFully(InputStream is, byte[] bytes, int offset, int avail) |
- throws IOException { |
- while (avail > 0) { |
- int numRead = is.read(bytes, offset, avail); |
- assert numRead > 0; |
- offset += numRead; |
- avail -= numRead; |
- } |
- } |
- |
/** |
* Returns a VersionInfo for the bytes in the compact version integer. |
*/ |