SwadhyAI Notes

All Java notes

Java FileInputStream

›Short versionOpen if you only have a minute.
  • FileInputStream reads bytes from a file. It does not decode characters.
  • read() returns 0 through 255, and -1 at the end of the file.
  • read(byte[]) can fill only part of the array. Use the count it returns.
  • Wrap it in an InputStreamReader with a charset when the file is text.
  • Close the outermost wrapper with try-with-resources. That close releases the file.

A is how you pull a file into the program as bytes. A JPEG, a zip, and a PDF are already bytes, so they can stay on this stream. A text file is bytes too, and it needs a before those bytes become characters.

One byte, then a chunk

The one-argument form of the idea is read(). It returns the next as an int, or -1 at the . Teaching code looks like this. A large file should not be read this way, because each call does a small amount of work for a single byte.

ReadOneByte.java
try (FileInputStream input = new FileInputStream("data.bin")) {
    int value;
    while ((value = input.read()) != -1) {
        // value is 0 through 255
    }
}

The working form reads into an array. The return value is a count, and the last successful read is often a . Process chunk[0] through chunk[count - 1], then loop.

ReadChunks.java
byte[] chunk = new byte[8192];
try (FileInputStream input = new FileInputStream("data.bin")) {
    int count;
    while ((count = input.read(chunk)) != -1) {
        consume(chunk, count);
    }
}

Text is a layer on top

When the bytes are UTF-8 text, wrap the stream. InputStreamReader decodes. BufferedReader then fills a character buffer so readLine() can run from memory. The charset belongs on the reader that touches the bytes.

ReadText.java
try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(new FileInputStream("notes.txt"), StandardCharsets.UTF_8))) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}

readLine() returns null at the end. That null is the character-stream end, the partner of -1 on the byte stream. An empty line is an empty string, because the line ending was there and the line had no characters.

The same buffer that makes reading cheap can hide a failure on the way out. This page only reads, so the file position moves as bytes arrive. The matching writer page is where a BufferedWriter accepts characters, returns, and throws only when flush or close pushes them. If you later write a copy through a buffered writer, a short write can look done while the new file is still unchanged.

Who closes the file

is the close. The variable declared in the parentheses is closed when the block ends. In the text example the variable is the BufferedReader. Its close() closes the InputStreamReader, which closes the FileInputStream, which releases the descriptor.

You opened the stack, so you close it. A helper that receives an already-open InputStream should read and return, and leave the close to the caller, unless the method's contract says it takes ownership. Closing a wrapper you built around a borrowed stream closes the caller's file too.

The last read(chunk) returned 200, and chunk.length is 8192. How many bytes from that array should the copy write?

200. They sit at the front of the array. out.write(chunk, 0, 200) writes those and stops. out.write(chunk) would also write the 7992 bytes left over from earlier reads. The next call that returns -1 is the end, and that call contributes no bytes.