### Eclipse Workspace Patch 1.0 #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 29 Jun 2006 21:33:46 -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" #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 29 Jun 2006 21:33:48 -0000 @@ -180,8 +180,7 @@ */ /** * 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,74 +196,55 @@ 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 - - // 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 { + // length is a good guess when the encoding produces less or the same amount of characters than the file length 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); - } - // 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; - } + do { + int amountRead = reader.read(contents, totalRead, length - totalRead); + if (amountRead < 0) + break; + totalRead += amountRead; + } while (totalRead != length); + } + + // read remaining characters + while (true) { + // avoid creating a char[] if there is no more char to read + int current = reader.read(); + if (current < 0) + break; + + int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K + + // resize contents if needed + if (totalRead + 1 + amountRequested > contents.length) + System.arraycopy(contents, 0, contents = new char[totalRead + 1 + amountRequested], 0, totalRead); + contents[totalRead++] = (char) current; + + // 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; }