3

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

M_K
  • 119
  • 1
  • 3
  • 13
  • Why are you using RandomAccessFile for this? Why not simply read the file, using a FileReader wrapped in a BufferedReader, alter the Strings and then write the new file using a FileWriter wrapped in a PrintWriter? – Hovercraft Full Of Eels Mar 17 '13 at 13:59

5 Answers5

4

RandomAccessFile

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 pointer is 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.

  • Ohh i didn't know that randomaccessfile worked like this. Is there any way i can do this. By using anything like fileoutputstream, filewriter etc. I don't want to create a new temp file for doing this operation or store data into an arraylist or map and update it in another file. – M_K Mar 17 '13 at 16:20
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();
         }
      }
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • @Hovercraft..not working with "Text to be appended with here some words" when something after this sentence in same line..it can not insert the "new text has been appended". so can you help me how to insert in same line? – Java Man Oct 24 '13 at 05:54
1

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.

Thihara
  • 7,031
  • 2
  • 29
  • 56
  • I don't want to create a new temp file for this operation. Will it be possible if i use something like csvparser? – M_K Mar 17 '13 at 16:02
1

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

}

sendon1982
  • 9,982
  • 61
  • 44
0

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.

sendon1982
  • 9,982
  • 61
  • 44