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;
}
}
}
You shouldn't be reading the file in as bytes to do text manipulation. Try Files.readAllLines()
and iterate over the lines of each file.
Your program seems to be reading a non-text file. From the documentation for 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.
Be aware that using this strategy will modify "matches" in non-text files as well.