ファイル内の行を見つけ、その行(コンテンツではなく行)を削除するが、見つけることができなかった小さなコードスニペットを探しています。したがって、たとえば、私は次のファイルにあります:
myFile.txt:
aaa
bbb
ccc
ddd
次のような関数が必要です:public void removeLine(String lineContent)
、_removeLine("bbb")
を渡すと、次のようなファイルが得られます:
myFile.txt:
aaa
ccc
ddd
このソリューションは最適でもきれいでもないかもしれませんが、機能します。入力ファイルを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);
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();
}
}
これはインターネットで見つけました。
次のようなことをしたい場合:
(これは宿題のように見えるため、実際のコードは書きませんが、問題がある特定の部分については他の質問を投稿してください)
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);
だから、誰かがテキストをフィルタリングしたいと言っているのを聞くたびに、すぐに Streams に行くと思います(主に、必要に応じて正確にフィルタリングするfilter
というメソッドがあるからです)。別の回答では、Apache commons-ioライブラリでStream
sを使用することについて言及していますが、これを標準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
に送信され、すぐにファイルに書き込まれ、保存されません。一時ファイルに保存する必要があります。既存のファイルを読み取り中に同時に上書きすることはできないため、最後に、一時ファイルの名前を変更して既存のファイルを置き換えます。
どうぞ。このソリューションでは、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
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();
}
これが完全なクラスです。以下のファイルの「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);
}
}
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!");
}
}
}
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");
}
}
}
古い質問ですが、簡単な方法は次のとおりです。
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");
}
}
このソリューションでは、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
を継続的に置き換えるだけです。とにかく、このソリューションは一般的に、メモリに全体ファイルをキャッシュしたり、一時ディレクトリにコピーしたりするよりもはるかに優れています。
これを試して:
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();
}
このソリューションは、入力ファイルを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();
}
このソリューションでは、ビルドパスに 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();
}