See InputSteram.read(byte[]) for reading bytes at a time.

Example code:

try {
    File file = new File("myFile");
    FileInputStream is = new FileInputStream(file);
    byte[] chunk = new byte[1024];
    int chunkLen = 0;
    while ((chunkLen = is.read(chunk)) != -1) {
        // your code..
    }
} catch (FileNotFoundException fnfE) {
    // file not found, handle case
} catch (IOException ioE) {
    // problem reading, handle case
}
Answer from cklab on Stack Overflow
🌐
Wasolutionscompany
wasolutionscompany.com › java › java+read+heavy+files+with+chunks.html
Program Tutorials - Java - Read heavy files efficiently with chunks.
The magic is to do it by blocks, that is, by dividing the file into small portions of the same we will have better processing either to search or to copy. In the example the reading time happened in a conventional way about 2 min, and with blocks low to less than 10 seconds, additional memory was never affected by running the process. Let's see how it works ... For this process do not need to add additional libraries to the path, we only need import java.io.BufferedReader; import java.io.FileReader;, with the first read the file and the second is necessary to build the buffer...
🌐
Stack Overflow
stackoverflow.com › questions › 41559926 › how-to-read-a-file-in-chunks-that-is-to-large-to-be-stored-in-memory
java - How to read a file in chunks that is to large to be stored in memory - Stack Overflow
January 10, 2017 - With the BufferedReader you read a small part of the file in buffer (number of characters can be changed or left to default size) at a time that way you don't have to worry about going out of memory.
🌐
Coderanch
coderanch.com › t › 278433 › java › Reading-File-Chunks
Reading File in Chunks (I/O and Streams forum at Coderanch)
If not, you can just read 50 lines, leave the file open while you do something else, read 50 more and so on. If yes, you might try to compute how many bytes you have read in the first chunk, close the file while you do something else, open it again and Reader.skip() that many bytes before reading more.
🌐
Novixys Software
novixys.com › blog › java-reading-large-file-efficiently
Java - Reading a Large File Efficiently | Novixys Software Dev Blog
August 6, 2017 - First off, you could just load the whole file into memory if the file is small enough. For large files, you need to process chunks. A binary file can be processed in chunks of say, 4kB.
🌐
How to do in Java
howtodoinjava.com › home › java new input/output › reading a file with channels and buffers
Reading a File with Channels and Buffers
April 12, 2022 - Use this technique to read a large file where all the file content will not fit into the buffer at a time. To avoid OutOfMemory issues, we can read the file in chunks with a fixed size small buffer.
🌐
Stack Overflow
stackoverflow.com › questions › 19633974 › how-to-read-certain-chunks-of-a-text-file-java
How to read certain chunks of a text file. Java - Stack Overflow
Key Methods to use are FileReaders read() Method to get a single char (or -1 if there are no more) and skip() to ignore a certain amount of chars (already processed) ... import java.io.File; import java.io.FileReader; import java.io.IOException; ...
🌐
Baeldung
baeldung.com › home › java › java io › how to read a large file efficiently with java
How to Read a Large File Efficiently with Java | Baeldung
May 11, 2024 - As we can see, this method offers another way to return an instance of BufferedReader. SeekableByteChannel provides a channel to read and manipulate a given file. It produces a faster performance than standard I/O classes as it’s backed by an auto-resizing byte array. ... try (SeekableByteChannel ch = java.nio.file.Files.newByteChannel(Paths.get(fileName), StandardOpenOption.READ)) { ByteBuffer bf = ByteBuffer.allocate(1000); while (ch.read(bf) > 0) { bf.flip(); // System.out.println(new String(bf.array())); bf.clear(); } }
Find elsewhere
🌐
Blogger
self-learning-java-tutorial.blogspot.com › 2022 › 07 › java-how-to-process-large-file-in-chunks.html
Programming for beginners: Java: How to process a large file in chunks?
July 25, 2022 - BufferedReader#read method used to read the data one chunk at a time. ... Reads characters into a portion of an array. This method return the number of characters read, or -1 if the end of the stream has been reached · Below snippet read the ...
🌐
Medium
medium.com › @testanother-codwar › fast-file-io-in-java-part-7-splitting-the-file-to-chunks-77eb237df9be
Fast File IO in Java Part 7 — Splitting the file to Chunks | by Halit Dönmez | Medium
March 19, 2024 - for (long l = chunks[0]; l < chunks[1]; l++) { ... } for (long l = chunks[1]; l < chunks[2]; l++) { ... } for (long l = chunks[2]; l < end; l++) { ... } This way you can read the file from a defined start and end locations.
🌐
Medium
medium.com › @anuragv.1020 › chunk-by-chunk-tackling-big-data-with-efficient-file-reading-in-chunks-c6f7cf153ccd
Chunk-by-Chunk: Tackling Big Data with Efficient File Reading in Chunks | by Anurag Verma | Medium
July 19, 2023 - By reading the file in smaller chunks using a buffer, you can process the data incrementally without overwhelming the system’s memory. Network communication: If you’re reading data from a network stream, such as receiving data over a socket ...
🌐
Flylib
flylib.com › books › en › 1.134.1 › reading_chunks_of_data_from_a_stream.html
Reading Chunks of Data from a Stream | Input Streams
Both methods return the number ... · The default implementation of these methods in the java.io.InputStream class merely calls the basic read( ) method enough times to fill the requested array or subarray....
Top answer
1 of 1
2

A simple way to do this is to wrap another Reader with a simple class like this:

/**
 * Read fixed-sized chunks from an underlying {@link Reader}
 */
public class ChunkReader {
    private final int chunkSize;
    private Reader reader;

    public ChunkReader(Reader reader, int chunkSize) {
        if (chunkSize <= 0) {
            throw new IllegalArgumentException("Chunk size must be > 0");
        }
        this.reader = reader;
        this.chunkSize = chunkSize;
    }

    public String readChunk() throws IOException {
        if (reader == null) {
            return null;
        }
        char[] cbuf = new char[chunkSize];
        int off = 0;
        int read = 0;
        while (read < chunkSize) {
            int ret = reader.read(cbuf, off, chunkSize-off);
            if (ret == -1) {
                reader = null;
                if (read == 0) {
                    return null;
                }
                break;
            }
            read += ret;
        }
        return new String(cbuf, 0, read);
    }
}

You could turn it into an Iterator fairly easily if you want, but there's one small caveat: we don't quite know if the next readChunk call will return null if the last one succeeded fully (i.e. read a full chunk), because the underlying Reader could immediately return -1 on the first call. So we'll need to do some sneaky look-aheads for this:

public class ChunkIterator implements Iterator<String> {
    private final int chunkSize;
    private Reader reader;
    private String next;

    public ChunkIterator(Reader reader, int chunkSize) {
        if (chunkSize <= 0) {
            throw new IllegalArgumentException("Chunk size must be > 0");
        }
        this.reader = reader;
        this.chunkSize = chunkSize;
    }

    private String readChunk() throws IOException {
        // same as above
    }

    @Override
    public boolean hasNext() {
        if (next != null) {
            return true;
        }
        if (reader == null) {
            return false;
        }
        try {
            next = readChunk();
        } catch (IOException e) {
            // could also return false, depending on your requirements
            throw new RuntimeException(e);
        }
        return next != null;
    }

    @Override
    public String next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return next;
    }
}
Top answer
1 of 2
14

To chunk your input use a FileInputStream:

    Path pp = FileSystems.getDefault().getPath("logs", "access.log");
    final int BUFFER_SIZE = 1024*1024; //this is actually bytes

    FileInputStream fis = new FileInputStream(pp.toFile());
    byte[] buffer = new byte[BUFFER_SIZE]; 
    int read = 0;
    while( ( read = fis.read( buffer ) ) > 0 ){
        // call your other methodes here...
    }

    fis.close();
2 of 2
9

To stream a file, you need to step away from Files.readAllBytes(). It's a nice utility for small files, but as you noticed not so much for large files.

In pseudocode it would look something like this:

while there are more bytes available
    read some bytes
    process those bytes
    (write the result back to a file, if needed)

In Java, you can use a FileInputStream to read a file byte by byte or chunk by chunk. Lets say we want to write back our processed bytes. First we open the files:

FileInputStream is = new FileInputStream(new File("input.txt"));
FileOutputStream os = new FileOutputStream(new File("output.txt"));

We need the FileOutputStream to write back our results - we don't want to just drop our precious processed data, right? Next we need a buffer which holds a chunk of bytes:

byte[] buf = new byte[4096];

How many bytes is up to you, I kinda like chunks of 4096 bytes. Then we need to actually read some bytes

int read = is.read(buf);

this will read up to buf.length bytes and store them in buf. It will return the total bytes read. Then we process the bytes:

//Assuming the processing function looks like this:
//byte[] process(byte[] data, int bytes);
byte[] ret = process(buf, read);

process() in above example is your processing method. It takes in a byte-array, the number of bytes it should process and returns the result as byte-array.

Last, we write the result back to a file:

os.write(ret);

We have to execute this in a loop until there are no bytes left in the file, so lets write a loop for it:

int read = 0;
while((read = is.read(buf)) > 0) {
    byte[] ret = process(buf, read);
    os.write(ret);
}

and finally close the streams

is.close();
os.close();

And thats it. We processed the file in 4096-byte chunks and wrote the result back to a file. It's up to you what to do with the result, you could also send it over TCP or even drop it if it's not needed, or even read from TCP instead of a file, the basic logic is the same.

This still needs some proper error-handling to work around missing files or wrong permissions but that's up to you to implement that.


A example implementation for the process method:

//returns the hex-representation of the bytes
public static byte[] process(byte[] bytes, int length) {
    final char[] hexchars = "0123456789ABCDEF".toCharArray();
    char[] ret = new char[length * 2];
    for ( int i = 0; i < length; ++i) {
        int b = bytes[i] & 0xFF;
        ret[i * 2] = hexchars[b >>> 4];
        ret[i * 2 + 1] = hexchars[b & 0x0F];
    }
    return ret;
}
🌐
amitph
amitph.com › home › java › java large files – efficient processing
Java Large Files - Efficient Processing - amitph
November 22, 2024 - This detailed practical comparison concludes that using a buffer is the best way to transfer a large amount of data using Java IO. Copying the file in chunks helps to limit the amount of consumed memory consumed by the file content. Both the FileChannel and BufferedInputStream performed head-to-head in our tests. The advantage of using BufferedInputStream or FileChannel to read large files is that they have a configurable buffer.
🌐
Java Code Geeks
javacodegeeks.com › home › core java
Memory-Friendly File Reading in Java - Java Code Geeks
April 1, 2024 - Java NIO: The Files class in Java NIO offers methods like lines(Path path) to read lines from a file using streams. This approach is particularly efficient for handling large text files. The best technique for your specific case depends on several factors: File size and format: For very large binary files, chunking with InputStream might be ideal.
🌐
DaniWeb
daniweb.com › programming › software-development › threads › 487976 › read-by-chunks-from-binary-with-java
Read by chunks from binary with java | DaniWeb
November 22, 2014 - I've added the code you shared and it works if the input is text file, but fails with the binary, confirming that scanner doesn't work with binaries. Besides your other way you suggest (read byte by byte), I've been testing with RamdonAccesFile and Inputstream (as shown in first post) reading in blocks of 1024 bytes. The idea is almost working, but I'm failing since it happens as follow. 1- In first iteration I read 1024 bytes and result 4 sequences of D2A7, resulting in 3 complete chunks and 1 incomplete chunk (224 bytes).