mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-20 20:19:32 +00:00
ICU-11341 better ICUBinary.getByteBufferFromInputStream(): minimize number of memory allocations, allocate available() bytes on good JDK, do not rely on available() for finding the end of the stream
X-SVN-Rev: 36681
This commit is contained in:
parent
d302fddd6b
commit
299f24790f
1 changed files with 39 additions and 19 deletions
|
@ -519,32 +519,52 @@ public final class ICUBinary {
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue