it-swarm.com.de

Suchen Sie eine Zeile in einer Datei und entfernen Sie sie

Ich suche nach einem kleinen Code-Snippet, der eine Zeile in Datei findet und diese Zeile entfernt (nicht Inhalt, sondern Zeile), aber nicht finden konnte. Also zum Beispiel habe ich in einer Datei folgendes:

myFile.txt :

aaa
bbb
ccc
ddd

Ich brauche eine Funktion wie diese: public void removeLine(String lineContent), und wenn ich removeLine("bbb") übergeben habe, bekomme ich eine Datei wie folgt:

myFile.txt:

aaa
ccc
ddd
53
Narek

Diese Lösung ist möglicherweise nicht optimal oder hübsch, funktioniert aber. Es liest Zeile für Zeile eine Eingabedatei ein und schreibt jede Zeile in eine temporäre Ausgabedatei. Wenn Sie auf eine Zeile stoßen, die Ihren Wünschen entspricht, wird das Schreiben dieser Zeile übersprungen. Die Ausgabedatei wird dann umbenannt. Ich habe die Fehlerbehandlung, das Schließen von Lesern/Schreibern usw. aus dem Beispiel weggelassen. Ich gehe auch davon aus, dass in der Zeile, nach der Sie suchen, keine führenden oder nachgestellten Leerzeichen vorhanden sind. Ändern Sie den Code um trim () herum, um eine Übereinstimmung zu finden.

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

Das habe ich im Internet gefunden.

24
Narek

Sie möchten etwas wie das Folgende machen:

  • Öffnen Sie die alte Datei zum Lesen
  • Öffnen Sie eine neue (temporäre) Datei zum Schreiben
  • Iterieren Sie über die Zeilen in der alten Datei (wahrscheinlich mit einem BufferedReader )
    • Prüfen Sie für jede Zeile, ob sie dem entspricht, was Sie entfernen möchten
    • Wenn es passt, tu nichts
    • Wenn es nicht passt, schreiben Sie es in die temporäre Datei
  • Wenn Sie fertig sind, schließen Sie beide Dateien
  • Löschen Sie die alte Datei
  • Benennen Sie die temporäre Datei in den Namen der Originaldatei um

(Ich schreibe nicht den eigentlichen Code, da dies wie eine Hausaufgabe aussieht, aber Sie können gerne andere Fragen zu bestimmten Teilen posten, mit denen Sie Probleme haben.) 

20
Adam Batkin

Mit Apache commons-io und Java 8 können Sie verwenden

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

Immer wenn ich jemanden sagen höre, dass er Text herausfiltern möchte, denke ich sofort zu Streams (hauptsächlich weil es eine Methode namens filter gibt, die genau so filtert, wie Sie es brauchen). In einer anderen Antwort wird Streams mit der Apache commons-io-Bibliothek erwähnt, aber ich dachte, es lohnt sich zu zeigen, wie dies in Standard-Java 8 möglich ist. Hier ist die einfachste Form:

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

Ich denke, da gibt es nicht zu viel zu erklären, im Grunde bekommt Files.lines einen Stream<String> der Zeilen der Datei, filter nimmt die Zeilen heraus, die wir nicht wollen, und collect setzt alle Zeilen der neuen Datei in ein List. Dann schreiben wir die Liste mit Files.write über die vorhandene Datei und verwenden dazu die zusätzliche Option TRUNCATE, damit der alte Inhalt der Datei ersetzt wird.

Natürlich hat dieser Ansatz den Nachteil, dass jede Zeile in den Speicher geladen wird, da sie alle in einer List gespeichert werden, bevor sie wieder herausgeschrieben werden. Wenn Sie einfach ohne Speichern ändern möchten, müssen Sie eine Form von OutputStream verwenden, um jede neue Zeile in eine Datei zu schreiben, während sie den Stream durchläuft.

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

In diesem Beispiel wurde nicht viel geändert. Anstatt collect zum Sammeln des Dateiinhalts im Speicher zu verwenden, verwenden wir forEach, sodass jede Zeile, die durch filter gelangt, an PrintWriter gesendet wird, um sofort in die Datei geschrieben und nicht gespeichert zu werden. Wir müssen sie in einer temporären Datei speichern, da wir die vorhandene Datei nicht gleichzeitig überschreiben können, während wir noch aus ihr lesen. Deshalb benennen wir die temporäre Datei am Ende um, um die vorhandene Datei zu ersetzen.

