Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limit file size while writing in java

I need to limit the file size to 1 GB while writing preferably using BufferedWriter.

Is it possible using BufferedWriter or I have to use other libraries ?

like

try (BufferedWriter writer = Files.newBufferedWriter(path)) {   
    //...
    writer.write(lines.stream());
} 
like image 337
hacker Avatar asked Dec 19 '22 14:12

hacker


2 Answers

You can always write your own OutputStream to limit the number of bytes written.

The following assumes you want to throw exception if size is exceeded.

public final class LimitedOutputStream extends FilterOutputStream {
    private final long maxBytes;
    private long       bytesWritten;
    public LimitedOutputStream(OutputStream out, long maxBytes) {
        super(out);
        this.maxBytes = maxBytes;
    }
    @Override
    public void write(int b) throws IOException {
        ensureCapacity(1);
        super.write(b);
    }
    @Override
    public void write(byte[] b) throws IOException {
        ensureCapacity(b.length);
        super.write(b);
    }
    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        ensureCapacity(len);
        super.write(b, off, len);
    }
    private void ensureCapacity(int len) throws IOException {
        long newBytesWritten = this.bytesWritten + len;
        if (newBytesWritten > this.maxBytes)
            throw new IOException("File size exceeded: " + newBytesWritten + " > " + this.maxBytes);
        this.bytesWritten = newBytesWritten;
    }
}

You will of course now have to set up the Writer/OutputStream chain manually.

final long SIZE_1GB = 1073741824L;
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
        new LimitedOutputStream(Files.newOutputStream(path), SIZE_1GB),
        StandardCharsets.UTF_8))) {
    //
}
like image 150
Andreas Avatar answered Dec 29 '22 10:12

Andreas


Exact bytes to 1 GB is very difficult in cases where you are writing lines. Each line may contain unknown number of bytes in it. I am assuming you want to write data line by line in file.

However, you can check how many bytes does line has before writing it to the file and another approach is to check file size after writing each line.

Following basic example writes one same line each time. Here This is just a test ! text takes 21 bytes on file in UTF-8 encoding. Ultimately after 49 writes it reaches to 1029 Bytes and stops writing.

public class Test {

    private static final int ONE_KB = 1024;

    public static void main(String[] args) {
        File file = new File("D:/test.txt");

        try (BufferedWriter writer = Files.newBufferedWriter(file.toPath())) {
            while (file.length() < ONE_KB) {
                writer.write("This is just a test !");
                writer.flush();
            }
            System.out.println("1 KB Data is written to the file.!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

As you can see we have already written out of the limit of 1KB as above program writes 1029 Bytes and not less than 1024 Bytes.

Second approach is checking the bytes according to specific encoding before writing it to file.

public class Test {

    private static final int ONE_KB = 1024;

    public static void main(String[] args) throws UnsupportedEncodingException {
        File file = new File("D:/test.txt");
        String data = "This is just a test !";
        int dataLength = data.getBytes("UTF-8").length;

        try (BufferedWriter writer = Files.newBufferedWriter(file.toPath())) {
            while (file.length() + dataLength < ONE_KB) {
                writer.write(data);
                writer.flush();
            }
            System.out.println("1 KB Data written to the file.!");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}   

In this approach we check length of bytes prior to writing it to the file. So, it will write 1008 Bytes and it will stop writing.

Problems with both the approaches,

  • Write and Check : You may end up with some extra bytes and file size may cross the limit
  • Check and Write : You may have less bytes than the limit if next line has lot of data in it. You should be careful about the encoding.

However, there are other ways to do this validations with some third party library like apache io and I find it more cumbersome then conventional java ways.

like image 31
akash Avatar answered Dec 29 '22 12:12

akash