[英]Remove word after line from txt file is read
我有這段代碼用於從文件中讀取行並將其插入 Postgre:
try {
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader(
"C:\\in_progress\\test.txt"));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
Thread.sleep(100);
Optional<ProcessedWords> isFound = processedWordsService.findByKeyword(line);
if(!isFound.isPresent()){
ProcessedWords obj = ProcessedWords.builder()
.keyword(line)
.createdAt(LocalDateTime.now())
.build();
processedWordsService.save(obj);
}
// read next line
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
catch (Exception e) {
e.printStackTrace();
}
將行插入 SQL 數據庫后,如何從文件中刪除一行?
以供參考
import java.io.*;
public class RemoveLinesFromAfterProcessed {
public static void main(String[] args) throws Exception {
String fileName = "TestFile.txt";
String tempFileName = "tempFile";
File mainFile = new File(fileName);
File tempFile = new File(tempFileName);
try (BufferedReader br = new BufferedReader(new FileReader(mainFile));
PrintWriter pw = new PrintWriter(new FileWriter(tempFile))
) {
String line;
while ((line = br.readLine()) != null) {
if (toProcess(line)) { // #1
// process the code and add it to DB
// ignore the line (i.e, not add to temp file)
} else {
// add to temp file.
pw.write(line + "\n"); // #2
}
}
} catch (Exception e) {
e.printStackTrace();
}
// delete the old file
boolean hasDeleted = mainFile.delete(); // #3
if (!hasDeleted) {
throw new Exception("Can't delete file!");
}
boolean hasRenamed = tempFile.renameTo(mainFile); // #4
if (!hasRenamed) {
throw new Exception("Can't rename file!");
}
System.out.println("Done!");
}
private static boolean toProcess(String line) {
// any condition
// sample condition for example
return line.contains("aa");
}
}
閱讀文件。
1:決定是刪除還是保留該行的條件。
2:將不想刪除的行寫入臨時文件。
3:刪除原文件。
4:將臨時文件重命名為原始文件名。
基本思想與@Shiva Rahul 在回答中所說的相同。
但是另一種方法是,將所有要刪除的行號存儲在一個list
。 在您擁有要刪除的所有必需的行號后,您可以使用LineNumberReader
檢查和復制您的主文件。
大多數情況下,我在批量插入中使用了這種技術,我不確定有多少行可能有一個特定的文件,加上在刪除行之前必須進行大量處理。 它可能不適合您的情況,如果有人碰到此線程,請在此處發布建議。
private void deleteLines(String inputFilePath,String outputDirectory,List<Integer> lineNumbers) throws IOException{
File tempFile = new File("temp.txt");
File inputFile = new File(inputFilePath);
// using LineNumberReader we can fetch the line numbers of each line
LineNumberReader lineReader = new LineNumberReader(new FileReader(inputFile));
//writter for writing the lines into new file
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(tempFile));
String currentLine;
while((currentLine = lineReader.readLine()) != null){
//if current line number is present in removeList then put empty line in new file
if(lineNumbers.contains(lineReader.getLineNumber())){
currentLine="";
}
bufferedWriter.write(currentLine + System.getProperty("line.separator"));
}
//closing statements
bufferedWriter.close();
lineReader.close();
//delete the main file and rename the tempfile to original file Name
boolean delete = inputFile.delete();
//boolean b = tempFile.renameTo(inputFile); // use this to save the temp file in same directory;
boolean b = tempFile.renameTo(new File(outputDirectory+inputFile.getName()));
}
要使用此功能,您只需收集所有需要的行號。 inputFilePath
是源文件的路徑,而outputDirectory
是我要在處理后存儲文件的位置。
當前代碼的問題:
findByKeyword()
調用,准備數據並將其分發到數據庫中。 它幾乎無法徹底測試,並且很難維護。Exception
類型 - 您的代碼應該只捕獲 thou 異常,這些異常或多或少是預期的,並且對於如何處理它們有明確的方案。 但不要捕獲所有異常。將行插入 SQL 數據庫后,如何從文件中刪除一行?
從字面上看,不可能從文件中刪除一行。 您可以覆蓋文件的內容或將其替換為另一個文件。
我的建議是將數據歸檔到內存中,對其進行處理,然后將應該保留的行寫入同一個文件中(即覆蓋文件內容)。
您可以爭辯說該文件很大,將其轉儲到內存中會導致OutOfMemoryError
。 您想從文件中讀取一行,以某種方式對其進行處理,然后將處理后的數據存儲到數據庫中,然后將該行寫入文件中......這樣一切都逐行完成,所有操作一次完成單行,因此所有代碼都擠在一種方法中。 我希望情況並非如此,否則這是一個明顯的XY-problem
。
首先,文件系統不是一種可靠的數據存儲方式,而且速度不是很快。 如果文件很大,那么讀取和寫入它將花費大量時間,並且只是為了使用少量信息而完成它,那么這種方法是錯誤的 - 這些信息應該以不同的方式存儲和構造(即考慮放入數據庫),以便可以檢索所需的數據,並且刪除不再需要的條目不會有問題。
但是如果文件很精簡,並且不包含關鍵數據。 那么它完全沒問題,我會繼續假設它是這種情況。
總體方法是根據文件內容生成一個映射Map<String, Optional<ProcessedWords>>
,處理非空的可選項並准備一個行列表來覆蓋之前的文件內容。
下面的代碼基於 NIO2 文件系統 API。
public void readProcessAndRemove(ProcessedWordsService service, Path path) {
Map<String, Optional<ProcessedWords>> result;
try (var lines = Files.lines(path)) {
result = processLines(service, lines);
} catch (IOException e) {
result = Collections.emptyMap();
logger.log();
e.printStackTrace();
}
List<String> linesToRetain = prepareAndSave(service, result);
writeToFile(linesToRetain, path);
}
處理來自文件的行流返回Files.lines()
:
private static Map<String, Optional<ProcessedWords>> processLines(ProcessedWordsService service,
Stream<String> lines) {
return lines.collect(Collectors.toMap(
Function.identity(),
service::findByKeyword
));
}
保存findByKeyword()
返回空選項的單詞:
private static List<String> prepareAndSave(ProcessedWordsService service,
Map<String, Optional<ProcessedWords>> wordByLine) {
wordByLine.forEach((k, v) -> {
if (v.isEmpty()) saveWord(service, k);
});
return getLinesToRetain(wordByLine);
}
private static void saveWord(ProcessedWordsService service, String line) {
ProcessedWords obj = ProcessedWords.builder()
.keyword(line)
.createdAt(LocalDateTime.now())
.build();
service.save(obj);
}
生成要保留的行列表:
private static List<String> getLinesToRetain(Map<String, Optional<ProcessedWords>> wordByLine) {
return wordByLine.entrySet().stream()
.filter(entry -> entry.getValue().isPresent())
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
使用Files.write()
覆蓋文件內容。 注意:由於沒有為可變參數OpenOption
提供任何參數,因此該調用將被視為存在CREATE
、 TRUNCATE_EXISTING
和WRITE
選項。
private static void writeToFile(List<String> lines, Path path) {
try {
Files.write(path, lines);
} catch (IOException e) {
logger.log();
e.printStackTrace();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.