9
Tim M.

Bitte schön. Bei dieser Lösung wird mit DataInputStream nach der Position der Zeichenfolge gesucht, die ersetzt werden soll, und mit FileChannel wird der Text genau an dieser Position ersetzt. Sie ersetzt nur das erste Vorkommen der gefundenen Zeichenfolge. Diese Lösung speichert keine Kopie der gesamten Datei irgendwo (entweder RAM oder eine temporäre Datei), sondern bearbeitet nur den gefundenen Teil der Datei.

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 */)));
    }
}

Beispiel

Eingabe: ABCDEFGHIJKLMNOPQRSTUVWXYZ

Methodenaufruf:

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

Ergebnisdatei: ABCDEFGHIJKLMNOP000TUVWXYZ

2
Kröw
    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();
    }
2
seyed ali ziaei

Hier ist die komplette Klasse. In der folgenden Datei bezieht sich "somelocation" auf den tatsächlichen Pfad der Datei.

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

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

}
0
Altair

Ich habe die Lösung überarbeitet, die Narek (meiner Meinung nach) für einen etwas effizienteren und leicht verständlichen Code erstellen musste. Ich habe Embedded Automatic Resource Management, ein aktuelles Feature in Java, und eine Scanner-Klasse verwendet, die meiner Meinung nach einfacher zu verstehen und zu verwenden ist. 

Hier ist der Code mit bearbeiteten Kommentaren:

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

Alte Frage, aber ein einfacher Weg ist:

  • Durchlaufen Sie die Datei und fügen Sie jede Zeile einer neuen Array-Liste hinzu
  • iterieren Sie durch das Array, suchen Sie nach übereinstimmendem String und rufen Sie dann die remove-Methode auf.
  • iterieren Sie erneut durch das Array, und drucken Sie jede Zeile in die Datei. Boolean für Append sollte false sein, wodurch die Datei grundsätzlich ersetzt wird
0
Enemyfish
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-von-a-text-file/

0
iCrazybest

Diese Lösung verwendet RandomAccessFile, um nur den Teil der Datei zwischenzuspeichern, der auf den zu entfernenden String folgt. Es scannt, bis es das String findet, das Sie entfernen möchten. Dann kopiert es alle Daten after des gefundenen Strings, schreibt sie dann über den gefundenen String und alles danach. Zuletzt wird die Dateigröße abgeschnitten, um die überschüssigen Daten zu entfernen.

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

Verwendungszweck:

Dateiinhalt: ABCDEFGHIJKLMNOPQRSTUVWXYZ

Methodenaufruf: remove("ABC", new File("Drive:/Path/File.extension"));

Resultierende Inhalte: DEFGHIJKLMNOPQRSTUVWXYZ

Diese Lösung kann leicht geändert werden, um sie mit einem bestimmten, vorgebbaren cacheSize zu entfernen, wenn Speicher ein Problem ist. Dies würde lediglich das Durchlaufen des Restes der Datei erfordern, um Teile der Größe cacheSize kontinuierlich zu ersetzen. Unabhängig davon ist diese Lösung im Allgemeinen viel besser als das Speichern einer gesamter -Datei im Speicher oder das Kopieren in ein temporäres Verzeichnis usw.

0
Kröw

Versuche dies:

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
ahmad adawi

Diese Lösung liest eine Eingabedatei zeilenweise ein und schreibt jede Zeile in eine StringBuilder-Variable. Immer wenn es auf eine Zeile stößt, die mit dem übereinstimmt, wonach Sie suchen, wird diese Zeile übersprungen. Anschließend wird der Dateiinhalt gelöscht und der Inhalt der StringBuilder-Variablen abgelegt.

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

Für diese Lösung muss die Bibliothek Apache Commons IO zum Buildpfad hinzugefügt werden. Es liest die gesamte Datei und schreibt jede Zeile zurück, jedoch nur, wenn der Suchbegriff nicht enthalten ist.

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
BullyWiiPlaza