java 使用 RandomAccessFile 在中间插入文本会在此之后删除一些文本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15461555/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Inserting text in middle using RandomAccessFile removes some text after that
提问by user671646
My Sample Code
我的示例代码
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 before execution
执行前的demo.txt
one two three
Text to be appended with
five six seven
eight nine ten
demo.txt after execution
执行后的demo.txt
one two three
Text to be appended with
new text has been appendedten
Also i tried using setLength to change length of file before new text is appended. But still some text is getting trimmed from output file. Any help will be appreciated
我还尝试使用 setLength 在追加新文本之前更改文件长度。但是仍然有一些文本正在从输出文件中被修剪。任何帮助将不胜感激
Thanks Mathew
谢谢马修
回答by hthserhs
A random access file behaves like a large array of bytes stored in the file system.
随机访问文件的行为类似于存储在文件系统中的大量字节。
In fact it does not care about shifting the array elements in the case of write operations (only the pointeris advanced). Such an operation overwrites existing values:
事实上,它并不关心在写操作的情况下移动数组元素(只有指针前进)。这样的操作会覆盖现有值:
Output operations write bytes starting at the file pointer and advance the file pointer past the bytes written.
输出操作从文件指针开始写入字节,并将文件指针前进到写入的字节之后。
回答by Hovercraft Full Of Eels
Understand that when you write with a RAF, you over-write data which was previously held at the file pointer location. If you want to inserttext into a file, I suggest that you not use a RAF but rather simply read the text of the file into a String or ArrayList<String>
or StringBuilder, using a File held by a FileReader wrapped in a BufferedReader or a File wrapped in a Scanner, alter the Strings or StringBuilder held in memory, and then write the altered data to the new file using a FileWriter wrapped in a PrintWriter.
了解当您使用 RAF 进行写入时,您会覆盖先前保存在文件指针位置的数据。如果您想将文本插入到文件中,我建议您不要使用 RAF,而是简单地将文件的文本读入 StringArrayList<String>
或 StringBuilder,使用由包装在 BufferedReader 中的 FileReader 持有的文件或包装在一个扫描器,更改保存在内存中的字符串或 StringBuilder,然后使用包装在 PrintWriter 中的 FileWriter 将更改的数据写入新文件。
e.g.,
例如,
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();
}
}
}
}
回答by Thihara
When you seek to the file's byte location and writes data, the bytes will be overwritten.
当您查找文件的字节位置并写入数据时,这些字节将被覆盖。
Which is why you get an output like this.
这就是为什么你会得到这样的输出。
Just imagine editing something in notepad with the insert key pressed. It will replace instead of inserting the new data in between. Same thing's happening here.
想象一下按下插入键在记事本中编辑一些东西。它将替换而不是在两者之间插入新数据。同样的事情在这里发生。
EDIT:
编辑:
You should actually do what Eel is suggesting if you want to edit the file content.
如果您想编辑文件内容,您实际上应该按照 Eel 的建议进行操作。
Or you can get the rest of the file and add it to the modified data and write to the file in order to avoid the loss, but that will get ugly and complicated real fast. Not to mention performance penalties.
或者您可以获取文件的其余部分并将其添加到修改后的数据中并写入文件以避免丢失,但这会很快变得丑陋和复杂。更不用说绩效惩罚了。
回答by sendon1982
You can use RandomAccessFile in Java to achieve this on one condition: The size of each line has to be fixed otherwise, when new string is written back, it might override the string in the next line.
您可以在 Java 中使用 RandomAccessFile 在一个条件下实现这一点:每行的大小必须固定,否则,当写回新字符串时,它可能会覆盖下一行中的字符串。
Therefore, in my example, I set the line length as 100 and padding with space string when creating the file and writing back to the file.
因此,在我的示例中,我在创建文件并写回文件时将行长度设置为 100 并使用空格字符串填充。
So in order to allow update, you need to set the length of line a little larger than the longest length of the line in this file.
所以为了允许更新,您需要将行的长度设置为比该文件中最长的行长一点。
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();
}
}
}
回答by sendon1982
If replaced string is too long, the strings after the line matched with input will be replaced. It seems you have to read file, modify it and write back to old or new file. Of course, you have options to use multi-threading programming and Java 7's new IO features to improve performance.
如果被替换的字符串太长,则与输入匹配的行之后的字符串将被替换。看来您必须读取文件,修改它并写回旧文件或新文件。当然,您可以选择使用多线程编程和 Java 7 的新 IO 特性来提高性能。