2009-09-04 64 views
43

我正在尋找一個小代碼片段,它將在文件中找到一行並刪除該行(不是內容但行),但無法找到。因此,例如我有一個文件如下:在文件中找到一行並將其刪除

MYFILE.TXT

aaa 
bbb 
ccc 
ddd 

需要有這樣的功能:public void removeLine(String lineContent),如果我通過 removeLine("bbb"),我得到的文件是這樣的:

MYFILE.TXT:

aaa 
ccc 
ddd 
+0

您是否找到了實現此目標的最佳方法。更快,更快的方式 – 2016-06-20 12:22:05

回答

66

此解決方案可能不是最佳或漂亮的,但它的工作原理。它逐行讀入輸入文件,將每行寫入臨時輸出文件。每當它遇到一條與你正在尋找的線相匹配的線時,它就會跳過寫出一條線。然後重命名輸出文件。我從示例中省略了錯誤處理,關閉了讀者/作者等。我也假設你正在尋找的行中沒有前導空白或尾隨空白。根據需要更改trim()的代碼,以便找到匹配項。

File inputFile = new File("myFile.txt"); 
File tempFile = new File("myTempFile.txt"); 

BufferedReader reader = new BufferedReader(new FileReader(inputFile)); 
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile)); 

String lineToRemove = "bbb"; 
String currentLine; 

while((currentLine = reader.readLine()) != null) { 
    // trim newline when comparing with lineToRemove 
    String trimmedLine = currentLine.trim(); 
    if(trimmedLine.equals(lineToRemove)) continue; 
    writer.write(currentLine + System.getProperty("line.separator")); 
} 
writer.close(); 
reader.close(); 
boolean successful = tempFile.renameTo(inputFile); 
+0

我在互聯網上發現了這樣的東西,但無論如何非常感謝! – Narek 2009-09-04 05:14:39

+13

您應該在重命名之前添加一個writer.close()。否則,作者可能沒有將最後一行或兩行刷新到磁盤。 – 2009-09-04 06:57:44

+0

最好使用BufferedWriter或PrintWriter? – RadijatoR 2015-07-27 22:32:42

18

