【问题标题】:Inserting text in middle using RandomAccessFile removes some text after that使用 RandomAccessFile 在中间插入文本之后会删除一些文本
【发布时间】:2013-03-17 13:58:13
【问题描述】:

我的示例代码

    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 在添加新文本之前更改文件的长度。但仍有一些文本正在从输出文件中修剪。任何帮助将不胜感激

谢谢 马修

【问题讨论】:

  • 你为什么要使用 RandomAccessFile 呢?为什么不简单地读取文件,使用包装在 BufferedReader 中的 FileReader,更改字符串,然后使用包装在 PrintWriter 中的 FileWriter 写入新文件?

标签: java java-io


【解决方案1】:

RandomAccessFile

随机访问文件的行为类似于存储在 文件系统。

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

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

【讨论】:

  • 哦,我不知道 randomaccessfile 是这样工作的。有什么办法我可以做到这一点。通过使用文件输出流、文件写入器等任何东西。我不想创建一个新的临时文件来执行此操作或将数据存储到数组列表或映射中并在另一个文件中更新它。
【解决方案2】:

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

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

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

编辑:

如果你想编辑文件内容,你应该按照 Eel 的建议去做。

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

【讨论】:

  • 我不想为此操作创建新的临时文件。如果我使用类似 csvparser 之类的东西有可能吗?
【解决方案3】:

了解当您使用 RAF 写入时,您会覆盖之前保存在文件指针位置的数据。如果您想将文本插入到文件中,我建议您不要使用 RAF,而只需将文件文本读入 String 或 ArrayList<String> 或 StringBuilder,使用由封装在 BufferedReader 中的 FileReader 或封装在 Scanner 中的 File,更改内存中保存的 Strings 或 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();
         }
      }
   }
}

【讨论】:

  • @Hovercraft ..当这句话后面的内容在同一行中时,不能使用“要在此处附加一些单词的文本”..它无法插入“已附加新文本”。那你能帮我在同一行插入吗?
【解决方案4】:

您可以在 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();
}

}

【讨论】:

    【解决方案5】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2014-10-24
      • 2019-01-31
      • 2020-11-03
      • 1970-01-01
      • 2013-07-02
      相关资源
      最近更新 更多