You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@harmony.apache.org by "Vladimir Strigun (JIRA)" <ji...@apache.org> on 2006/03/03 17:00:41 UTC

[jira] Created: (HARMONY-166) method read() in InputStreamReader failed to read one character

method read() in InputStreamReader failed to read one character
---------------------------------------------------------------

         Key: HARMONY-166
         URL: http://issues.apache.org/jira/browse/HARMONY-166
     Project: Harmony
        Type: Bug
  Components: Classlib  
    Reporter: Vladimir Strigun


I've started to play with harmony-57 contribution and found bug in InputStreamReader class. Method read() should read a single character from input stream but it works incorrectly for 2 bytes-per-char charsets. Example below shows that it failed to read one character in UTF-16 charset. Sorry for so ugly test, it's just a part of InputStreamReaderTest from Harmony-57 contribution. 

import java.io.*;
import junit.framework.TestCase;

public class InputStreamReaderTest extends TestCase {

	public static void main(String[] args) {
		junit.textui.TestRunner.run(InputStreamReaderTest.class);
	}

	public void test_ISR_read() throws Exception {
		InputStream in;
		InputStreamReader reader;

		try {
			in = new LimitedByteArrayInputStream(0);
			reader = new InputStreamReader(in, "UTF-16BE");
			int xx = reader.read();
			assertTrue("Incorrect byte UTF-16BE", xx == '\u6172');
		} catch (UnsupportedEncodingException e) {
			// Can't test without the converter
			System.out.println(e);
		} catch (IOException e) {
			e.printStackTrace();
			fail("UTF-16BE unexpected 1: " + e);

		}
		try {
			in = new LimitedByteArrayInputStream(0);
			reader = new InputStreamReader(in, "UTF-16LE");
			int xx = reader.read();
			assertTrue("Incorrect byte UTF-16BE", xx == '\u7261');
		} catch (UnsupportedEncodingException e) {
			// Can't test without the converter
		} catch (IOException e) {
			fail("UTF-16BE unexpected 2: " + e);
		}
		try {
			in = new LimitedByteArrayInputStream(1);
			reader = new InputStreamReader(in, "UTF-16");
			assertTrue("Incorrect byte UTF-16BE", reader.read() == '\u7261');
		} catch (UnsupportedEncodingException e) {
			// Can't test without the converter
		} catch (IOException e) {
			fail("UTF-16BE unexpected 3: " + e);
		}

		try {
			in = new LimitedByteArrayInputStream(2);
			reader = new InputStreamReader(in, "ISO2022JP");
			int ch = reader.read();
			assertTrue("Incorrect byte ISO2022JP 1: " + ch, ch == '\u4e5d');
			ch = reader.read();
			assertTrue("Incorrect byte ISO2022JP 2: " + ch, ch == '\u7b2c');
		} catch (UnsupportedEncodingException e) {
			// Can't test without the converter
			System.out.println(e);
		} catch (IOException e) {
			fail("ISO2022JP unexpected: " + e);
		}
	}

	static class LimitedByteArrayInputStream extends ByteArrayInputStream {
		// A ByteArrayInputStream that only returns a single byte per read
		byte[] bytes;

		int count;

		public LimitedByteArrayInputStream(int type) {
			super(new byte[0]);
			switch (type) {
			case 0:
				bytes = new byte[] { 0x61, 0x72 };
				break;
			case 1:
				bytes = new byte[] { (byte) 0xff, (byte) 0xfe, 0x61, 0x72 };
				break;
			case 2:
				bytes = new byte[] { '\u001b', '$', 'B', '6', 'e', 'B', 'h',
						'\u001b', '(', 'B' };
				break;
			}
			count = bytes.length;
		}

		public int read() {
			if (count == 0)
				return -1;
			count--;
			return bytes[bytes.length - count];
		}

		public int read(byte[] buffer, int offset, int length) {
			if (count == 0)
				return -1;
			if (length == 0)
				return 0;
			buffer[offset] = bytes[bytes.length - count];
			count--;
			return 1;
		}

		public int available() {
			return count;
		}
	}
}


-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


[jira] Updated: (HARMONY-166) method read() in InputStreamReader failed to read one character

