Inserting text in middle using RandomAccessFile removes some text after that
Solution 1
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 insert text 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.
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();
}
}
}
}
Solution 2
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.
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.
Solution 3
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.
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.
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();
}
}
M_K
Updated on June 16, 2022Comments
-
M_K almost 2 years
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
one two three Text to be appended with five six seven eight nine ten
demo.txt after execution
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
Thanks Mathew