Вставка текста в середину с помощью RandomAccessFile удаляет некоторый текст после этого


Мой Пример Кода

    String line = null;
    RandomAccessFile file = new RandomAccessFile("D:/mahtew.txt", "rw");
    System.out.println(file.getFilePointer());
    while((line = file.readLine()) != null){
        System.out.println(line);
        System.out.println(file.getFilePointer());

        if(line.contains("Text to be appended with")){
            file.seek(file.getFilePointer());
            file.write(" new text has been appended".getBytes());
            break;
        }
    }
    file.close();

Демо.txt перед выполнением

one two three
Text to be appended with
five six seven
eight nine ten

Демо.txt после выполнения

one two three
Text to be appended with
 new text has been appendedten

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

Спасибо Мэтью

5 2

5 ответов:

RandomAccessFile

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

На самом деле он не заботится о смещении элементов массива в случае операций записи (только указатель выдвигается). Такая операция перезаписывает существующие значения:

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

Когда вы ищете байтовое расположение файла и записываете данные, байты будут перезаписаны.

Вот почему вы получаете такой вывод.

Просто представьте, что вы редактируете что-то в блокноте с нажатой клавишей insert. Он будет заменять, а не вставлять новые данные между ними. То же самое происходит и здесь.

Правка:

Если вы хотите отредактировать содержимое файла, вам следует сделать то, что предлагает Eel.

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

Поймите, что когда вы пишете с RAF, вы перезаписываете данные, которые ранее хранились в местоположении указателя файла. Если вы хотите вставить текст в файл, я предлагаю вам не использовать RAF, а просто прочитать текст файла в строку или ArrayList<String> или StringBuilder, используя файл, хранящийся в FileReader, завернутый в BufferedReader, или файл, завернутый в сканер, изменить строки или StringBuilder, хранящиеся в памяти, а затем записать измененные данные в новый файл с помощью сканера. Файловая машинка, завернутая в печатный станок.

Например,

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class AppendLine {
   private static final String FILE_PATH = "src/tetris/mahtew.txt";
   private static final String MARKER_LINE = "Text to be appended with";
   private static final String TEXT_TO_ADD = "new text has been appended";

   public static void main(String[] args) {
      List<String> fileLines = new ArrayList<String>();
      Scanner scanner = null;
      try {
         scanner = new Scanner(new File(FILE_PATH));
         while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            fileLines.add(line);
            if (line.trim().equalsIgnoreCase(MARKER_LINE)) {
               fileLines.add(TEXT_TO_ADD);
            }
         }

      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } finally {
         if (scanner != null) {
            scanner.close();
         }
      }

      PrintWriter pw = null;
      try {
         pw = new PrintWriter(new File(FILE_PATH));
         for (String line : fileLines) {
            pw.println(line);
         }
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } finally {
         if (pw != null) {
            pw.close();
         }
      }
   }
}

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

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

Поэтому в моем примере я устанавливаю длину строки как 100 и заполнение пробелом строки при создании файла и записи обратно в файл.

Итак, чтобы разрешить обновление, вам нужно установить длину строки немного больше, чем самая длинная длина строки в этом файл.

public class RandomAccessFileUtil {
public static final long RECORD_LENGTH = 100;
public static final String EMPTY_STRING = " ";
public static final String CRLF = "\n";

public static final String PATHNAME = "/home/mjiang/JM/mahtew.txt";

/**
 *  one two three
    Text to be appended with
    five six seven
    eight nine ten
 * 
 * 
 * @param args
 * @throws IOException
 */
public static void main(String[] args) throws IOException
{
    String starPrefix = "Text to be appended with";
    String replacedString = "new text has been appended";

    RandomAccessFile file = new RandomAccessFile(new File(PATHNAME), "rw");

    String line = "";
    while((line = file.readLine()) != null)
    {
        if(line.startsWith(starPrefix))
        {
            file.seek(file.getFilePointer() - RECORD_LENGTH - 1);
            file.writeBytes(replacedString);
        }

    }
}

public static void createFile() throws IOException
{
    RandomAccessFile file = new RandomAccessFile(new File(PATHNAME), "rw");

    String line1 = "one two three";
    String line2 = "Text to be appended with";
    String line3 = "five six seven";
    String line4 = "eight nine ten";

    file.writeBytes(paddingRight(line1));
    file.writeBytes(CRLF);
    file.writeBytes(paddingRight(line2));
    file.writeBytes(CRLF);
    file.writeBytes(paddingRight(line3));
    file.writeBytes(CRLF);
    file.writeBytes(paddingRight(line4));
    file.writeBytes(CRLF);

    file.close();

    System.out.println(String.format("File is created in [%s]", PATHNAME));
}

public static String paddingRight(String source)
{
    StringBuilder result = new StringBuilder(100);
    if(source != null)
    {
        result.append(source);
        for (int i = 0; i < RECORD_LENGTH - source.length(); i++)
        {
            result.append(EMPTY_STRING);
        }
    }

    return result.toString();
}

}