69

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

我的文件.txt

aaa
bbb
ccc
ddd

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

我的文件.txt:

aaa
ccc
ddd
4

17 回答 17

94

这个解决方案可能不是最佳的或漂亮的,但它确实有效。它逐行读取输入文件,将每一行写入临时输出文件。每当遇到与您要查找的内容匹配的行时,它都会跳过写出该行。然后它重命名输出文件。我在示例中省略了错误处理、关闭读取器/写入器等。我还假设您要查找的行中没有前导或尾随空格。根据需要更改 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);
于 2009-09-04T05:08:46.167 回答
26
    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();
    }
  }

这是我在互联网上找到的。

于 2009-09-04T19:13:21.710 回答
21

您想要执行以下操作:

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

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

于 2009-09-04T05:09:03.280 回答
19

使用 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);
于 2015-02-22T13:19:52.457 回答
19

因此,每当我听到有人提到他们想要过滤掉文本时,我立即想到去Streams(主要是因为有一种方法叫做filter可以完全按照您的需要进行过滤)。另一个答案提到将Streams 与 Apache commons-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>文件的 a 行,filter取出我们不想要的行,然后collect将新文件的所有行放入List. Files.write然后,我们使用附加选项将列表写入现有文件的顶部,TRUNCATE以便替换文件的旧内容。

当然,这种方法的缺点是将每一行都加载到内存中,因为它们List在被写回之前都被存储到 a 中。如果我们想简单地修改而不存储,我们将需要使用某种形式在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要立即写入文件而不是存储的行。我们必须将它保存到一个临时文件中,因为我们不能同时覆盖现有文件,因为我们仍在读取它,所以最后,我们重命名临时文件以替换现有文件。

于 2017-08-20T16:06:54.893 回答
5
    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();
    }
于 2017-04-07T13:46:26.450 回答
4

干得好。此解决方案使用 aDataInputStream扫描要替换的字符串的位置,并使用 aFileChannel替换该确切位置的文本。它只替换它找到的字符串的第一次出现。此解决方案不会将整个文件的副本存储在某处(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

于 2018-07-05T12:26:23.850 回答
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);
    }

}
于 2015-01-31T03:54:02.213 回答
1

此解决方案逐行读取输入文件,将每一行写入 StringBuilder 变量。每当遇到与您要查找的内容匹配的行时,它都会跳过写出该行。然后它删除文件内容并放入 StringBuilder 变量内容。

public void removeLineFromFile(String lineToRemove, File f) throws FileNotFoundException, IOException{
    //Reading File Content and storing it to a StringBuilder variable ( skips lineToRemove)
    StringBuilder sb = new StringBuilder();
    try (Scanner sc = new Scanner(f)) {
        String currentLine;
        while(sc.hasNext()){
            currentLine = sc.nextLine();
            if(currentLine.equals(lineToRemove)){
                continue; //skips lineToRemove
            }
            sb.append(currentLine).append("\n");
        }
    }
    //Delete File Content
    PrintWriter pw = new PrintWriter(f);
    pw.close();

    BufferedWriter writer = new BufferedWriter(new FileWriter(f, true));
    writer.append(sb.toString());
    writer.close();
}
于 2019-07-11T13:18:57.427 回答
1

使用 maven/gradle+groovy 的超级简单方法。

public void deleteConfig(String text) {
    File config = new File("/the/path/config.txt")
    def lines = config.readLines()
    lines.remove(text);
    config.write("")
    lines.each {line -> {
        config.append(line+"\n")
    }}
}
于 2021-10-11T02:47:38.817 回答
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!");
        }
    }

}
于 2014-09-12T14:31:31.530 回答
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/

于 2015-03-01T05:10:17.933 回答
0

此解决方案需要将Apache Commons IO 库添加到构建路径。它通过读取整个文件并写回每一行来工作,但前提是不包含搜索词。

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();
}
于 2015-04-27T12:22:28.997 回答
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");
        }

    }



}
于 2016-08-27T11:22:47.757 回答
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();
}
于 2017-03-28T11:04:11.893 回答
0

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

  • 遍历文件,将每一行添加到一个新的数组列表中
  • 遍历数组,找到匹配的字符串,然后调用remove方法。
  • 再次遍历数组,将每一行打印到文件中,追加的布尔值应该为假,这基本上替换了文件
于 2018-07-04T06:39:45.947 回答
0

此解决方案使用 aRandomAccessFile仅缓存要删除的字符串之后的文件部分。它会扫描直到找到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如果内存是一个问题,则可以轻松地修改此解决方案以删除特定的、可指定的 。这将只涉及迭代文件的其余部分以不断替换大小的部分,cacheSize. 无论如何,此解决方案通常比将整个文件缓存在内存中或将其复制到临时目录等要好得多。

于 2018-12-18T05:43:51.263 回答