파일에서 줄을 찾아 제거
파일에서 한 줄을 찾고 해당 줄 (내용이 아니라 줄)을 제거하지만 찾을 수없는 작은 코드 조각을 찾고 있습니다. 예를 들어 다음 파일에 있습니다.
myFile.txt :
aaa
bbb
ccc
ddd
다음과 같은 기능이 필요합니다.을 public void removeLine(String lineContent)
통과 removeLine("bbb")
하면 다음과 같은 파일이 생성됩니다.
myFile.txt :
aaa
ccc
ddd
이 솔루션은 최적이거나 예쁘지 않을 수 있지만 작동합니다. 입력 파일을 한 줄씩 읽고 각 줄을 임시 출력 파일에 씁니다. 찾고있는 내용과 일치하는 줄을 발견 할 때마다 해당 줄을 작성하지 않습니다. 그런 다음 출력 파일의 이름을 바꿉니다. 예제에서 오류 처리, 읽기 / 쓰기 닫기 등을 생략했습니다. 또한 찾고있는 줄에 선행 또는 후행 공백이 없다고 가정합니다. 일치하는 항목을 찾을 수 있도록 필요에 따라 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();
}
}
이것은 인터넷에서 찾았습니다.
다음과 같은 작업을 원합니다.
- 읽기 위해 이전 파일을 엽니 다.
- 쓰기를 위해 새 (임시) 파일 열기
- 이전 파일의 행을 반복합니다 (아마 BufferedReader 사용 ).
- 각 줄에 대해 제거하려는 항목과 일치하는지 확인하십시오.
- 일치하면 아무것도하지 마십시오
- 일치하지 않으면 임시 파일에 쓰십시오.
- 완료되면 두 파일을 모두 닫습니다.
- 이전 파일 삭제
- 임시 파일의 이름을 원본 파일의 이름으로 바꿉니다.
(실제 코드를 작성하지는 않겠습니다. 숙제처럼 보이지만 문제가있는 특정 부분에 대해 다른 질문을 자유롭게 게시 할 수 있습니다.)
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
필요한대로 정확히 필터링 하는 메서드가 있기 때문입니다 ). 또 다른 대답 Stream
은 Apache commons-io 라이브러리에서 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!");
}
}
}
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/
이 솔루션을 사용하려면 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();
}
나는 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");
}
}
}
이 시도:
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();
}
오래된 질문이지만 쉬운 방법은 다음과 같습니다.
- 파일을 반복하여 새 배열 목록에 각 줄을 추가합니다.
- 배열을 반복하고 일치하는 문자열을 찾은 다음 remove 메서드를 호출합니다.
- 배열을 다시 반복하여 각 행을 파일에 인쇄하고 추가에 대한 부울은 기본적으로 파일을 대체하는 false 여야합니다.
이 솔루션은를 사용 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
. 그럼에도 불구하고이 솔루션은 일반적으로 전체 파일을 메모리에 캐싱 하거나 임시 디렉토리에 복사 하는 것보다 훨씬 낫습니다 .
이 솔루션은 입력 파일을 한 줄씩 읽고 각 줄을 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();
}
참고 URL : https://stackoverflow.com/questions/1377279/find-a-line-in-a-file-and-remove-it
'development' 카테고리의 다른 글
IIS : 모든 요청을 한 페이지로 리디렉션 하시겠습니까? (0) | 2020.12.10 |
---|---|
공백이있는 경로를 매개 변수로 bat 파일에 전달 (0) | 2020.12.10 |
Parcelable을 비 정렬 화하는 문제 (0) | 2020.12.10 |
쿠키의 만료 시간을 얻는 방법 (0) | 2020.12.10 |
CakePHP 용으로 생성 된 기존 MySQL 데이터베이스에서 ER 다이어그램 생성 (0) | 2020.12.10 |