/** * Obtains streams from the Clob and makes sure we can always read the last char in the Clob. * * <p>See DERBY-4060. * * @param id id of the Clob to use * @param length the length of the Clob * @param alphabet the alphabet used to create the content * @throws IOException if reading from a stream fails * @throws SQLException if something goes wrong */ private void getCharacterStreamLongLastChar(int id, int length, CharAlphabet alphabet) throws IOException, SQLException { // Get last char from the source stream. Reader cmpReader = new LoopingAlphabetReader(length, alphabet); cmpReader.skip(length - 1); char srcLastChar = (char) cmpReader.read(); assertTrue(cmpReader.read() == -1); PreparedStatement ps = prepareStatement("select CLOBDATA from BLOBCLOB where ID=?"); ps.setInt(1, id); // Read everything first. int charsToRead = length; ResultSet rs = ps.executeQuery(); rs.next(); Reader reader = rs.getClob(1).getCharacterStream(length - charsToRead + 1, charsToRead); // Drain the stream, and make sure we are able to read the last char. char lastCharRead = getLastCharInStream(reader, charsToRead); assertEquals(srcLastChar, lastCharRead); reader.close(); rs.close(); // Read a portion of the stream. charsToRead = length / 4; rs = ps.executeQuery(); rs.next(); reader = rs.getClob(1).getCharacterStream(length - charsToRead + 1, charsToRead); lastCharRead = getLastCharInStream(reader, charsToRead); assertEquals(srcLastChar, lastCharRead); reader.close(); rs.close(); // Read a very small portion of the stream. charsToRead = 1; rs = ps.executeQuery(); rs.next(); reader = rs.getClob(1).getCharacterStream(length - charsToRead + 1, charsToRead); lastCharRead = getLastCharInStream(reader, charsToRead); assertEquals(srcLastChar, lastCharRead); reader.close(); rs.close(); }
public void testReader() throws Exception { Encoding encoding = Encoding.getDatabaseEncoding("SQL_ASCII"); InputStream stream = new ByteArrayInputStream(new byte[] {97, 98}); Reader reader = encoding.getDecodingReader(stream); assertEquals(97, reader.read()); assertEquals(98, reader.read()); assertEquals(-1, reader.read()); }
/** * Drains the stream and returns the last char read from the stream. * * @param reader stream to drain * @param expectedCount expected number of chars (remaining) in the stream * @return The last char read. * @throws AssertionError if there are too many/few chars in the stream * @throws IOException if reading from the stream fails */ public static char getLastCharInStream(Reader reader, int expectedCount) throws IOException { int read = 0; final char[] buf = new char[256]; assertTrue(buf.length > 0); // Do not allow an infinite loop here. while (true) { int readThisTime = reader.read(buf, 0, buf.length); // -1 is expected, but catch all cases with a negative return value. if (readThisTime < 0) { assertEquals("Invalid return value from stream", -1, readThisTime); fail("Reached EOF prematurely, expected " + expectedCount + ", got " + read); } else if (readThisTime == 0) { // Another special case that should not happen. fail("Stream breaks contract, read zero chars: " + reader); } read += readThisTime; if (read == expectedCount) { return buf[readThisTime - 1]; } else if (read > expectedCount) { fail( "Too many chars in stream, expected " + expectedCount + "have " + read + "(EOF not reached/confirmed)"); } } }