2

我的示例代码

    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();

demo.txt 执行前

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

demo.txt 执行后

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

我还尝试使用 setLength 在添加新文本之前更改文件的长度。但仍有一些文本正在从输出文件中修剪。任何帮助将不胜感激

谢谢马修

4

5 回答 5

3

RandomAccessFile

随机访问文件的行为类似于存储在文件系统中的大型字节数组。

事实上,它并不关心在写操作的情况下移动数组元素(只有指针是先进的)。这样的操作会覆盖现有值:

输出操作从文件指针开始写入字节,并将文件指针前进到写入的字节。

于 2013-03-17T14:07:21.263 回答
1

了解当您使用 RAF 写入时,您会覆盖以前保存在文件指针位置的数据。如果要将文本插入文件,我建议您不要使用 RAF,而只需使用ArrayList<String>包含在 BufferedReader 中的 FileReader 或包含在一个 Scanner,更改内存中保存的字符串或 StringBuilder,然后使用包装在 PrintWriter 中的 FileWriter 将更改后的数据写入新文件。

例如,

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();
         }
      }
   }
}
于 2013-03-17T14:06:52.907 回答
1

当您寻找文件的字节位置并写入数据时,字节将被覆盖。

这就是为什么你会得到这样的输出。

想象一下按下插入键在记事本中编辑某些内容。它将替换而不是在两者之间插入新数据。这里也发生了同样的事情。

编辑:

如果您想编辑文件内容,您实际上应该按照 Eel 的建议进行操作。

或者您可以获取文件的其余部分并将其添加到修改后的数据中并写入文件以避免丢失,但这会很快变得丑陋和复杂。更不用说性能惩罚了。

于 2013-03-17T14:11:27.750 回答
1

您可以在 Java 中使用 RandomAccessFile 在一个条件下实现此目的:必须固定每行的大小,否则,当写回新字符串时,它可能会覆盖下一行中的字符串。

因此,在我的示例中,我将行长设置为 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();
}

}

于 2014-03-28T02:35:35.260 回答
0

如果被替换的字符串太长,则与输入匹配的行之后的字符串将被替换。看来您必须读取文件,修改它并写回旧文件或新文件。当然,您可以选择使用多线程编程和 Java 7 的新 IO 特性来提高性能。

于 2014-03-27T04:06:43.690 回答