Предварительно ожидайте строки в файл в Java

Существует ли способ предварительно ожидать строку в Файл в Java, не создавая временный файл, и пишущий необходимое содержание в него?

21
задан skaffman 29 March 2010 в 12:58
поделиться

5 ответов

Нет, это невозможно сделать БЕЗОПАСНО на Java.

Ни одна реализация файловой системы ни в одной из основных операционных систем не поддерживает такого рода вещи, и вы не найдете эту функцию поддерживаемой ни в одном из основных языков программирования.

Реальные файловые системы реализованы на устройствах, которые хранят данные в виде «блоков» фиксированного размера. Невозможно реализовать модель файловой системы, в которой вы можете вставлять байты в середину файла без значительного замедления ввода-вывода файла, потери дискового пространства или и того, и другого.


Решения, предполагающие перезапись файла на месте, по своей сути небезопасны. Если ваше приложение будет остановлено или питание отключится в середине процесса добавления / перезаписи, вы, вероятно, потеряете данные. Я бы НЕ рекомендовал использовать этот подход на практике.

Используйте временный файл. Так безопаснее.

21
ответ дан 29 November 2019 в 21:35
поделиться

Есть способ, он включает в себя перезапись всего файла (но не временного файла). Как уже упоминалось, ни одна файловая система не поддерживает добавление содержимого к файлу. Вот пример кода, который использует RandomAccessFile для записи и чтения содержимого, сохраняя при этом некоторый контент в буфере в памяти:

public static void main(final String args[]) throws Exception {
    File f = File.createTempFile(Main.class.getName(), "tmp");
    f.deleteOnExit();

    System.out.println(f.getPath());

    // put some dummy content into our file
    BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
    for (int i = 0; i < 1000; i++) {
        w.write(UUID.randomUUID().toString());
        w.write('\n');
    }
    w.flush();
    w.close();

            // append "some uuids" to our file
    int bufLength = 4096;
    byte[] appendBuf = "some uuids\n".getBytes();
    byte[] writeBuf = appendBuf;
    byte[] readBuf = new byte[bufLength];

    int writeBytes = writeBuf.length;

    RandomAccessFile rw = new RandomAccessFile(f, "rw");
    int read = 0;
    int write = 0;

    while (true) {
                    // seek to read position and read content into read buffer
        rw.seek(read);
        int bytesRead = rw.read(readBuf, 0, readBuf.length);

                    // seek to write position and write content from write buffer
        rw.seek(write);
        rw.write(writeBuf, 0, writeBytes);

                    // no bytes read - end of file reached
        if (bytesRead < 0) {
                            // end of
            break;
        }

                    // update seek positions for write and read
        read += bytesRead;
        write += writeBytes;
        writeBytes = bytesRead;

                    // reuse buffer, create new one to replace (short) append buf
        byte[] nextWrite = writeBuf == appendBuf ? new byte[bufLength] : writeBuf;
        writeBuf = readBuf;
        readBuf = nextWrite;
    };

    rw.close();

            // now show the content of our file
    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));

    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}
6
ответ дан 29 November 2019 в 21:35
поделиться

Вы можете сохранить содержимое файла в строке и добавить желаемую строку к началу с помощью StringBuilder-Object. Вам просто нужно сначала поставить желаемую строку, а затем добавить строку file-content-String.
Никаких дополнительных временных файлов не требуется.

0
ответ дан 29 November 2019 в 21:35
поделиться

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

1
ответ дан 29 November 2019 в 21:35
поделиться

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

Однако не делайте этого, потому что если что-то остановится (нехватка памяти, отключение питания, вызов несанкционированного потока System.exit ) в середине этого процесса, данные будут потеряны. Вместо этого используйте временный файл.

0
ответ дан 29 November 2019 в 21:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: