[英]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.