Создать файл с заданным размером в Java

Есть ли эффективный способ создать файл с заданным размером в Java?

В C это можно сделать с помощью ftruncate (см. Ответ).

Большинство людей просто записывают в файл n фиктивных байтов, но должен быть более быстрый путь. Я думаю о ftruncate, а также о разреженных файлах...

2 ответа

Решение

Создайте новый RandomAccessFile и вызовите метод setLength, указав желаемую длину файла. Базовая реализация JRE должна использовать наиболее эффективный метод, доступный в вашей среде.

Следующая программа

import java.io.*;

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

на машине с Linux выделит место с помощью 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

в то время как на машине Solaris он будет использовать функцию F_FREESP64 системного вызова fcntl(2).

/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

В обоих случаях это приведет к созданию разреженного файла.

Начиная с Java 8, этот метод работает в Linux и 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);
}

Вы можете открыть файл для записи, выполнить поиск смещения (n-1) и записать один байт. ОС автоматически расширит файл до желаемого количества байтов.

Другие вопросы по тегам