Подтвердить что ты не робот

Найдите строку в файле и удалите ее

Я ищу небольшой фрагмент кода, который найдет строку в файле и удалит эту строку (а не контент, но строка), но не смог найти. Так, например, у меня есть следующий файл:

Myfile.txt

aaa
bbb
ccc
ddd

Нужно иметь такую ​​функцию: public void removeLine(String lineContent), и если я пройду removeLine("bbb"), я получаю файл следующим образом:

Myfile.txt:

aaa
ccc
ddd
4b9b3361

Ответ 1

Это решение может быть не оптимальным или красивым, но оно работает. Он читает во входном файле строку за строкой, записывая каждую строку во временный выходной файл. Всякий раз, когда он встречает строку, которая соответствует тому, что вы ищете, она пропускает запись этого. Затем он переименовывает выходной файл. Я пропустил обработку ошибок, закрытие читателей/писателей и т.д. Из примера. Я также предполагаю, что в строке, которую вы ищете, нет ведущего или конечного пробела. Измените код вокруг 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

    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

Вы хотите сделать что-то вроде следующего:

  • Откройте старый файл для чтения
  • Откройте новый (временный) файл для записи
  • Итерации по строкам в старом файле (возможно, с помощью BufferedReader)
    • Для каждой строки проверьте, соответствует ли она тому, что вы должны удалить.
    • Если он соответствует, ничего не делать
    • Если он не совпадает, напишите его во временный файл
  • По завершении закройте оба файла
  • Удалить старый файл
  • Переименуйте временный файл в имя исходного файла

(Я не буду писать фактический код, так как это выглядит как домашнее задание, но не стесняйтесь публиковать другие вопросы о конкретных битах, с которыми у вас возникают проблемы)

Ответ 4

Используя 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);

Ответ 5

Поэтому, когда я слышу, как кто-то упоминает, что он хочет отфильтровать текст, я сразу же думаю о том, чтобы перейти к Streams (главным образом потому, что есть метод с именем filter который фильтрует именно так, как вам нужно). В другом ответе упоминается использование Stream с библиотекой 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> строк файла, filter Files.lines строки, которые нам не нужны, а затем collect помещает все строки нового файл в List. Затем мы записываем список поверх существующего файла с помощью Files.write, используя дополнительную опцию TRUNCATE чтобы заменить старое содержимое файла.

Конечно, у этого подхода есть обратная сторона: загрузка каждой строки в память, так как все они сохраняются в 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 для немедленной записи в файл и не сохранялась. Мы должны сохранить его во временный файл, потому что мы не можем перезаписать существующий файл в то же время, когда мы все еще читаем из него, поэтому в конце мы переименовываем временный файл, чтобы заменить существующий файл.

Ответ 6

Ну вот. Это решение использует 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

Ответ 7

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

Ответ 8

Вот полный класс. В приведенном ниже файле "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

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

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

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

Ответ 11

Это решение требует добавления в путь сборки Apo 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

Я реорганизовал решение, которое Нарек должен был создать (по мне) несколько более эффективным и понятным для понимания кодом. Я использовал встроенное автоматическое управление ресурсами, недавнюю функцию 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");
        }

    }



}

Ответ 13

Попробуйте следующее:

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

Старый вопрос, но простой способ заключается в следующем:

  • Итерация по файлу, добавление каждой строки в новый список массивов
  • переберите массив, найдите подходящую строку, затем вызовите метод удаления.
  • повторять массив снова, печатая каждую строку в файл, логическое значение для append должно быть false, что в основном заменяет файл

Ответ 15

Это решение использует 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, если проблема cacheSize памятью. Это будет просто включать в себя итерации по остальной части файла, чтобы постоянно заменять части размера, cacheSize. В любом случае, это решение, как правило, намного лучше, чем кэширование всего файла в памяти или копирование его во временный каталог и т.д.

Ответ 16

Это решение читает строку входного файла построчно, записывая каждую строку в переменную 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();
}