Java - removing a line from a text file by overwriting while reading

I am trying to delete a line of text from a text file without copying to a temporary file. I try to do this using Printwriter and Scanner, and skipping them at the same time, the author writes that the scanner reads and overwrites each line with the same thing until it reaches the line that I want to Delete. Then I promote the scanner, but not the writer, and continue as before. Here is the code:

But first the parameters: My file names are numbers, so this will read 1.txt or 2.txt, etc., and therefore f indicates the file name. I convert it to String in the constructor for the file. Int n is the index of the row I want to delete.

public void deleteLine(int f, int n){ try{ Scanner reader = new Scanner(new File(f+".txt")); PrintWriter writer = new PrintWriter(new FileWriter(new File(f+".txt")),false); for(int w=0; w<n; w++) writer.write(reader.nextLine()); reader.nextLine(); while(reader.hasNextLine()) writer.write(reader.nextLine()); } catch(Exception e){ System.err.println("Enjoy the stack trace!"); e.printStackTrace(); } } 

This gives me weird errors. It says “NoSuchElementException” and “line not found” in the stack trace. It points to different lines; it seems that any of the calls to nextLine () can do this. Is it possible to delete a row this way? If so, what am I doing wrong? If not, why? (BTW, just in case you want it, the text file is about 500 lines. I don’t know if it matters as big or even important.)

+8
java text-files printwriter
source share
3 answers

As others have pointed out, it may be useful for you to use a temporary file if there is even the slightest risk that your program will crash in the middle of the path:

 public static void removeNthLine(String f, int toRemove) throws IOException { File tmp = File.createTempFile("tmp", ""); BufferedReader br = new BufferedReader(new FileReader(f)); BufferedWriter bw = new BufferedWriter(new FileWriter(tmp)); for (int i = 0; i < toRemove; i++) bw.write(String.format("%s%n", br.readLine())); br.readLine(); String l; while (null != (l = br.readLine())) bw.write(String.format("%s%n", l)); br.close(); bw.close(); File oldFile = new File(f); if (oldFile.delete()) tmp.renameTo(oldFile); } 

(Beware of sloppy handling of encodings, newlines and exception handling).


However, I do not like to answer the questions: "I will not tell you how, because you should not do this anyway." (In some other situations, for example, you can work with a file that exceeds half your hard drive!) So, here it goes:

Instead, you need to use RandomAccessFile . Using this class, you can read and write to a file using the same object:

 public static void removeNthLine(String f, int toRemove) throws IOException { RandomAccessFile raf = new RandomAccessFile(f, "rw"); // Leave the n first lines unchanged. for (int i = 0; i < toRemove; i++) raf.readLine(); // Shift remaining lines upwards. long writePos = raf.getFilePointer(); raf.readLine(); long readPos = raf.getFilePointer(); byte[] buf = new byte[1024]; int n; while (-1 != (n = raf.read(buf))) { raf.seek(writePos); raf.write(buf, 0, n); readPos += n; writePos += n; raf.seek(readPos); } raf.setLength(writePos); raf.close(); } 
+19
source share

You cannot do this. FileWriter can only add a file, not write in the middle. You need RandomAccessFile if you want to write in the middle. What you are doing now is that you redefine the file the first time you write it (and it becomes empty - that’s why you get an exception). You can create a FileWriter with the attach flag set to true, but in this way you would add to the file instead of writing it in the middle.

I would recommend writing a new file and then renaming it at the end.

+2
source share

@shelley: you cannot do what you are trying to do, and what else, you should not. You must read the file and write to a temporary file for several reasons, for example, you can do it this way (unlike what you are trying to do), and for another, if the process gets damaged, you can use it without losing the original file. Now you can update a specific file location using RandomAccessFile, but this is usually done (in my experience) when you are dealing with fixed record sizes, rather than typical text files.

+1
source share

All Articles