Modify a .txt file in Java

This solution seems slightly "hacky" to me, especially if I have thousands of lines in my text file.

Anybody know of a better solution?

6,206 16 16 gold badges 53 53 silver badges 58 58 bronze badges asked May 4, 2009 at 21:29 Zakir Hemraj Zakir Hemraj 959 3 3 gold badges 13 13 silver badges 18 18 bronze badges

You can use RandomAccessFile in Java to modify the file without writing back the whole file back. See detailed information below posted by me.

Commented Mar 28, 2014 at 2:40

12 Answers 12

I haven't done this in Java recently, but writing an entire file into memory seems like a bad idea.

The best idea that I can come up with is open a temporary file in writing mode at the same time, and for each line, read it, modify if necessary, then write into the temporary file. At the end, delete the original and rename the temporary file.

If you have modify permissions on the file system, you probably also have deleting and renaming permissions.

answered May 4, 2009 at 21:33 Andrei Krotkov Andrei Krotkov 5,644 3 3 gold badges 34 34 silver badges 37 37 bronze badges

Turns out my answer was wrong; I forgot that RandomAccessFile doesn't allow insertions or deletions. I think this is the best answer.

Commented May 4, 2009 at 21:40 I ended up using this approach with a BufferedReader and BufferedWriter. Commented May 5, 2009 at 14:33

if the file is just a few thousand lines you should be able to read the entire file in one read and convert that to a String.

You can use apache IOUtils which has method like the following.

public static String readFile(String filename) throws IOException < File file = new File(filename); int len = (int) file.length(); byte[] bytes = new byte[len]; FileInputStream fis = null; try < fis = new FileInputStream(file); assert len == fis.read(bytes); >catch (IOException e) < close(fis); throw e; >return new String(bytes, "UTF-8"); > public static void writeFile(String filename, String text) throws IOException < FileOutputStream fos = null; try < fos = new FileOutputStream(filename); fos.write(text.getBytes("UTF-8")); >catch (IOException e) < close(fos); throw e; >> public static void close(Closeable closeable) < try < closeable.close(); >catch(IOException ignored) < >> 
answered May 5, 2009 at 6:28 Peter Lawrey Peter Lawrey 532k 82 82 gold badges 766 766 silver badges 1.1k 1.1k bronze badges

RandomAccessFile

You can use RandomAccessFile in Java to modify the file 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(); > 
330k 119 119 gold badges 908 908 silver badges 1.2k 1.2k bronze badges answered Mar 28, 2014 at 2:38 sendon1982 sendon1982 10.9k 66 66 silver badges 48 48 bronze badges

If the file is large, you might want to use a FileStream for output, but that seems pretty much like it is the simplest process to do what you're asking (and without more specificity i.e. on what types of changes / edits / deletions you're trying to do, it's impossible to determine what more complicated way might work).

answered May 4, 2009 at 21:34 Paul Sonier Paul Sonier 39.4k 3 3 gold badges 78 78 silver badges 117 117 bronze badges

No reason to buffer the entire file.

Simply write each line as your read it, insert lines when necessary, delete lines when necessary, replace lines when necessary.

Fundamentally, you will not get around having to recreate the file wholesale, especially if it's just a text file.

answered May 4, 2009 at 21:38 Will Hartung Will Hartung 118k 20 20 gold badges 131 131 silver badges 204 204 bronze badges

What kind of data is it? Do you control the format of the file?

If the file contains name/value pairs (or similar), you could have some luck with Properties, or perhaps cobbling together something using a flat file JDBC driver.

Alternatively, have you considered not writing the data so often? Operating on an in-memory copy of your file should be relatively trivial. If there are no external resources which need real time updates of the file, then there is no need to go to disk every time you want to make a modification. You can run a scheduled task to write periodic updates to disk if you are worried about data backup.

answered May 4, 2009 at 23:05 James Van Huis James Van Huis 5,551 1 1 gold badge 27 27 silver badges 25 25 bronze badges

In general you cannot edit the file in place; it's simply a very long sequence of characters, which happens to include newline characters. You could edit in place if your changes don't change the number of characters in each line.

answered May 4, 2009 at 21:34 user98989 user98989

Can't you use regular expressions, if you know what you want to change ? Jakarta Regexp should probably do the trick.

answered May 10, 2009 at 11:58 Valentin Rocher Valentin Rocher 11.7k 46 46 silver badges 59 59 bronze badges

Although this question was a time ago posted, I think it is good to put my answer here. I think that the best approach is to use FileChannel from java.nio.channels package in this scenario. But this, only if you need to have a good performance! You would need to get a FileChannel via a RandomAccessFile , like this:

java.nio.channels.FileChannel channel = new java.io.RandomAccessFile("/my/fyle/path", "rw").getChannel();

After this, you need a to create a ByteBuffer where you will read from the FileChannel .

this looks something like this:

 java.nio.ByteBuffer inBuffer = java.nio.ByteBuffer.allocate(100); int pos = 0; int aux = 0; StringBuilder sb = new StringBuilder(); while (pos != -1) < aux = channel.read(inBuffer, pos); pos = (aux != -1) ? pos + aux : -1; b = inBuffer.array(); sb.delete(0, sb.length()); for (int i = 0; i < b.length; ++i) < sb.append((char)b[i]); >//here you can do your stuff on sb inBuffer = ByteBuffer.allocate(100); > 

Hope that my answer will help you!