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

执行前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

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

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

输出操作从文件指针开始写入字节,并使文件指针超过写入的字节。

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

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

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

编辑:

如果要编辑文件内容,您应该实际执行Eel建议的操作。

或者你可以获取文件的其余部分并将其添加到修改后的数据并写入文件以避免丢失,但这将变得非常困难和复杂。 更不用说性能惩罚了。

了解当您使用RAF进行写入时,会覆盖先前保存在文件指针位置的数据。 如果要将文本插入文件,我建议您不要使用RAF,而只需使用包装在BufferedReader中的FileReader所持有的文件,将文件文本读入String或ArrayList或StringBuilder中。包含在扫描程序中的文件,更改内存中保存的字符串或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 fileLines = new ArrayList(); 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(); } } } } 

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

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

}