簡體   English   中英

Java - 通過在讀取文本文件時覆蓋從文本文件中刪除行

[英]Java - delete line from text file by overwriting while reading it

我試圖從文本文件中刪除一行文本而不復制到臨時文件。 我試圖通過使用 Printwriter 和 Scanner 並讓它們同時遍歷文件來做到這一點,作者寫下 Scanner 讀取的內容並用相同的東西覆蓋每一行,直到到達我希望的行刪除。 然后,我推進 Scanner 而不是 writer,並像以前一樣繼續。 這是代碼:

但首先,參數:我的文件名是數字,所以這將讀取 1.txt 或 2.txt 等,因此 f 指定文件名。 我在文件的構造函數中將其轉換為字符串。 Int n 是我要刪除的行的索引。

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

它給了我奇怪的錯誤。 它在堆棧跟蹤中顯示“NoSuchElementException”和“未找到行”。 它指向不同的線; 似乎任何 nextLine() 調用都可以做到這一點。 是否可以通過這種方式刪除一行? 如果是這樣,我做錯了什么? 如果不是,為什么? (順便說一句,以防萬一你想要這個,文本文件大約有 500 行。不過,我不知道這是否算大甚至重要。)

正如其他人指出的那樣,如果您的程序在中途崩潰的風險很小,那么您最好使用臨時文件:

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

}

(注意編碼、換行符和異常處理的草率處理。)


但是,我不喜歡用“我不會告訴你怎么做,因為無論如何你都不應該這樣做。 ”來回答問題。 (例如,在其他一些情況下,您可能正在處理一個大於一半硬盤驅動器的文件!)所以這里是:

您需要改用RandomAccessFile 使用此類,您可以使用相同的對象讀取和寫入文件:

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

你不能這樣做。 FileWriter 只能附加到一個文件,而不是在它的中間寫入 - 如果要在中間寫入,則需要 RandomAccessFile。 您現在所做的 - 您在第一次寫入文件時覆蓋該文件(並且它變空 - 這就是您收到異常的原因)。 您可以創建 FileWriter 並將附加標志設置為 true - 但這樣您將附加到文件而不是在文件中間寫入。

我真的建議寫入一個新文件,然后在最后重命名它。

@shelley:你不能做你想做的事,更重要的是,你不應該做。 出於多種原因,您應該讀取文件並寫入臨時文件,一方面,可以這樣做(與您嘗試執行的操作相反);另一方面,如果進程損壞,您可以打包不丟失原文件。 現在您可以使用 RandomAccessFile 更新文件的特定位置,但這通常在您處理固定大小的記錄而不是典型的文本文件時完成(根據我的經驗)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM