Создать файл заданного размера на Java

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

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

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
51
0
42 981
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Будет ли полученный файл разреженным?

sk. 29.10.2008 02:37

ск: В целом да. На практике это зависит от специфики базовой ОС и может потребовать некоторых действий, чтобы сделать файл разреженным.

Greg Hewgill 29.10.2008 02:39

В Unix и Linux это будет разреженный файл - один блок из нулевых байтов, кроме записанного одного байта (который, конечно, также может быть нулевым).

Jonathan Leffler 29.10.2008 02:40

В Windows (NTFS) и OS-X (HFS +) вы не получите разреженный файл.

Dana Robinson 14.11.2012 01:09
Ответ принят как подходящий

Создайте новый 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

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

Как вы записывали эти трассировки вызовов библиотеки? ^^

akuhn 29.10.2008 03:38

Это трассировки системных вызовов. Я использовал strace (1) под Linux и truss (1) под Solaris.

Diomidis Spinellis 29.10.2008 09:37

В javadoc написано, что «В этом случае содержимое расширенной части файла не определено». Гарантирует ли это обнуление в Windows и Linux, или есть какой-нибудь эффективный способ убедиться, что все байты нули?

Sarmun 28.03.2009 02:15

Я ожидал, что любая ОС (включая Windows и Linux) обнулит байты, чтобы избежать утечки старых данных, принадлежащих другому пользователю. Однако я могу думать о сценариях, в которых этого не было бы: старые данные, принадлежащие тому же процессу, или небольшая (J2ME) платформа.

Diomidis Spinellis 29.03.2009 17:00

Блестяще. Я использовал его, чтобы протестировать приложение для Android в условиях «SD-карта заполнена»!

Mauro Vanetti 18.03.2011 20:08

Интересно, что RandomAccessFile.setLength() API также заполняет файл нулями, что иногда может быть очень полезно.

Sandeep 14.07.2011 22:21

@Sandeep это неверно. В Javadoc прямо говорится, что «содержимое расширенной части файла не определено». Нули могут быть поведением на конкретной платформе.

user207421 18.10.2011 04:52

Действительно ли вышеупомянутый ответ работает? Единственное, что создано в моей тестовой системе (виртуальная машина CentOS 5.6), похоже, является ПУСТОЙ файл, который сообщает о «выделенном» размере с помощью метода length (), который может быть сколь угодно большим независимо от доступного пространства. Если вы откроете файл и напишете несколько символов, размер файла изменится до нескольких байтов. Метод getFreeSpace () класса File сообщает об одном и том же объеме доступного пространства до и после «создания» файла, и вы можете использовать свободное дисковое пространство раздела, как если бы созданного файла там не было, независимо от того, насколько велик предустановленная длина составляет.

PNS 21.10.2011 05:12

Файл заданного размера не должен занимать такое количество байтов. Многие системы поддерживают разреженные файлы (это то, что вы видите), когда пустые части файла не хранятся на диске. Другие системы могут поддерживать сжатые файлы, где объем используемого хранилища зависит от того, насколько сжимаемо содержимое файла.

Diomidis Spinellis 12.07.2014 18:49

Работает так, как ожидалось, но есть ли способы настроить этот подход для создания уникальных файлов (какие значения MD5 отличаются)? @DiomidisSpinellis

talha06 14.02.2017 14:38

Чтобы сделать файлы уникальными, создайте их другой длины или добавьте UUID в начало или конец файла.

Diomidis Spinellis 16.02.2017 11:22

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

Kreender 04.06.2020 23:40

В исходном вопросе конкретно задан вопрос о создании разреженного файла. Для разреженных файлов по определению требуется меньше места, чем их длина.

Diomidis Spinellis 06.06.2020 00:05

Начиная с 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);
}

Большое спасибо @mandev. Работал как шарм !!

PravyNandas 26.02.2021 21:46

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