读取txt文件的行后删除单词

发布于 2025-02-04 01:22:24 字数 1195 浏览 2 评论 0 原文

我有此代码,用于从文件中读取行并将其插入帖子中:

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数据库后从文件中删除一行?

I have this code which is used to read lines from a file and insert it into 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();
        }

How I can remove a line from the file after the line is inserted into SQL database?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

叶落知秋 2025-02-11 01:22:24

当前代码的问题:

  • 遵守单一责任原则。您的代码做太多的事情:从文件中读取,执行 findbykeyword()调用,准备数据并将其送出来存储在数据库中。几乎无法对其进行彻底的测试,并且很难维持。
  • 始终使用 a>在任何情况下都可以关闭您的recourses。
  • 请勿捕获常规异常类型 - 您的代码只能捕获thous例外,这或多或少是预期的,并且对于如何处理它们有一个明确的方案。但是不要捕获所有例外。

我如何从文件中删除一条线 将行插入SQL数据库之后?

从字面意义上讲,不可能从文件中删除一行。您可以覆盖文件的内容或用另一个文件替换。

我的建议是将数据归档,对其进行处理,然后写入应将其保留到同一文件中的行( ie替代文件内容)。

您可以争辩说该文件很大,将其转储到内存中会导致 OutofmemoryError 。而且您想从文件中读取一行,以某种方式对其进行处理,然后将处理的数据存储到数据库中,然后将行写入文件中...以便所有操作都是按行完成的因此,所有代码都以一种方法塞满了。我希望事实并非如此,因为否则它是一个清晰的 xy-problem

首先,文件系统不是存储数据的可靠均值,并且不是很快。如果文件庞大,那么阅读和写作将花费大量时间,并且它只是为了使用细小的信息而完成此方法,那么此方法是错误的 - 该信息应以不同的方式存储和结构化(即考虑将其放入DB),以便可以检索所需的数据,并且删除不再需要的条目没有问题。

但是,如果文件是精益的,并且不包含关键数据。然后完全可以,我将继续假设是这种情况。

总体方法是生成映射 map&lt;字符串,可选&lt; processedwords&gt;&gt; 基于文件内容,处理非空置选项并准备一条列表以覆盖先前的文件内容。

下面的代码基于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
    ));
}

保存 findbyKeykeyword()>的单词返回一个空的可选:

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.write.write.write.write () 注意: 由于varargs openoption 没有提供任何参数,此调用将被视为 create> create> create> create truncate_existing 写入选项。

private static void writeToFile(List<String> lines, Path path) {
    try {
        Files.write(path, lines);
    } catch (IOException e) {
        logger.log();
        e.printStackTrace();
    }
}

The issues with the current code:

  • Adhere to the Single responsibility principle. Your code is doing too many things: reads from a file, performs findByKeyword() call, prepares the data and hands it out to store in the database. It's hardly can be thoroughly tested, and it's very difficult to maintain.
  • Always use try-with-recourses to get your recourses closed at any circumstances.
  • Don't catch the general Exception type - your code should only catch thous exceptions, which are more or less expected and for which there's a clear scenario on how to handle them. But don't catch all the exceptions.

How I can remove a line from the file after the line is inserted into SQL database?

It is not possible to remove a line from a file in the literal sense. You can override the contents of the file or replace it with another file.

My advice would be to file data in memory, process it, and then write the lines which should be retained into the same file (i.e. override the file contents).

You can argue that the file is huge and dumping it into memory would result in an OutOfMemoryError. And you want to read a line from a file, process it somehow, then store the processed data into the database and then write the line into a file... So that everything is done line by line, all actions in one go for a single line, and as a consequence all the code is crammed in one method. I hope that's not the case because otherwise it's a clear XY-problem.

Firstly, File System isn't a reliable mean of storing data, and it's not very fast. If the file is massive, then reading and writing it will a take a considerable amount of time, and it's done just it in order to use a tinny bit of information then this approach is wrong - this information should be stored and structured differently (i.e. consider placing into a DB) so that it would be possible to retrieve the required data, and there would be no problem with removing entries that are no longer needed.

But if the file is lean, and it doesn't contain critical data. Then it's totally fine, I will proceed assuming that it's the case.

The overall approach is to generate a map Map<String, Optional<ProcessedWords>> based on the file contents, process the non-empty optionals and prepare a list of lines to override the previous file content.

The code below is based on the NIO2 file system 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);
}

Processing the stream of lines from a file returned Files.lines():

private static Map<String, Optional<ProcessedWords>> processLines(ProcessedWordsService service,
                                                                  Stream<String> lines) {
    return lines.collect(Collectors.toMap(
        Function.identity(),
        service::findByKeyword
    ));
}

Saving the words for which findByKeyword() returned an empty optional:

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

Generating a list of lines to retain:

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

Overriding the file contents using Files.write(). Note: since varargs OpenOption isn't provided with any arguments, this call would be treated as if the CREATE, TRUNCATE_EXISTING, and WRITE options are present.

private static void writeToFile(List<String> lines, Path path) {
    try {
        Files.write(path, lines);
    } catch (IOException e) {
        logger.log();
        e.printStackTrace();
    }
}
爱冒险 2025-02-11 01:22:24

供参考

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:将临时文件重命名为原始文件名。

For Reference

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

Read the file.
1: The condition to decide whether to delete the line or to retain it.
2: Write those line which you don't want to delete into the temporary file.
3: Delete the original file.
4: Rename the temporary file to original file name.

岁月流歌 2025-02-11 01:22:24

基本思想与@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 是我想要在处理后存储文件的地方。

The basic idea is the same as what @Shiva Rahul said in his answer.


However another approach can be , store all the line numbers you want to delete in a list. After you have all the required line numbers that you want to delete you can use LineNumberReader to check and duplicate your main file.

Mostly I have used this technique in batch-insert where I was unsure how many lines may have a particular file plus before removal of lines had to do lot of processing.
It may not be suitable for your case ,just posting the suggestion here if any one bumps to this thread.

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

To use this function all you have to do is gather all the required line numbers.inputFilePath is the path of the source file and outputDirectory is where I want store the file after processing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文