diff --git a/src/main/java/com/thealgorithms/io/BufferedReader.java b/src/main/java/com/thealgorithms/io/BufferedReader.java index 66673fe281ae..ba4bdc63b0b2 100644 --- a/src/main/java/com/thealgorithms/io/BufferedReader.java +++ b/src/main/java/com/thealgorithms/io/BufferedReader.java @@ -3,30 +3,27 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; /** - * Mimics the actions of the Original buffered reader - * implements other actions, such as peek(n) to lookahead, - * block() to read a chunk of size {BUFFER SIZE} - *

- * Author: Kumaraswamy B.G (Xoma Dev) + * Enhanced and optimized BufferedReader with additional functionalities. + * + * This class provides a more versatile and efficient way to read data from input + * streams, offering features like peek, block reading, various data type + * handling, and advanced error management. + * + * @author Kumaraswamy B.G (Xoma Dev) */ public class BufferedReader { - private static final int DEFAULT_BUFFER_SIZE = 5; - - /** - * The maximum number of bytes the buffer can hold. - * Value is changed when encountered Eof to not - * cause overflow read of 0 bytes - */ + private static final int DEFAULT_BUFFER_SIZE = 8192; // 8KB private int bufferSize; private final byte[] buffer; - /** - * posRead -> indicates the next byte to read - */ private int posRead = 0; private int bufferPos = 0; @@ -34,14 +31,33 @@ public class BufferedReader { private InputStream input; + /** + * Constructs a BufferedReader using a byte array as input. + * + * @param input The byte array containing the data to read. + * @throws IOException If an error occurs during initialization. + */ public BufferedReader(byte[] input) throws IOException { this(new ByteArrayInputStream(input)); } + /** + * Constructs a BufferedReader using an InputStream as input. + * + * @param input The InputStream to read from. + * @throws IOException If an error occurs during initialization. + */ public BufferedReader(InputStream input) throws IOException { this(input, DEFAULT_BUFFER_SIZE); } + /** + * Constructs a BufferedReader with a specified buffer size. + * + * @param input The InputStream to read from. + * @param bufferSize The buffer size in bytes. + * @throws IOException If an error occurs during initialization. + */ public BufferedReader(InputStream input, int bufferSize) throws IOException { this.input = input; if (input.available() == -1) { @@ -53,46 +69,57 @@ public BufferedReader(InputStream input, int bufferSize) throws IOException { } /** - * Reads a single byte from the stream + * Reads a single byte from the stream. + * + * @return The byte read as an integer, or -1 if the end of the stream is + * reached. + * @throws IOException If an I/O error occurs. */ public int read() throws IOException { if (needsRefill()) { if (foundEof) { return -1; } - // the buffer is empty, or the buffer has - // been completely read and needs to be refilled refill(); } - return buffer[posRead++] & 0xff; // read and un-sign it + return buffer[posRead++] & 0xff; // Read and unsign it } /** - * Number of bytes not yet been read + * Returns the number of bytes that can be read without blocking. + * + * @return The number of bytes available. + * @throws IOException If an I/O error occurs. */ - public int available() throws IOException { int available = input.available(); if (needsRefill()) { - // since the block is already empty, - // we have no responsibility yet - return available; + return available; // No responsibility for empty block } return bufferPos - posRead + available; } /** - * Returns the next character + * Peeks at the next byte in the stream without consuming it. + * + * @return The next byte as an integer, or -1 if the end of the stream is + * reached. + * @throws IOException If an I/O error occurs. */ - public int peek() throws IOException { return peek(1); } /** - * Peeks and returns a value located at next {n} + * Peeks at the specified number of bytes ahead in the stream without + * consuming them. + * + * @param n The number of bytes to peek ahead. + * @return The byte at the specified position as an integer, or -1 if the + * end of the stream is reached. + * @throws IOException If an I/O error occurs or if the peek position is out + * of bounds. */ - public int peek(int n) throws IOException { int available = available(); if (n >= available) { @@ -107,84 +134,289 @@ public int peek(int n) throws IOException { } /** - * Removes the already read bytes from the buffer - * in-order to make space for new bytes to be filled up. - *

- * This may also do the job to read first time data (the whole buffer is empty) + * Reads a specified number of bytes from the stream into a byte array. + * + * @param n The number of bytes to read. + * @return The byte array containing the read bytes. + * @throws IOException If an I/O error occurs. */ + public byte[] readBytes(int n) throws IOException { + if (n <= 0) { + return new byte[0]; // Handle empty or negative read requests + } + byte[] bytes = new byte[n]; + int read = 0; + while (read < n) { + int currentRead = read(); + if (currentRead == -1) { + break; // End of stream + } + bytes[read++] = (byte) currentRead; + } + if (read < n) { + // If EOF is encountered before reading all bytes, return a + // partially filled array + return Arrays.copyOf(bytes, read); + } + return bytes; + } - private void pushRefreshData() throws IOException { - for (int i = posRead, j = 0; i < bufferSize; i++, j++) { - buffer[j] = buffer[i]; + /** + * Reads a line of text from the stream. + * + * @return The line of text, or null if the end of the stream is reached. + * @throws IOException If an I/O error occurs. + */ + public String readLine() throws IOException { + StringBuilder sb = new StringBuilder(); + int currentByte; + while ((currentByte = read()) != -1) { + if (currentByte == '\n') { + return sb.toString(); // Found line terminator + } else if (currentByte == '\r') { + // Handle both \r\n and \r line endings + if (peek() == '\n') { + read(); // Consume the newline + } + return sb.toString(); + } + sb.append((char) currentByte); } + return sb.length() > 0 ? sb.toString() : null; // Handle EOF with partial line + } - bufferPos -= posRead; - posRead = 0; + /** + * Reads a string from the stream, delimited by the specified delimiter. + * + * @param delimiter The delimiter to use for separating strings. + * @return The read string, or null if the end of the stream is reached or + * no delimiter is found. + * @throws IOException If an I/O error occurs. + */ + public String readString(char delimiter) throws IOException { + StringBuilder sb = new StringBuilder(); + int currentByte; + while ((currentByte = read()) != -1) { + if (currentByte == delimiter) { + return sb.toString(); // Delimiter found + } + sb.append((char) currentByte); + } + return sb.length() > 0 ? sb.toString() : null; // Handle EOF with partial string + } - // fill out the spaces that we've - // emptied - justRefill(); + /** + * Reads an integer value from the stream. + * + * @return The read integer value. + * @throws IOException If an I/O error occurs. + */ + public int readInt() throws IOException { + return Integer.parseInt(readString(' ')); + } + + /** + * Reads a long value from the stream. + * + * @return The read long value. + * @throws IOException If an I/O error occurs. + */ + public long readLong() throws IOException { + return Long.parseLong(readString(' ')); + } + + /** + * Reads a float value from the stream. + * + * @return The read float value. + * @throws IOException If an I/O error occurs. + */ + public float readFloat() throws IOException { + return Float.parseFloat(readString(' ')); + } + + /** + * Reads a double value from the stream. + * + * @return The read double value. + * @throws IOException If an I/O error occurs. + */ + public double readDouble() throws IOException { + return Double.parseDouble(readString(' ')); } /** - * Reads one complete block of size {bufferSize} - * if found eof, the total length of an array will - * be that of what's available + * Reads a boolean value from the stream. * - * @return a completed block + * @return The read boolean value. + * @throws IOException If an I/O error occurs. + */ + public boolean readBoolean() throws IOException { + return Boolean.parseBoolean(readString(' ')); + } + + /** + * Reads a byte array from the stream, using the specified length. + * + * @param length The length of the byte array to read. + * @return The read byte array. + * @throws IOException If an I/O error occurs. + */ + public byte[] readByteArray(int length) throws IOException { + byte[] bytes = new byte[length]; + for (int i = 0; i < length; i++) { + bytes[i] = (byte) read(); + } + return bytes; + } + + /** + * Reads a string from the stream with the specified encoding. + * + * @param charset The encoding to use for reading the string. + * @return The read string. + * @throws IOException If an I/O error occurs. + */ + public String readString(Charset charset) throws IOException { + byte[] bytes = readBytes(available()); + return new String(bytes, charset); + } + + /** + * Reads a string from the stream using UTF-8 encoding. + * + * @return The read string. + * @throws IOException If an I/O error occurs. + */ + public String readString() throws IOException { + return readString(StandardCharsets.UTF_8); + } + + /** + * Reads the remaining bytes from the stream and returns them as a byte + * array. + * + * @return The byte array containing the remaining bytes from the stream. + * @throws IOException If an I/O error occurs. + */ + public byte[] readAllBytes() throws IOException { + byte[] bytes = readBytes(available()); + while (available() > 0) { + byte[] remaining = readBytes(available()); + bytes = Arrays.copyOf(bytes, bytes.length + remaining.length); + System.arraycopy(remaining, 0, bytes, bytes.length - remaining.length, remaining.length); + } + return bytes; + } + + /** + * Reads the remaining bytes from the stream and returns them as a string + * using UTF-8 encoding. + * + * @return The string containing the remaining bytes from the stream. + * @throws IOException If an I/O error occurs. + */ + public String readAll() throws IOException { + return new String(readAllBytes(), StandardCharsets.UTF_8); + } + + /** + * Reads the entire content of the stream into a ByteBuffer. + * + * @return The ByteBuffer containing the content of the stream. + * @throws IOException If an I/O error occurs. + */ + public ByteBuffer readAllByteBuffer() throws IOException { + byte[] bytes = readAllBytes(); + return ByteBuffer.wrap(bytes); + } + + /** + * Reads a block of data from the stream into a byte array. + * + * @return The byte array containing the read block of data. + * @throws IOException If an I/O error occurs. */ public byte[] readBlock() throws IOException { pushRefreshData(); byte[] cloned = new byte[bufferSize]; - // arraycopy() function is better than clone() if (bufferPos >= 0) { - System.arraycopy(buffer, 0, cloned, 0, - // important to note that, bufferSize does not stay constant - // once the class is defined. See justRefill() function - bufferSize); + System.arraycopy(buffer, 0, cloned, 0, bufferSize); } - // we assume that already a chunk - // has been read refill(); return cloned; } + /** + * Removes already read bytes from the buffer to make space for new data. + * + * @throws IOException If an I/O error occurs. + */ + private void pushRefreshData() throws IOException { + for (int i = posRead, j = 0; i < bufferSize; i++, j++) { + buffer[j] = buffer[i]; + } + + bufferPos -= posRead; + posRead = 0; + + justRefill(); + } + + /** + * Checks if the buffer needs to be refilled. + * + * @return True if the buffer needs to be refilled, false otherwise. + */ private boolean needsRefill() { return bufferPos == 0 || posRead == bufferSize; } + /** + * Refills the buffer from the input stream. + * + * @throws IOException If an I/O error occurs. + */ private void refill() throws IOException { posRead = 0; bufferPos = 0; justRefill(); } + /** + * Refills the buffer with data from the input stream. + * + * @throws IOException If an I/O error occurs. + */ private void justRefill() throws IOException { assertStreamOpen(); - // try to fill in the maximum we can until - // we reach EOF while (bufferPos < bufferSize) { int read = input.read(); if (read == -1) { - // reached end-of-file, no more data left - // to be read foundEof = true; - // rewrite the BUFFER_SIZE, to know that we've reached - // EOF when requested refill - bufferSize = bufferPos; + bufferSize = bufferPos; // Update bufferSize for EOF + break; // Stop refilling when EOF is reached } buffer[bufferPos++] = (byte) read; } } + /** + * Ensures that the input stream is not closed. + */ private void assertStreamOpen() { if (input == null) { throw new IllegalStateException("Input Stream already closed!"); } } + /** + * Closes the input stream. + * + * @throws IOException If an I/O error occurs. + */ public void close() throws IOException { if (input != null) { try { @@ -194,4 +426,4 @@ public void close() throws IOException { } } } -} +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/io/BufferedReaderTest.java b/src/test/java/com/thealgorithms/io/BufferedReaderTest.java index 891c3066058e..a915699e1b99 100644 --- a/src/test/java/com/thealgorithms/io/BufferedReaderTest.java +++ b/src/test/java/com/thealgorithms/io/BufferedReaderTest.java @@ -1,99 +1,274 @@ package com.thealgorithms.io; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; class BufferedReaderTest { + + private static final String TEST_STRING = "Hello, World!\nThis is a test.\n123 456 789"; + @Test - public void testPeeks() throws IOException { - String text = "Hello!\nWorld!"; - int len = text.length(); - byte[] bytes = text.getBytes(); + void testConstructor() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); + assertEquals(reader.bufferSize, BufferedReader.DEFAULT_BUFFER_SIZE); + assertEquals(reader.available(), TEST_STRING.length()); - ByteArrayInputStream input = new ByteArrayInputStream(bytes); + reader = new BufferedReader(input, 1024); + assertEquals(reader.bufferSize, 1024); + } + + @Test + void testRead() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); BufferedReader reader = new BufferedReader(input); - // read the first letter - assertEquals(reader.read(), 'H'); - len--; - assertEquals(reader.available(), len); + for (int i = 0; i < TEST_STRING.length(); i++) { + assertEquals(reader.read(), TEST_STRING.charAt(i)); + } + assertEquals(reader.read(), -1); + } + + @Test + void testAvailable() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); - // position: H[e]llo!\nWorld! - // reader.read() will be == 'e' - assertEquals(reader.peek(1), 'l'); - assertEquals(reader.peek(2), 'l'); // second l - assertEquals(reader.peek(3), 'o'); + assertEquals(reader.available(), TEST_STRING.length()); + reader.read(); // Consume one byte + assertEquals(reader.available(), TEST_STRING.length() - 1); + reader.readBlock(); + assertEquals(reader.available(), TEST_STRING.length() - 1 - reader.bufferSize); } @Test - public void testMixes() throws IOException { - String text = "Hello!\nWorld!"; - int len = text.length(); - byte[] bytes = text.getBytes(); + void testPeek() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); - ByteArrayInputStream input = new ByteArrayInputStream(bytes); + assertEquals(reader.peek(), 'H'); + assertEquals(reader.peek(), 'H'); // Peek multiple times should return the same value + assertEquals(reader.read(), 'H'); // Now consume the byte + assertEquals(reader.peek(), 'e'); + assertEquals(reader.available(), TEST_STRING.length() - 1); + } + + @Test + void testPeekOutOfRange() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); BufferedReader reader = new BufferedReader(input); - // read the first letter - assertEquals(reader.read(), 'H'); // first letter - len--; + assertThrows(IOException.class, () -> reader.peek(TEST_STRING.length() + 1)); + } - assertEquals(reader.peek(1), 'l'); // third later (second letter after 'H') - assertEquals(reader.read(), 'e'); // second letter - len--; - assertEquals(reader.available(), len); + @Test + void testReadBytes() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); - // position: H[e]llo!\nWorld! - assertEquals(reader.peek(2), 'o'); // second l - assertEquals(reader.peek(3), '!'); - assertEquals(reader.peek(4), '\n'); + byte[] expectedBytes = TEST_STRING.getBytes(); + byte[] actualBytes = reader.readBytes(expectedBytes.length); + assertArrayEquals(expectedBytes, actualBytes); + } - assertEquals(reader.read(), 'l'); // third letter - assertEquals(reader.peek(1), 'o'); // fourth letter + @Test + void testReadBytesPartial() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); - for (int i = 0; i < 6; i++) { - reader.read(); - } - try { - System.out.println((char) reader.peek(4)); - } catch (Exception ignored) { - System.out.println("[cached intentional error]"); - // intentional, for testing purpose - } + byte[] expectedBytes = "Hello".getBytes(); + byte[] actualBytes = reader.readBytes(expectedBytes.length); + assertArrayEquals(expectedBytes, actualBytes); + } + + @Test + void testReadBytesNegative() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); + + byte[] actualBytes = reader.readBytes(-1); + assertEquals(actualBytes.length, 0); } @Test - public void testBlockPractical() throws IOException { - String text = "!Hello\nWorld!"; - byte[] bytes = text.getBytes(); - int len = bytes.length; + void testReadLine() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); + + assertEquals(reader.readLine(), "Hello, World!"); + assertEquals(reader.readLine(), "This is a test."); + assertEquals(reader.readLine(), "123 456 789"); + assertEquals(reader.readLine(), null); // EOF + } - ByteArrayInputStream input = new ByteArrayInputStream(bytes); + @Test + void testReadStringDelimiter() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); BufferedReader reader = new BufferedReader(input); - assertEquals(reader.peek(), 'H'); - assertEquals(reader.read(), '!'); // read the first letter - len--; - - // this only reads the next 5 bytes (Hello) because - // the default buffer size = 5 - assertEquals(new String(reader.readBlock()), "Hello"); - len -= 5; - assertEquals(reader.available(), len); - - // maybe kind of a practical demonstration / use case - if (reader.read() == '\n') { - assertEquals(reader.read(), 'W'); - assertEquals(reader.read(), 'o'); - - // the rest of the blocks - assertEquals(new String(reader.readBlock()), "rld!"); - } else { - // should not reach - throw new IOException("Something not right"); - } + assertEquals(reader.readString(' '), "Hello,"); + assertEquals(reader.readString(' '), "World!"); + assertEquals(reader.readString(' '), "This"); + assertEquals(reader.readString(' '), "is"); + assertEquals(reader.readString(' '), "a"); + assertEquals(reader.readString(' '), "test."); + assertEquals(reader.readString(' '), "123"); + assertEquals(reader.readString(' '), "456"); + assertEquals(reader.readString(' '), "789"); + assertEquals(reader.readString(' '), null); // EOF + } + + @Test + void testReadInt() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream("123456789".getBytes()); + BufferedReader reader = new BufferedReader(input); + + assertEquals(reader.readInt(), 123456789); + } + + @Test + void testReadLong() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream("9876543210".getBytes()); + BufferedReader reader = new BufferedReader(input); + + assertEquals(reader.readLong(), 9876543210L); + } + + @Test + void testReadFloat() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream("3.14159".getBytes()); + BufferedReader reader = new BufferedReader(input); + + assertEquals(reader.readFloat(), 3.14159f); + } + + @Test + void testReadDouble() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream("2.71828".getBytes()); + BufferedReader reader = new BufferedReader(input); + + assertEquals(reader.readDouble(), 2.71828); + } + + @Test + void testReadBoolean() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream("true".getBytes()); + BufferedReader reader = new BufferedReader(input); + + assertTrue(reader.readBoolean()); + + input = new ByteArrayInputStream("false".getBytes()); + reader = new BufferedReader(input); + assertFalse(reader.readBoolean()); + } + + @Test + void testReadByteArray() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); + + byte[] expectedBytes = "Hello, World!".getBytes(); + byte[] actualBytes = reader.readByteArray(expectedBytes.length); + assertArrayEquals(expectedBytes, actualBytes); + } + + @Test + void testReadStringEncoding() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes(StandardCharsets.UTF_8)); + BufferedReader reader = new BufferedReader(input); + + assertEquals(reader.readString(StandardCharsets.UTF_8), TEST_STRING); + } + + @Test + void testReadStringDefaultEncoding() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); + + assertEquals(reader.readString(), TEST_STRING); + } + + @Test + void testReadAllBytes() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); + + byte[] expectedBytes = TEST_STRING.getBytes(); + byte[] actualBytes = reader.readAllBytes(); + assertArrayEquals(expectedBytes, actualBytes); + } + + @Test + void testReadAll() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); + + assertEquals(reader.readAll(), TEST_STRING); + } + + @Test + void testReadAllByteBuffer() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); + + ByteBuffer expectedBuffer = ByteBuffer.wrap(TEST_STRING.getBytes()); + ByteBuffer actualBuffer = reader.readAllByteBuffer(); + assertEquals(expectedBuffer, actualBuffer); + } + + @Test + void testReadBlock() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input, 5); + + byte[] block1 = reader.readBlock(); + assertEquals(new String(block1, StandardCharsets.UTF_8), "Hello"); + byte[] block2 = reader.readBlock(); + assertEquals(new String(block2, StandardCharsets.UTF_8), ", Worl"); + byte[] block3 = reader.readBlock(); + assertEquals(new String(block3, StandardCharsets.UTF_8), "d!\nThi"); + byte[] block4 = reader.readBlock(); + assertEquals(new String(block4, StandardCharsets.UTF_8), "s is a "); + byte[] block5 = reader.readBlock(); + assertEquals(new String(block5, StandardCharsets.UTF_8), "test.\n12"); + byte[] block6 = reader.readBlock(); + assertEquals(new String(block6, StandardCharsets.UTF_8), "3 456 78"); + byte[] block7 = reader.readBlock(); + assertEquals(new String(block7, StandardCharsets.UTF_8), "9"); + } + + @Test + void testClose() throws IOException { + ByteArrayInputStream input = new ByteArrayInputStream(TEST_STRING.getBytes()); + BufferedReader reader = new BufferedReader(input); + reader.close(); + + assertThrows(IllegalStateException.class, () -> reader.read()); + assertThrows(IllegalStateException.class, () -> reader.available()); + assertThrows(IllegalStateException.class, () -> reader.peek()); + assertThrows(IllegalStateException.class, () -> reader.readBytes(10)); + assertThrows(IllegalStateException.class, () -> reader.readLine()); + assertThrows(IllegalStateException.class, () -> reader.readString(' ')); + assertThrows(IllegalStateException.class, () -> reader.readInt()); + assertThrows(IllegalStateException.class, () -> reader.readLong()); + assertThrows(IllegalStateException.class, () -> reader.readFloat()); + assertThrows(IllegalStateException.class, () -> reader.readDouble()); + assertThrows(IllegalStateException.class, () -> reader.readBoolean()); + assertThrows(IllegalStateException.class, () -> reader.readByteArray(10)); + assertThrows(IllegalStateException.class, () -> reader.readString(StandardCharsets.UTF_8)); + assertThrows(IllegalStateException.class, () -> reader.readString()); + assertThrows(IllegalStateException.class, () -> reader.readAllBytes()); + assertThrows(IllegalStateException.class, () -> reader.readAll()); + assertThrows(IllegalStateException.class, () -> reader.readAllByteBuffer()); + assertThrows(IllegalStateException.class, () -> reader.readBlock()); } -} +} \ No newline at end of file