Java - заменить содержимое файлов в каталоге

Итак, недавно мне было поручено заменить повторяющуюся фразу в серии документов другой фразой. Я ожидал один документ, который мог бы прочесать, но это куча огромных каталогов с тоннами этих файлов.

Мой мозг разработчика заработал, и поэтому я 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;
        }
    }
}

2 ответа

Решение

Как @Daniel O предложил в комментарии своего ответа, используя java.util.Scanner Класс, похоже, сработал!

Его слова: По крайней мере, в коде, который вы разместили с этим вопросом, вы используете очень сложное выражение для чтения файла. Вы пытались разбить это выражение на несколько строк, печатая промежуточные значения по пути, чтобы увидеть, какая конкретная часть дает сбой? Если ничего не помогает, вы можете просто прочитать файл по-другому, как с java.util.Scanner,

Вы не должны читать файл в байтах для манипулирования текстом. Пытаться Files.readAllLines() и итерации по строкам каждого файла.

Кажется, ваша программа читает нетекстовый файл. Из документации для String(bytes[], Charset):

Этот метод всегда заменяет последовательности неправильно сформированного ввода и не отображаемых символов на строку замены этого набора символов по умолчанию. Класс CharsetDecoder следует использовать, когда требуется больший контроль над процессом декодирования.

Имейте в виду, что использование этой стратегии изменит "совпадения" и в нетекстовых файлах.

Другие вопросы по тегам