### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/util/Util.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java,v retrieving revision 1.55 diff -u -r1.55 Util.java --- compiler/org/eclipse/jdt/internal/compiler/util/Util.java 29 Mar 2006 02:50:01 -0000 1.55 +++ compiler/org/eclipse/jdt/internal/compiler/util/Util.java 4 Jul 2006 12:23:43 -0000 @@ -155,33 +155,10 @@ return contents; } - /* - * NIO support to get input stream as char array. - * Not used as with JDK 1.4.2 this support is slower than standard IO one... - * Keep it as comment for future in case of next JDK versions improve performance - * in this area... - public static char[] getInputStreamAsCharArray(FileInputStream stream, int length, String encoding) - throws IOException { - - FileChannel channel = stream.getChannel(); - int size = (int)channel.size(); - if (length >= 0 && length < size) size = length; - Charset charset = encoding==null?systemCharset:Charset.forName(encoding); - if (charset != null) { - MappedByteBuffer bbuffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, size); - CharsetDecoder decoder = charset.newDecoder(); - CharBuffer buffer = decoder.decode(bbuffer); - char[] contents = new char[buffer.limit()]; - buffer.get(contents); - return contents; - } - throw new UnsupportedCharsetException(SYSTEM_FILE_ENCODING); - } - */ + /** * Returns the given input stream's contents as a character array. - * If a length is specified (ie. if length != -1), only length chars - * are returned. Otherwise all chars in the stream are returned. + * If a length is specified (ie. if length != -1), this represents the number of bytes in the stream. * Note this doesn't close the stream. * @throws IOException if a problem occured reading the stream. */ @@ -197,73 +174,51 @@ reader = new InputStreamReader(stream); } char[] contents; + int totalRead = 0; if (length == -1) { contents = CharOperation.NO_CHAR; - int contentsLength = 0; - int amountRead = -1; - do { - int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K + } else { + // length is a good guess when the encoding produces less or the same amount of characters than the file length + contents = new char[length]; // best guess + } + while (true) { + int amountRequested; + if (totalRead < length) { + // until known length is met, reuse same array sized eagerly + amountRequested = length - totalRead; + } else { + // reading beyond known length + int current = reader.read(); + if (current < 0) break; + + amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K + // resize contents if needed - if (contentsLength + amountRequested > contents.length) { - System.arraycopy( - contents, - 0, - contents = new char[contentsLength + amountRequested], - 0, - contentsLength); - } - - // read as many chars as possible - amountRead = reader.read(contents, contentsLength, amountRequested); - - if (amountRead > 0) { - // remember length of contents - contentsLength += amountRead; - } - } while (amountRead != -1); - - // Do not keep first character for UTF-8 BOM encoding - int start = 0; - if (contentsLength > 0 && UTF_8.equals(encoding)) { - if (contents[0] == 0xFEFF) { // if BOM char then skip - contentsLength--; - start = 1; - } - } - // resize contents if necessary - if (contentsLength < contents.length) { - System.arraycopy( - contents, - start, - contents = new char[contentsLength], - 0, - contentsLength); - } - } else { - contents = new char[length]; - int len = 0; - int readSize = 0; - while ((readSize != -1) && (len != length)) { - // See PR 1FMS89U - // We record first the read size. In this case len is the actual read size. - len += readSize; - readSize = reader.read(contents, len, length - len); + if (totalRead + 1 + amountRequested > contents.length) + System.arraycopy(contents, 0, contents = new char[totalRead + 1 + amountRequested], 0, totalRead); + + // add current character + contents[totalRead++] = (char) current; // coming from totalRead==length } - // Do not keep first character for UTF-8 BOM encoding - int start = 0; - if (length > 0 && UTF_8.equals(encoding)) { - if (contents[0] == 0xFEFF) { // if BOM char then skip - len--; - start = 1; - } + // read as many chars as possible + int amountRead = reader.read(contents, totalRead, amountRequested); + if (amountRead < 0) break; + totalRead += amountRead; + } + + // Do not keep first character for UTF-8 BOM encoding + int start = 0; + if (totalRead > 0 && UTF_8.equals(encoding)) { + if (contents[0] == 0xFEFF) { // if BOM char then skip + totalRead--; + start = 1; } - // See PR 1FMS89U - // Now we need to resize in case the default encoding used more than one byte for each - // character - if (len != length) - System.arraycopy(contents, start, (contents = new char[len]), 0, len); } + + // resize contents if necessary + if (totalRead < contents.length) + System.arraycopy(contents, start, contents = new char[totalRead], 0, totalRead); return contents; } #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/EncodingTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/EncodingTests.java,v retrieving revision 1.42 diff -u -r1.42 EncodingTests.java --- src/org/eclipse/jdt/core/tests/model/EncodingTests.java 29 Mar 2006 04:03:07 -0000 1.42 +++ src/org/eclipse/jdt/core/tests/model/EncodingTests.java 4 Jul 2006 12:23:53 -0000 @@ -12,6 +12,7 @@ import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; import junit.framework.Test; @@ -672,6 +673,50 @@ } } + /* + * Ensures that an encoding that a file using an encoding producing more charaters than the file size can + * be correctly read. + * (regression test for bug 149028 Limiting number of characters to read with the file size is invalid.) + */ + public void test034() throws CoreException, IOException { + try { + // Create file + IFile file = createFile("/Encoding/Test34.txt", "acegikm"); + + // Read file using a transformation where a character is read and the next alphabetical character is + // automaticaly added + final InputStream fileStream = file.getContents(); + try { + InputStream in = new InputStream() { + int current = -1; + public int read() throws IOException { + int result; + if (current != -1) { + result = current; + current = -1; + } else { + result = fileStream.read(); + if (result == -1) + return -1; + current = result + 1; + } + return result; + } + }; + char[] result = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(in, (int) file.getLocation().toFile().length(), "UTF-8"); + assertSourceEquals( + "Unexpected source", + "abcdefghijklmn", + new String(result) + ); + } finally { + fileStream.close(); + } + } finally { + deleteFile("Encoding/Test34.txt"); + } + } + /** * Bug 66898: refactor-rename: encoding is not preserved * @see "http://bugs.eclipse.org/bugs/show_bug.cgi?id=66898"