61

Is there an efficient way to create a file with a given size in Java?

In C it can be done with ftruncate (see that answer).

Most people would just write n dummy bytes into the file, but there must be a faster way. I'm thinking of ftruncate and also of Sparse files

3 Answers 3

123

Create a new RandomAccessFile and call the setLength method, specifying the desired file length. The underlying JRE implementation should use the most efficient method available in your environment.

The following program

import java.io.*;

class Test {
     public static void main(String args[]) throws Exception {
           RandomAccessFile f = new RandomAccessFile("t", "rw");
           f.setLength(1024 * 1024 * 1024);
     }
}

on a Linux machine will allocate the space using the ftruncate(2)

6070  open("t", O_RDWR|O_CREAT, 0666)   = 4
6070  fstat(4, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
6070  lseek(4, 0, SEEK_CUR)             = 0
6070  ftruncate(4, 1073741824)          = 0

while on a Solaris machine it will use the the F_FREESP64 function of the fcntl(2) system call.

/2:     open64("t", O_RDWR|O_CREAT, 0666)               = 14
/2:     fstat64(14, 0xFE4FF810)                         = 0
/2:     llseek(14, 0, SEEK_CUR)                         = 0
/2:     fcntl(14, F_FREESP64, 0xFE4FF998)               = 0

In both cases this will result in the creation of a sparse file.

Sign up to request clarification or add additional context in comments.

14 Comments

They are system call traces. I used strace(1) under Linux and truss(1) under Solaris.
I would expect that any OS worth its salt (this includes Windows and Linux) to zero the bytes, to avoid the leakage of older data belonging to another user. However, I can think of scenarios where this would not be the case: old data belonging to the same process, or a small (J2ME) platform.
Brilliant. I used it to test an Android app under "SD card filled" conditions!
@Sandeep that is not correct. The Javadoc specifically says that 'the contents of the extended portion of the file are not defined'. The zeros may be the behaviour on a specific platform.
A file of a given size, does not have to occupy that many bytes. Many systems support sparse files (this is what you are seeing), where parts of the file that are empty are not stored on disk. Other systems may support compressed files, where the amount of storage used depends on how compressible are the file's contents.
|
6

Since Java 8, this method works on Linux and Windows :

final ByteBuffer buf = ByteBuffer.allocate(4).putInt(2);
buf.rewind();

final OpenOption[] options = { StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW , StandardOpenOption.SPARSE };
final Path hugeFile = Paths.get("hugefile.txt");

try (final SeekableByteChannel channel = Files.newByteChannel(hugeFile, options);) {
    channel.position(HUGE_FILE_SIZE);
    channel.write(buf);
}

Comments

4

You can open the file for writing, seek to offset (n-1), and write a single byte. The OS will automatically extend the file to the desired number of bytes.

4 Comments

Will the resulting file be sparse?
sk: In general, yes. In practice, this depends on the specifics of the underlying OS and might require some fiddling to make the file sparse.
On Unix and Linux, that will be a sparse file - one block of zero bytes apart from the single byte written (which might also be zero, of course).
On Windows (NTFS) and OS-X (HFS+) you will not get a sparse file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.