Search code examples
javafilefile-writingfile-readjava.nio.file

Java - Replace Contents Of Files In A Directory


So, recently I've been tasked with replacing a repeated phrase in a series of documents with another phrase. I was expecting a single document I might be able to comb over but it's a bunch of huge directories with tonnes of these files in.

My developer brain kicked in and so I though of the replaceAll() function, I created this little method to find all the files within a directory and all of it's sub-directories and it worked fine.

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

So after some more work, I developed a program to replace all the phrases in a directory with another phrase:

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

The problem with the program is that when the file reads in the file as a String it decides to fail and instead give me an empty String. I'm not sure why but I think it has something to do with the paths.

EDIT: I've changed the code, it doesn't seemed to have made any difference using the readAllLines(Path, Charset) method. Here's the new code:

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

Solution

  • As @Daniel O suggested in his answer's comment, using the java.util.Scanner class seems to have worked!

    His words: At least in the code you posted with this question, you use a very complex expression to read the file. Have you tried breaking that expression up across multiple lines, printing intermediate values along the way so you can see which specific part is failing? If all else fails, you could just read the file another way, like with a java.util.Scanner.