web-dev-qa-db-ja.com

ファイル内の行を見つけて削除する

ファイル内の行を見つけ、その行(コンテンツではなく行)を削除するが、見つけることができなかった小さなコードスニペットを探しています。したがって、たとえば、私は次のファイルにあります:

myFile.txt

aaa
bbb
ccc
ddd

次のような関数が必要です:public void removeLine(String lineContent)、_removeLine("bbb")を渡すと、次のようなファイルが得られます:

myFile.txt:

aaa
ccc
ddd
58
Narek

このソリューションは最適でもきれいでもないかもしれませんが、機能します。入力ファイルを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);
77
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();
    }
  }

これはインターネットで見つけました。

24
Narek

次のようなことをしたい場合:

  • 古いファイルを読み取り用に開きます
  • 書き込み用に新しい(一時)ファイルを開く
  • 古いファイル内の行を反復処理します(おそらく BufferedReader )を使用します
    • 各行について、削除することになっているものと一致するかどうかを確認します
    • 一致する場合、何もしません
    • 一致しない場合は、一時ファイルに書き込みます
  • 完了したら、両方のファイルを閉じます
  • 古いファイルを削除する
  • 一時ファイルの名前を元のファイルの名前に変更します

(これは宿題のように見えるため、実際のコードは書きませんが、問題がある特定の部分については他の質問を投稿してください)

20
Adam Batkin

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);
16
Zeze

だから、誰かがテキストをフィルタリングしたいと言っているのを聞くたびに、すぐに Streams に行くと思います(主に、必要に応じて正確にフィルタリングするfilterというメソッドがあるからです)。別の回答では、Apache commons-ioライブラリでStreamsを使用することについて言及していますが、これを標準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は不要な行を取り出し、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に送信され、すぐにファイルに書き込まれ、保存されません。一時ファイルに保存する必要があります。既存のファイルを読み取り中に同時に上書きすることはできないため、最後に、一時ファイルの名前を変更して既存のファイルを置き換えます。

10
Tim M.

どうぞ。このソリューションでは、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

3
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

これが完全なクラスです。以下のファイルの「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);
    }

}
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

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

古い質問ですが、簡単な方法は次のとおりです。

  • ファイルを反復処理し、各行を新しい配列リストに追加します
  • 配列を反復処理し、一致する文字列を見つけてから、removeメソッドを呼び出します。
  • 再度配列を反復処理し、各行をファイルに出力します。追加のブール値はfalseである必要があり、基本的にファイルを置き換えます
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-from-a-text-file/

0
iCrazybest

このソリューションでは、RandomAccessFileを使用して、削除する文字列に続くファイルの部分のみをキャッシュします。削除するStringが見つかるまでスキャンします。次に、すべてのデータをコピーしますafter見つかった文字列、それから見つかった文字列に上書きします。最後に、ファイルサイズを切り捨てて余分なデータを削除します。

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を継続的に置き換えるだけです。とにかく、このソリューションは一般的に、メモリに全体ファイルをキャッシュしたり、一時ディレクトリにコピーしたりするよりもはるかに優れています。

0
Kröw

これを試して:

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

このソリューションは、入力ファイルを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();
}
0
Tahero

このソリューションでは、ビルドパスに 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
BullyWiiPlaza