代码之家  ›  专栏  ›  技术社区  ›  Narek

在文件中查找一行并删除它

  •  53
  • Narek  · 技术社区  · 16 年前

    我正在寻找一个小代码片段,它将在文件中找到一行并删除该行(不是内容,而是行),但找不到。例如,我在一个文件中有:

    MyFiel.TXT :

    aaa
    bbb
    ccc
    ddd
    

    需要具有这样的功能: public void removeLine(String lineContent) 如果我通过 removeLine("bbb") ,我得到这样的文件:

    myfile.txt文件:

    aaa
    ccc
    ddd
    
    15 回复  |  直到 6 年前
        1
  •  73
  •   leo    10 年前

    这个解决方案可能不是最佳的或漂亮的,但它是有效的。它一行一行地读入输入文件,将每一行写到一个临时输出文件中。每当它遇到与您要查找的内容相匹配的行时,它就会跳过编写该行。然后它重命名输出文件。我在示例中省略了错误处理、关闭读写器等。我还假设您要查找的行中没有前导空格或尾随空格。根据需要更改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);
    
        2
  •  24
  •   TheLittleNaruto JAAD    11 年前
        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
  •  20
  •   Adam Batkin    16 年前

    您希望执行以下操作:

    • 打开旧文件进行读取
    • 打开新(临时)文件进行写入
    • 迭代旧文件中的行(可能使用 BufferedReader )
      • 对于每一行,检查它是否与您应该删除的内容匹配
      • 如果匹配,什么都不做
      • 如果不匹配,则将其写入临时文件
    • 完成后,关闭两个文件
    • 删除旧文件
    • 将临时文件重命名为原始文件的名称

    (我不会写实际的代码,因为这看起来像是家庭作业,但请随意将其他问题发布到您遇到问题的特定位置)

        4
  •  15
  •   Zeze    10 年前

    使用Apache公钥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);
    
        5
  •  9
  •   Tim M.    8 年前

    所以,每当我听到有人说他们想过滤掉文本,我立刻想去 Streams (主要是因为有一个方法 filter 你需要的过滤器。另一个答案提到使用 Stream 使用Apache CuMon 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);
    }
    

    我认为基本上没有太多的解释 Files.lines 得到一个 Stream<String> 在文件的行中, 滤波器 把我们不想要的台词删掉,然后 collect 将新文件的所有行放入 List . 然后我们将列表写在现有文件的顶部, Files.write ,使用附加选项 TRUNCATE 因此文件的旧内容被替换。

    当然,这种方法的缺点是将每一行加载到内存中,因为它们都存储在 在被写出来之前。如果我们只想修改而不存储,我们需要使用某种形式的 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);
    }
    

    在这个例子中,变化不大。基本上,而不是使用 收集 为了将文件内容收集到内存中,我们使用 forEach 使每一行通过 滤波器 发送到 PrintWriter 立即写入文件而不存储。我们必须将其保存到一个临时文件中,因为我们无法在读取现有文件的同时覆盖现有文件,因此在最后,我们重命名临时文件以替换现有文件。

        6
  •  2
  •   seyed ali ziaei    8 年前
        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();
        }
    
        7
  •  2
  •   Kröw    7 年前

    干得好。此解决方案使用 DataInputStream 扫描要替换的字符串的位置并使用 FileChannel 替换该位置的文本。它只替换它找到的字符串的第一个匹配项。这个解决方案 不将整个文件的副本存储在某个位置 ,(RAM或临时文件),它只编辑找到的文件部分。

    public static long scanForString(String text, File file) throws IOException {
        if (text.isEmpty())
            return file.exists() ? 0 : -1;
        // First of all, get a byte array off of this string:
        byte[] bytes = text.getBytes(/* StandardCharsets.your_charset */);
    
        // Next, search the file for the byte array.
        try (DataInputStream dis = new DataInputStream(new FileInputStream(file))) {
    
            List<Integer> matches = new LinkedList<>();
    
            for (long pos = 0; pos < file.length(); pos++) {
                byte bite = dis.readByte();
    
                for (int i = 0; i < matches.size(); i++) {
                    Integer m = matches.get(i);
                    if (bytes[m] != bite)
                        matches.remove(i--);
                    else if (++m == bytes.length)
                        return pos - m + 1;
                    else
                        matches.set(i, m);
                }
    
                if (bytes[0] == bite)
                    matches.add(1);
            }
        }
        return -1;
    }
    
    public static void replaceText(String text, String replacement, File file) throws IOException {
        // Open a FileChannel with writing ability. You don't really need the read
        // ability for this specific case, but there it is in case you need it for
        // something else.
        try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.WRITE, StandardOpenOption.READ)) {
            long scanForString = scanForString(text, file);
            if (scanForString == -1) {
                System.out.println("String not found.");
                return;
            }
            channel.position(scanForString);
            channel.write(ByteBuffer.wrap(replacement.getBytes(/* StandardCharsets.your_charset */)));
        }
    }
    

    例子

    输入: ABCDEFGHIJKLMNOPQRSTUVWXYZ

    方法调用:

    replaceText("QRS", "000", new File("path/to/file");
    

    结果文件: ABCDEFGHIJKLMNOP000TUVWXYZ

        8
  •  1
  •   Sireesh Yarlagadda    10 年前

    这是完整的课程。在下面的文件中,“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);
        }
    
    }
    
        9
  •  0
  •   Altair    11 年前
    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!");
            }
        }
    
    }
    
        10
  •  0
  •   iCrazybest    10 年前
    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/

        11
  •  0
  •   BullyWiiPlaza    10 年前

    此解决方案需要 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();
    }
    
        12
  •  0
  •   Grinish Nepal    9 年前

    我重构了narek必须(根据我的说法)创建的解决方案,它的代码更加高效、易于理解。我使用了嵌入式自动资源管理,Java中的一个新特性,并使用了一个扫描器类,根据我更容易理解和使用。

    下面是带编辑注释的代码:

    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");
            }
    
        }
    
    
    
    }
    
        13
  •  0
  •   AMA    8 年前

    试试这个:

    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();
    }
    
        14
  •  0
  •   Enemyfish    7 年前

    老问题,但一个简单的方法是:

    • 迭代文件,将每一行添加到新的数组列表中
    • 遍历数组,找到匹配的字符串,然后调用remove方法。
    • 再次遍历数组,将每一行打印到文件中,追加的布尔值应该为false,这基本上替换了文件。
        15
  •  0
  •   Kröw    6 年前

    此解决方案使用 RandomAccessFile 只缓存要删除的字符串后面的文件部分。它扫描直到找到 String 您要删除。然后它复制所有数据 之后 找到的字符串,然后将其写入找到的字符串以及之后的所有内容。最后,它截断文件大小以删除多余的数据。

    public static long scanForString(String text, File file) throws IOException {
        if (text.isEmpty())
            return file.exists() ? 0 : -1;
        // First of all, get a byte array off of this string:
        byte[] bytes = text.getBytes(/* StandardCharsets.your_charset */);
    
        // Next, search the file for the byte array.
        try (DataInputStream dis = new DataInputStream(new FileInputStream(file))) {
    
            List<Integer> matches = new LinkedList<>();
    
            for (long pos = 0; pos < file.length(); pos++) {
                byte bite = dis.readByte();
    
                for (int i = 0; i < matches.size(); i++) {
                    Integer m = matches.get(i);
                    if (bytes[m] != bite)
                        matches.remove(i--);
                    else if (++m == bytes.length)
                        return pos - m + 1;
                    else
                        matches.set(i, m);
                }
    
                if (bytes[0] == bite)
                    matches.add(1);
            }
        }
        return -1;
    }
    
    public static void remove(String text, File file) throws IOException {
        try (RandomAccessFile rafile = new RandomAccessFile(file, "rw");) {
            long scanForString = scanForString(text, file);
            if (scanForString == -1) {
                System.out.println("String not found.");
                return;
            }
            long remainderStartPos = scanForString + text.getBytes().length;
            rafile.seek(remainderStartPos);
            int remainderSize = (int) (rafile.length() - rafile.getFilePointer());
            byte[] bytes = new byte[remainderSize];
            rafile.read(bytes);
            rafile.seek(scanForString);
    
            rafile.write(bytes);
            rafile.setLength(rafile.length() - (text.length()));
        }
    }
    

    用法:

    文件内容: ABCDEFGHIJKLMNOPQRSTUVWXYZ

    方法调用: remove("ABC", new File("Drive:/Path/File.extension"));

    结果内容: DEFGHIJKLMNOPQRSTUVWXYZ

    此解决方案可以很容易地修改为使用特定的 cacheSize ,如果记忆是一个问题。这只需要对文件的其余部分进行迭代,以不断替换大小的部分, 高速缓存 . 无论如何,此解决方案通常比缓存 整个的 文件在内存中,或复制到临时目录等。

    推荐文章