你想這樣做了以下內容:閱讀

  • 打開一個新的(臨時)

    • 打開舊文件的文件在舊跨越的行書寫
    • 迭代文件(可能使用的是BufferedReader
      • 對於每一行,檢查它是否與你應該刪除的內容相匹配
      • 如果匹配,什麼都不做
      • 如果不匹配,將其寫入臨時文件
    • 完成後,關閉這兩個文件
    • 刪除舊文件
    • 重命名臨時文件到原始文件的名稱

    (我不會寫實際的代碼,因爲這看起來像家庭作業,但隨時可以發佈其他問題在您遇到麻煩的特定位上)

  • +5

    現在,如果你只是寫出了代碼,那麼你會得到接受的答案,哈哈! ;) – DaveJohnston 2010-03-10 21:45:31

    +0

    任何不涉及創建臨時文件的解決方案?一些可以在同一個文件中寫入的soln。 – 2017-08-08 11:03:30

    +0

    @AniketSinha當然。只要確保已將文件完全讀入數組/緩衝區/字符串並對其進行操作(因爲您可以在讀完所有文件後覆蓋原始文件) – 2017-08-13 03:01:48

    23
    public void removeLineFromFile(String file, String lineToRemove) { 
    
        try { 
    
         File inFile = new File(file); 
    
         if (!inFile.isFile()) { 
         System.out.println("Parameter is not an existing file"); 
         return; 
         } 
    
         //Construct the new file that will later be renamed to the original filename. 
         File tempFile = new File(inFile.getAbsolutePath() + ".tmp"); 
    
         BufferedReader br = new BufferedReader(new FileReader(file)); 
         PrintWriter pw = new PrintWriter(new FileWriter(tempFile)); 
    
         String line = null; 
    
         //Read from the original file and write to the new 
         //unless content matches data to be removed. 
         while ((line = br.readLine()) != null) { 
    
         if (!line.trim().equals(lineToRemove)) { 
    
          pw.println(line); 
          pw.flush(); 
         } 
         } 
         pw.close(); 
         br.close(); 
    
         //Delete the original file 
         if (!inFile.delete()) { 
         System.out.println("Could not delete file"); 
         return; 
         } 
    
         //Rename the new file to the filename the original file had. 
         if (!tempFile.renameTo(inFile)) 
         System.out.println("Could not rename file"); 
    
        } 
        catch (FileNotFoundException ex) { 
         ex.printStackTrace(); 
        } 
        catch (IOException ex) { 
         ex.printStackTrace(); 
        } 
        } 
    

    這是我在網上找到的。

    +3

    如果拋出異常,此代碼將不會關閉文件,你也需要一個最終的陳述。 – DaveJohnston 2010-03-10 21:44:53

    +2

    爲什麼你在每一行後沖洗?這不是沒有效率嗎? – joeytwiddle 2014-06-02 06:02:18

    0
    public static void deleteLine(String line, String filePath) { 
    
        File file = new File(filePath); 
    
        File file2 = new File(file.getParent() + "\\temp" + file.getName()); 
        PrintWriter pw = null; 
        Scanner read = null; 
    
        FileInputStream fis = null; 
        FileOutputStream fos = null; 
        FileChannel src = null; 
        FileChannel dest = null; 
    
        try { 
    
    
         pw = new PrintWriter(file2); 
         read = new Scanner(file); 
    
         while (read.hasNextLine()) { 
    
          String currline = read.nextLine(); 
    
          if (line.equalsIgnoreCase(currline)) { 
           continue; 
          } else { 
           pw.println(currline); 
          } 
         } 
    
         pw.flush(); 
    
         fis = new FileInputStream(file2); 
         src = fis.getChannel(); 
         fos = new FileOutputStream(file); 
         dest = fos.getChannel(); 
    
         dest.transferFrom(src, 0, src.size()); 
    
    
        } catch (IOException e) { 
         e.printStackTrace(); 
        } finally {  
         pw.close(); 
         read.close(); 
    
         try { 
          fis.close(); 
          fos.close(); 
          src.close(); 
          dest.close(); 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } 
    
         if (file2.delete()) { 
          System.out.println("File is deleted"); 
         } else { 
          System.out.println("Error occured! File: " + file2.getName() + " is not deleted!"); 
         } 
        } 
    
    } 
    
    1

    這裏是完整的類。在下面的文件中,「somelocation」指的是文件的實際路徑。

    import java.io.BufferedReader; 
    import java.io.BufferedWriter; 
    import java.io.File; 
    import java.io.FileReader; 
    import java.io.FileWriter; 
    import java.io.IOException; 
    
    
    
    public class FileProcess 
    { 
    
    
        public static void main(String[] args) throws IOException 
        { 
         File inputFile = new File("C://somelocation//Demographics.txt"); 
         File tempFile = new File("C://somelocation//Demographics_report.txt"); 
    
         BufferedReader reader = new BufferedReader(new FileReader(inputFile)); 
         BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile)); 
    
         String currentLine; 
    
         while((currentLine = reader.readLine()) != null) { 
          if(null!=currentLine && !currentLine.equalsIgnoreCase("BBB")){ 
           writer.write(currentLine + System.getProperty("line.separator")); 
          } 
         } 
         writer.close(); 
         reader.close(); 
         boolean successful = tempFile.renameTo(inputFile); 
         System.out.println(successful); 
        } 
    
    } 
    
    11

    使用Apache的commons-IO和Java 8,你可以使用

    List<String> lines = FileUtils.readLines(file); 
    List<String> updatedLines = lines.stream().filter(s -> !s.contains(searchString)).collect(Collectors.toList()); 
    FileUtils.writeLines(file, updatedLines, false); 
    
    +0

    這是否工作? – 2015-08-22 15:59:14

    +3

    在這種情況下整個文件會被讀入內存嗎? – Tim 2015-10-07 02:02:03

    +0

    @Tim恐怕如此 – 2016-08-04 15:26:09

    0
    package com.ncs.cache; 
    
    import java.io.BufferedReader; 
    import java.io.FileReader; 
    import java.io.File; 
    import java.io.FileWriter; 
    import java.io.FileNotFoundException; 
    import java.io.IOException; 
    import java.io.PrintWriter; 
    
    public class FileUtil { 
    
        public void removeLineFromFile(String file, String lineToRemove) { 
    
         try { 
    
          File inFile = new File(file); 
    
          if (!inFile.isFile()) { 
           System.out.println("Parameter is not an existing file"); 
           return; 
          } 
    
          // Construct the new file that will later be renamed to the original 
          // filename. 
          File tempFile = new File(inFile.getAbsolutePath() + ".tmp"); 
    
          BufferedReader br = new BufferedReader(new FileReader(file)); 
          PrintWriter pw = new PrintWriter(new FileWriter(tempFile)); 
    
          String line = null; 
    
          // Read from the original file and write to the new 
          // unless content matches data to be removed. 
          while ((line = br.readLine()) != null) { 
    
           if (!line.trim().equals(lineToRemove)) { 
    
            pw.println(line); 
            pw.flush(); 
           } 
          } 
          pw.close(); 
          br.close(); 
    
          // Delete the original file 
          if (!inFile.delete()) { 
           System.out.println("Could not delete file"); 
           return; 
          } 
    
          // Rename the new file to the filename the original file had. 
          if (!tempFile.renameTo(inFile)) 
           System.out.println("Could not rename file"); 
    
         } catch (FileNotFoundException ex) { 
          ex.printStackTrace(); 
         } catch (IOException ex) { 
          ex.printStackTrace(); 
         } 
        } 
    
        public static void main(String[] args) { 
         FileUtil util = new FileUtil(); 
         util.removeLineFromFile("test.txt", "bbbbb"); 
        } 
    } 
    

    源:http://www.javadb.com/remove-a-line-from-a-text-file/

    0

    這種解決方案需要被添加到構建路徑的Apache Commons IO library。它通過讀取整個文件並將每行寫回,但只有在不包含搜索項時才起作用。

    public static void removeLineFromFile(File targetFile, String searchTerm) 
         throws IOException 
    { 
        StringBuffer fileContents = new StringBuffer(
          FileUtils.readFileToString(targetFile)); 
        String[] fileContentLines = fileContents.toString().split(
          System.lineSeparator()); 
    
        emptyFile(targetFile); 
        fileContents = new StringBuffer(); 
    
        for (int fileContentLinesIndex = 0; fileContentLinesIndex < fileContentLines.length; fileContentLinesIndex++) 
        { 
         if (fileContentLines[fileContentLinesIndex].contains(searchTerm)) 
         { 
          continue; 
         } 
    
         fileContents.append(fileContentLines[fileContentLinesIndex] + System.lineSeparator()); 
        } 
    
        FileUtils.writeStringToFile(targetFile, fileContents.toString().trim()); 
    } 
    
    private static void emptyFile(File targetFile) throws FileNotFoundException, 
         IOException 
    { 
        RandomAccessFile randomAccessFile = new RandomAccessFile(targetFile, "rw"); 
    
        randomAccessFile.setLength(0); 
        randomAccessFile.close(); 
    } 
    
    0

    我重構是Narek必須創建(據我)一個稍微更有效,更容易理解的代碼的解決方案。我使用了嵌入式自動資源管理,它是Java中的一項新功能,並使用了一個Scanner類,根據我的理解和使用,該類更容易理解。

    下面是編輯點評代碼:

    public class RemoveLineInFile { 
    
        private static File file; 
    
        public static void main(String[] args) { 
         //create a new File 
         file = new File("hello.txt"); 
         //takes in String that you want to get rid off 
         removeLineFromFile("Hello"); 
        } 
    
    
        public static void removeLineFromFile(String lineToRemove) { 
    
    
         //if file does not exist, a file is created 
    
          if (!file.exists()) { 
           try { 
            file.createNewFile(); 
           } catch (IOException e) { 
            System.out.println("File "+file.getName()+" not created successfully"); 
           } 
          } 
    
          // Construct the new temporary file that will later be renamed to the original 
          // filename. 
          File tempFile = new File(file.getAbsolutePath() + ".tmp"); 
    
          //Two Embedded Automatic Resource Managers used 
          // to effectivey handle IO Responses 
          try(Scanner scanner = new Scanner(file)) { 
           try (PrintWriter pw = new PrintWriter(new FileWriter(tempFile))) { 
    
            //a declaration of a String Line Which Will Be assigned Later 
            String line; 
    
            // Read from the original file and write to the new 
            // unless content matches data to be removed. 
            while (scanner.hasNextLine()) { 
             line = scanner.nextLine(); 
             if (!line.trim().equals(lineToRemove)) { 
    
              pw.println(line); 
              pw.flush(); 
             } 
            } 
            // Delete the original file 
            if (!file.delete()) { 
             System.out.println("Could not delete file"); 
             return; 
            } 
    
            // Rename the new file to the filename the original file had. 
            if (!tempFile.renameTo(file)) 
             System.out.println("Could not rename file"); 
           } 
          } 
         catch (IOException e) 
         { 
          System.out.println("IO Exception Occurred"); 
         } 
    
        } 
    
    
    
    } 
    
    0

    試試這個:

    public static void main(String[] args) throws IOException { 
    
        File file = new File("file.csv"); 
    
        CSVReader csvFileReader = new CSVReader(new FileReader(file)); 
    
        List<String[]> list = csvFileReader.readAll(); 
    
        for (int i = 0; i < list.size(); i++) { 
         String[] filter = list.get(i); 
         if (filter[0].equalsIgnoreCase("bbb")) { 
          list.remove(i); 
         } 
        } 
        csvFileReader.close(); 
        CSVWriter csvOutput = new CSVWriter(new FileWriter(file)); 
    
        csvOutput.writeAll(list); 
        csvOutput.flush(); 
    
        csvOutput.close(); 
    } 
    
    0
    public static void deleteLine() throws IOException { 
         RandomAccessFile file = new RandomAccessFile("me.txt", "rw"); 
         String delete; 
         String task=""; 
         byte []tasking; 
         while ((delete = file.readLine()) != null) { 
          if (delete.startsWith("BAD")) { 
           continue; 
          } 
          task+=delete+"\n"; 
         } 
         System.out.println(task); 
         BufferedWriter writer = new BufferedWriter(new FileWriter("me.txt")); 
         writer.write(task); 
         file.close(); 
         writer.close(); 
        } 
    
    1

    所以,每當我聽到有人提到,他們希望過濾掉的文字,我立刻想到去Streams(主要是因爲有一種方法稱爲filter,它按照您的需要進行過濾)。另一個答案提及使用Stream s的Apache的公地IO庫,但我認爲這將是值得的,以顯示如何在標準Java 8.這是最簡單的形式來完成:

    public void removeLine(String lineContent) throws IOException 
    { 
        File file = new File("myFile.txt"); 
        List<String> out = Files.lines(file.toPath()) 
             .filter(line -> !line.contains(lineContent)) 
             .collect(Collectors.toList()); 
        Files.write(file.toPath(), out, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); 
    } 
    

    我認爲有ISN這裏沒有太多的解釋,基本上Files.lines得到Stream<String>的文件行,filter拿出我們不想要的行,然後collect把新文件的所有行放入List。然後,我們使用附加選項TRUNCATE在現有文件頂部的Files.write上編寫列表,以替換文件的舊內容。

    當然,這種方法將每一行加載到內存中都是不利的,因爲它們在被寫回前都被存儲到List中。如果我們想幹脆不保存修改,我們就需要通過流使用某種形式的OutputStream每一個新的行寫入一個文件,因爲它傳遞,就像這樣:

    public void removeLine(String lineContent) throws IOException 
    { 
        File file = new File("myFile.txt"); 
        File temp = new File("_temp_"); 
        PrintWriter out = new PrintWriter(new FileWriter(temp)); 
        Files.lines(file.toPath()) 
         .filter(line -> !line.contains(lineContent)) 
         .forEach(out::println); 
        out.flush(); 
        out.close(); 
        temp.renameTo(file); 
    } 
    

    沒有太多在這被改變例。基本上,我們不使用collect來將文件內容收集到內存中,而是使用forEach,以使通過filter的每一行都被髮送到PrintWriter,以便立即寫入到文件中而不存儲。我們必須將它保存到一個臨時文件中,因爲我們無法同時覆蓋現有文件,因爲我們仍然在讀取它,所以最後我們重命名臨時文件以替換現有文件。

    相關問題