Java - 替换目录中文件的内容

标签 java file file-writing file-read java.nio.file

所以,最近我的任务是用另一个短语替换一系列文档中重复的短语。我原本期待一个可以梳理的文档,但它是一堆巨大的目录,其中包含大量这些文件。

我的开发人员大脑开始运转,所以我想到了 replaceAll() 函数,我创建了这个小方法来查找目录及其所有子目录中的所有文件,并且效果很好.

private static ArrayList<File> getAllFilesInDirectory(File directory) {
    ArrayList<File> filesInDirectory = new ArrayList<File>();

    if(!directory.isDirectory()) {
        filesInDirectory.add(directory);
        return filesInDirectory;
    } else {
        for(File fileInDirectory : directory.listFiles()) {
            if(!fileInDirectory.isDirectory())
                filesInDirectory.add(fileInDirectory);
            else
                filesInDirectory.addAll(getAllFilesInDirectory(fileInDirectory));
        }
        return filesInDirectory;
    }
}

经过更多的工作,我开发了一个程序,用另一个短语替换目录中的所有短语:

package xyz.ammartarajia.programs.rasid;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

public class RASID {
    public static void main(String[] args) {
        JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(new File("."));
        chooser.setDialogTitle("Open Directory...");
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        chooser.setAcceptAllFileFilterUsed(false);
        chooser.showOpenDialog(null);

        String toReplace = JOptionPane.showInputDialog(null, "Please enter what you'd like to replace.", "To Replace", JOptionPane.QUESTION_MESSAGE),
                replaceWith = JOptionPane.showInputDialog(null, "Please enter what you'd like to replace the previous string with.", "Replace With", JOptionPane.QUESTION_MESSAGE);

        ArrayList<File> files = getAllFilesInDirectory(chooser.getSelectedFile());

        for(File file : files) {
            try(BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
                String newString = new String(Files.readAllBytes(Paths.get(file.getPath())), Charset.defaultCharset()).replaceAll(toReplace, replaceWith);
                System.out.println("New String: " + newString);
                writer.write(newString);
                writer.close();
            } catch(IOException e) {
                JOptionPane.showMessageDialog(null, "An error ocurred whilst editing the file!", "Error", JOptionPane.ERROR_MESSAGE);
                e.printStackTrace();
            }
        }
    }

    private static ArrayList<File> getAllFilesInDirectory(File directory) {
        ArrayList<File> filesInDirectory = new ArrayList<File>();

        if(!directory.isDirectory()) {
            filesInDirectory.add(directory);
            return filesInDirectory;
        } else {
            for(File fileInDirectory : directory.listFiles()) {
                if(!fileInDirectory.isDirectory())
                    filesInDirectory.add(fileInDirectory);
                else
                    filesInDirectory.addAll(getAllFilesInDirectory(fileInDirectory));
            }
            return filesInDirectory;
        }
    }
}

该程序的问题是,当文件以 String 形式读入文件时,它决定失败,而是给我一个空的String。我不确定为什么,但我认为这与路径有关。

编辑: 我更改了代码,使用 readAllLines(Path, Charset) 方法似乎没有任何区别。这是新代码:

package xyz.ammartarajia.programs.rasid;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

public class RASID {
    public static void main(String[] args) {
        JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(new File("."));
        chooser.setDialogTitle("Open Directory...");
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        chooser.setAcceptAllFileFilterUsed(false);
        chooser.showOpenDialog(null);

        String toReplace = JOptionPane.showInputDialog(null, "Please enter what you'd like to replace.", "To Replace", JOptionPane.QUESTION_MESSAGE),
                replaceWith = JOptionPane.showInputDialog(null, "Please enter what you'd like to replace the previous string with.", "Replace With", JOptionPane.QUESTION_MESSAGE);

        ArrayList<File> files = getAllFilesInDirectory(chooser.getSelectedFile());

        for(File file : files) {
            try(BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
                String newString = new String(combineLines(Files.readAllLines(Paths.get(file.getPath()), Charset.defaultCharset()))).replaceAll(toReplace, replaceWith);
                System.out.println("New String: " + newString);
                writer.write(newString);
                writer.close();
            } catch(IOException e) {
                JOptionPane.showMessageDialog(null, "An error ocurred whilst editing the file!", "Error", JOptionPane.ERROR_MESSAGE);
                e.printStackTrace();
            }
        }
    }

    private static String combineLines(List<String> lines) {
        String linesAsString = "";
        for(String line : lines)
            linesAsString += line + '\n';
        return linesAsString;
    }

    private static ArrayList<File> getAllFilesInDirectory(File directory) {
        ArrayList<File> filesInDirectory = new ArrayList<File>();

        if(!directory.isDirectory()) {
            filesInDirectory.add(directory);
            return filesInDirectory;
        } else {
            for(File fileInDirectory : directory.listFiles()) {
                if(!fileInDirectory.isDirectory())
                    filesInDirectory.add(fileInDirectory);
                else
                    filesInDirectory.addAll(getAllFilesInDirectory(fileInDirectory));
            }
            return filesInDirectory;
        }
    }
}

最佳答案

您不应该以字节的形式读取文件来进行文本操作。尝试 Files.readAllLines() 并迭代每个文件的行。

您的程序似乎正在读取非文本文件。来自 String(bytes[], Charset) 的文档:

This method always replaces malformed-input and unmappable-character sequences with this charset's default replacement string. The CharsetDecoder class should be used when more control over the decoding process is required.

请注意,使用此策略也会修改非文本文件中的“匹配项”。

关于Java - 替换目录中文件的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37865677/

相关文章:

java - Selenium 测试失败 "Element is not clickable at..."

file - 如何将所有控制台输出保存到 R 中的文件中?

python - 关闭文件 python

python - 如何加快此文件创建过程?

java - 为什么我的单向 @ManyToOne 关系中的表没有加入 Spring Data findAll() 查询?

java - 泛型类型的类参数

java - java从一个文件读取,修改并输出到另一个文件

go - 在 Go 中定期调用 N 个并发函数的最佳方法是什么?

python - 如何制作自定义打印格式?

java - 我可以将 servlet 与 Angular JS 结合使用并实现 MVC 架构吗?