Posted by "Vladimir Strigun (JIRA)" <ji...@apache.org>.
     [ http://issues.apache.org/jira/browse/HARMONY-166?page=all ]

Vladimir Strigun updated HARMONY-166:
-------------------------------------

    Attachment: InputStreamReader.patch.txt

Please try my patch.

> method read() in InputStreamReader failed to read one character
> ---------------------------------------------------------------
>
>          Key: HARMONY-166
>          URL: http://issues.apache.org/jira/browse/HARMONY-166
>      Project: Harmony
>         Type: Bug
>   Components: Classlib
>     Reporter: Vladimir Strigun
>  Attachments: InputStreamReader.patch.txt
>
> I've started to play with harmony-57 contribution and found bug in InputStreamReader class. Method read() should read a single character from input stream but it works incorrectly for 2 bytes-per-char charsets. Example below shows that it failed to read one character in UTF-16 charset. Sorry for so ugly test, it's just a part of InputStreamReaderTest from Harmony-57 contribution. 
> import java.io.*;
> import junit.framework.TestCase;
> public class InputStreamReaderTest extends TestCase {
> 	public static void main(String[] args) {
> 		junit.textui.TestRunner.run(InputStreamReaderTest.class);
> 	}
> 	public void test_ISR_read() throws Exception {
> 		InputStream in;
> 		InputStreamReader reader;
> 		try {
> 			in = new LimitedByteArrayInputStream(0);
> 			reader = new InputStreamReader(in, "UTF-16BE");
> 			int xx = reader.read();
> 			assertTrue("Incorrect byte UTF-16BE", xx == '\u6172');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 			System.out.println(e);
> 		} catch (IOException e) {
> 			e.printStackTrace();
> 			fail("UTF-16BE unexpected 1: " + e);
> 		}
> 		try {
> 			in = new LimitedByteArrayInputStream(0);
> 			reader = new InputStreamReader(in, "UTF-16LE");
> 			int xx = reader.read();
> 			assertTrue("Incorrect byte UTF-16BE", xx == '\u7261');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 		} catch (IOException e) {
> 			fail("UTF-16BE unexpected 2: " + e);
> 		}
> 		try {
> 			in = new LimitedByteArrayInputStream(1);
> 			reader = new InputStreamReader(in, "UTF-16");
> 			assertTrue("Incorrect byte UTF-16BE", reader.read() == '\u7261');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 		} catch (IOException e) {
> 			fail("UTF-16BE unexpected 3: " + e);
> 		}
> 		try {
> 			in = new LimitedByteArrayInputStream(2);
> 			reader = new InputStreamReader(in, "ISO2022JP");
> 			int ch = reader.read();
> 			assertTrue("Incorrect byte ISO2022JP 1: " + ch, ch == '\u4e5d');
> 			ch = reader.read();
> 			assertTrue("Incorrect byte ISO2022JP 2: " + ch, ch == '\u7b2c');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 			System.out.println(e);
> 		} catch (IOException e) {
> 			fail("ISO2022JP unexpected: " + e);
> 		}
> 	}
> 	static class LimitedByteArrayInputStream extends ByteArrayInputStream {
> 		// A ByteArrayInputStream that only returns a single byte per read
> 		byte[] bytes;
> 		int count;
> 		public LimitedByteArrayInputStream(int type) {
> 			super(new byte[0]);
> 			switch (type) {
> 			case 0:
> 				bytes = new byte[] { 0x61, 0x72 };
> 				break;
> 			case 1:
> 				bytes = new byte[] { (byte) 0xff, (byte) 0xfe, 0x61, 0x72 };
> 				break;
> 			case 2:
> 				bytes = new byte[] { '\u001b', '$', 'B', '6', 'e', 'B', 'h',
> 						'\u001b', '(', 'B' };
> 				break;
> 			}
> 			count = bytes.length;
> 		}
> 		public int read() {
> 			if (count == 0)
> 				return -1;
> 			count--;
> 			return bytes[bytes.length - count];
> 		}
> 		public int read(byte[] buffer, int offset, int length) {
> 			if (count == 0)
> 				return -1;
> 			if (length == 0)
> 				return 0;
> 			buffer[offset] = bytes[bytes.length - count];
> 			count--;
> 			return 1;
> 		}
> 		public int available() {
> 			return count;
> 		}
> 	}
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


[jira] Updated: (HARMONY-166) method read() in InputStreamReader failed to read one character

Posted by "Vladimir Strigun (JIRA)" <ji...@apache.org>.
     [ http://issues.apache.org/jira/browse/HARMONY-166?page=all ]

Vladimir Strigun updated HARMONY-166:
-------------------------------------

    Attachment: InputStreamReaderTest.java

test for this issue. it's the same as in description, but it's more comfortable to read.

> method read() in InputStreamReader failed to read one character
> ---------------------------------------------------------------
>
>          Key: HARMONY-166
>          URL: http://issues.apache.org/jira/browse/HARMONY-166
>      Project: Harmony
>         Type: Bug
>   Components: Classlib
>     Reporter: Vladimir Strigun
>  Attachments: InputStreamReader.patch.txt, InputStreamReaderTest.java
>
> I've started to play with harmony-57 contribution and found bug in InputStreamReader class. Method read() should read a single character from input stream but it works incorrectly for 2 bytes-per-char charsets. Example below shows that it failed to read one character in UTF-16 charset. Sorry for so ugly test, it's just a part of InputStreamReaderTest from Harmony-57 contribution. 
> import java.io.*;
> import junit.framework.TestCase;
> public class InputStreamReaderTest extends TestCase {
> 	public static void main(String[] args) {
> 		junit.textui.TestRunner.run(InputStreamReaderTest.class);
> 	}
> 	public void test_ISR_read() throws Exception {
> 		InputStream in;
> 		InputStreamReader reader;
> 		try {
> 			in = new LimitedByteArrayInputStream(0);
> 			reader = new InputStreamReader(in, "UTF-16BE");
> 			int xx = reader.read();
> 			assertTrue("Incorrect byte UTF-16BE", xx == '\u6172');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 			System.out.println(e);
> 		} catch (IOException e) {
> 			e.printStackTrace();
> 			fail("UTF-16BE unexpected 1: " + e);
> 		}
> 		try {
> 			in = new LimitedByteArrayInputStream(0);
> 			reader = new InputStreamReader(in, "UTF-16LE");
> 			int xx = reader.read();
> 			assertTrue("Incorrect byte UTF-16BE", xx == '\u7261');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 		} catch (IOException e) {
> 			fail("UTF-16BE unexpected 2: " + e);
> 		}
> 		try {
> 			in = new LimitedByteArrayInputStream(1);
> 			reader = new InputStreamReader(in, "UTF-16");
> 			assertTrue("Incorrect byte UTF-16BE", reader.read() == '\u7261');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 		} catch (IOException e) {
> 			fail("UTF-16BE unexpected 3: " + e);
> 		}
> 		try {
> 			in = new LimitedByteArrayInputStream(2);
> 			reader = new InputStreamReader(in, "ISO2022JP");
> 			int ch = reader.read();
> 			assertTrue("Incorrect byte ISO2022JP 1: " + ch, ch == '\u4e5d');
> 			ch = reader.read();
> 			assertTrue("Incorrect byte ISO2022JP 2: " + ch, ch == '\u7b2c');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 			System.out.println(e);
> 		} catch (IOException e) {
> 			fail("ISO2022JP unexpected: " + e);
> 		}
> 	}
> 	static class LimitedByteArrayInputStream extends ByteArrayInputStream {
> 		// A ByteArrayInputStream that only returns a single byte per read
> 		byte[] bytes;
> 		int count;
> 		public LimitedByteArrayInputStream(int type) {
> 			super(new byte[0]);
> 			switch (type) {
> 			case 0:
> 				bytes = new byte[] { 0x61, 0x72 };
> 				break;
> 			case 1:
> 				bytes = new byte[] { (byte) 0xff, (byte) 0xfe, 0x61, 0x72 };
> 				break;
> 			case 2:
> 				bytes = new byte[] { '\u001b', '$', 'B', '6', 'e', 'B', 'h',
> 						'\u001b', '(', 'B' };
> 				break;
> 			}
> 			count = bytes.length;
> 		}
> 		public int read() {
> 			if (count == 0)
> 				return -1;
> 			count--;
> 			return bytes[bytes.length - count];
> 		}
> 		public int read(byte[] buffer, int offset, int length) {
> 			if (count == 0)
> 				return -1;
> 			if (length == 0)
> 				return 0;
> 			buffer[offset] = bytes[bytes.length - count];
> 			count--;
> 			return 1;
> 		}
> 		public int available() {
> 			return count;
> 		}
> 	}
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


[jira] Commented: (HARMONY-166) method read() in InputStreamReader failed to read one character

Posted by "Vladimir Strigun (JIRA)" <ji...@apache.org>.
    [ http://issues.apache.org/jira/browse/HARMONY-166?page=comments#action_12368729 ] 

Vladimir Strigun commented on HARMONY-166:
------------------------------------------

The cause of problem is the following: if decode operation returns underflow, and the input have available bytes we should read next byte and call decode operation again. I'll attach fix for the issue soon.

> method read() in InputStreamReader failed to read one character
> ---------------------------------------------------------------
>
>          Key: HARMONY-166
>          URL: http://issues.apache.org/jira/browse/HARMONY-166
>      Project: Harmony
>         Type: Bug
>   Components: Classlib
>     Reporter: Vladimir Strigun

>
> I've started to play with harmony-57 contribution and found bug in InputStreamReader class. Method read() should read a single character from input stream but it works incorrectly for 2 bytes-per-char charsets. Example below shows that it failed to read one character in UTF-16 charset. Sorry for so ugly test, it's just a part of InputStreamReaderTest from Harmony-57 contribution. 
> import java.io.*;
> import junit.framework.TestCase;
> public class InputStreamReaderTest extends TestCase {
> 	public static void main(String[] args) {
> 		junit.textui.TestRunner.run(InputStreamReaderTest.class);
> 	}
> 	public void test_ISR_read() throws Exception {
> 		InputStream in;
> 		InputStreamReader reader;
> 		try {
> 			in = new LimitedByteArrayInputStream(0);
> 			reader = new InputStreamReader(in, "UTF-16BE");
> 			int xx = reader.read();
> 			assertTrue("Incorrect byte UTF-16BE", xx == '\u6172');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 			System.out.println(e);
> 		} catch (IOException e) {
> 			e.printStackTrace();
> 			fail("UTF-16BE unexpected 1: " + e);
> 		}
> 		try {
> 			in = new LimitedByteArrayInputStream(0);
> 			reader = new InputStreamReader(in, "UTF-16LE");
> 			int xx = reader.read();
> 			assertTrue("Incorrect byte UTF-16BE", xx == '\u7261');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 		} catch (IOException e) {
> 			fail("UTF-16BE unexpected 2: " + e);
> 		}
> 		try {
> 			in = new LimitedByteArrayInputStream(1);
> 			reader = new InputStreamReader(in, "UTF-16");
> 			assertTrue("Incorrect byte UTF-16BE", reader.read() == '\u7261');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 		} catch (IOException e) {
> 			fail("UTF-16BE unexpected 3: " + e);
> 		}
> 		try {
> 			in = new LimitedByteArrayInputStream(2);
> 			reader = new InputStreamReader(in, "ISO2022JP");
> 			int ch = reader.read();
> 			assertTrue("Incorrect byte ISO2022JP 1: " + ch, ch == '\u4e5d');
> 			ch = reader.read();
> 			assertTrue("Incorrect byte ISO2022JP 2: " + ch, ch == '\u7b2c');
> 		} catch (UnsupportedEncodingException e) {
> 			// Can't test without the converter
> 			System.out.println(e);
> 		} catch (IOException e) {
> 			fail("ISO2022JP unexpected: " + e);
> 		}
> 	}
> 	static class LimitedByteArrayInputStream extends ByteArrayInputStream {
> 		// A ByteArrayInputStream that only returns a single byte per read
> 		byte[] bytes;
> 		int count;
> 		public LimitedByteArrayInputStream(int type) {
> 			super(new byte[0]);
> 			switch (type) {
> 			case 0:
> 				bytes = new byte[] { 0x61, 0x72 };
> 				break;
> 			case 1:
> 				bytes = new byte[] { (byte) 0xff, (byte) 0xfe, 0x61, 0x72 };
> 				break;
> 			case 2:
> 				bytes = new byte[] { '\u001b', '$', 'B', '6', 'e', 'B', 'h',
> 						'\u001b', '(', 'B' };
> 				break;
> 			}
> 			count = bytes.length;
> 		}
> 		public int read() {
> 			if (count == 0)
> 				return -1;
> 			count--;
> 			return bytes[bytes.length - count];
> 		}
> 		public int read(byte[] buffer, int offset, int length) {
> 			if (count == 0)
> 				return -1;
> 			if (length == 0)
> 				return 0;
> 			buffer[offset] = bytes[bytes.length - count];
> 			count--;
> 			return 1;
> 		}
> 		public int available() {
> 			return count;
> 		}
> 	}
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira