Pattern-Based File Content Modification in Java
In many real-world scenarios, developers need to modify file content based on specific patterns. For instance, you might want to replace placeholders in a configuration file, update log messages, or clean up unwanted data. Java provides powerful tools for reading, analyzing, and rewriting file contents using regular expressions and efficient I/O APIs.
1. Introduction
Suppose you have a text file containing multiple lines of text, and you want to modify certain lines that match a specific pattern — for example, replacing all email addresses with a placeholder like [EMAIL_HIDDEN], or changing all occurrences of a word like “DEBUG” to “INFO” in log files. The challenge is to efficiently scan through large files, detect matches using regex patterns, and write back the modified content without corrupting the file.
1.1 Different Ways to Solve the Problem
- Using BufferedReader and BufferedWriter: Read the file line by line, apply pattern matching, and write to a new file.
- Using Java NIO (Files API): Load the entire file into memory as a list of strings, process it, and write back.
- Using Stream API: Leverage Java 8+ functional style with Files.lines() and map() for transformation.
- Using Regular Expressions (Regex): Combine regex with I/O for advanced pattern detection and replacement.
2. Code Example
The following Java program demonstrates four different approaches to modifying file content based on patterns, all combined into a single class for clarity.
// FilePatternModifier.java
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;
import java.util.regex.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FilePatternModifier {
public static void main(String[] args) {
modifyUsingBufferedReaderWriter();
modifyUsingNIO();
modifyUsingStreamAPI();
modifyUsingRegexAndNIO();
}
// -------------------------------------------------------------------
// 3.1 BufferedReader + BufferedWriter
// Replace email addresses
// -------------------------------------------------------------------
private static void modifyUsingBufferedReaderWriter() {
String inputFile = "input.txt";
String outputFile = "output_3_1.txt";
Pattern emailPattern = Pattern.compile(
"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-z]{2,}"
);
try (BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {
String line;
while ((line = reader.readLine()) != null) {
String modified = emailPattern.matcher(line)
.replaceAll("[EMAIL_HIDDEN]");
writer.write(modified);
writer.newLine();
}
System.out.println("Method 3.1 completed. Output written to " + outputFile);
} catch (IOException e) {
e.printStackTrace();
}
}
// -------------------------------------------------------------------
// 3.2 Java NIO (Files.readAllLines + Files.write)
// Replace DEBUG with INFO
// -------------------------------------------------------------------
private static void modifyUsingNIO() {
Path inputPath = Paths.get("input.txt");
Path outputPath = Paths.get("output_3_2.txt");
Pattern debugPattern = Pattern.compile("DEBUG");
try {
List<String> lines = Files.readAllLines(inputPath);
for (int i = 0; i < lines.size(); i++) {
lines.set(i, debugPattern.matcher(lines.get(i))
.replaceAll("INFO"));
}
Files.write(outputPath, lines);
System.out.println("Method 3.2 completed. Output written to " + outputPath);
} catch (IOException e) {
e.printStackTrace();
}
}
// -------------------------------------------------------------------
// 3.3 Stream API (Files.lines + map)
// Replace IP addresses
// -------------------------------------------------------------------
private static void modifyUsingStreamAPI() {
Path inputPath = Paths.get("input.txt");
Path outputPath = Paths.get("output_3_3.txt");
Pattern ipPattern = Pattern.compile("\\b\\d{1,3}(\\.\\d{1,3}){3}\\b");
try (Stream<String> stream = Files.lines(inputPath)) {
List<String> modified = stream
.map(line -> ipPattern.matcher(line)
.replaceAll("[IP_HIDDEN]"))
.collect(Collectors.toList());
Files.write(outputPath, modified);
System.out.println("Method 3.3 completed. Output written to " + outputPath);
} catch (IOException e) {
e.printStackTrace();
}
}
// -------------------------------------------------------------------
// 3.4 Regex + NIO (Files.readString + writeString)
// Mask password
// -------------------------------------------------------------------
private static void modifyUsingRegexAndNIO() {
Path inputPath = Paths.get("input.txt");
Path outputPath = Paths.get("output_3_4.txt");
try {
String content = Files.readString(inputPath, StandardCharsets.UTF_8);
Pattern pattern = Pattern.compile("password=\\w+");
String modified = pattern.matcher(content)
.replaceAll("password=[PROTECTED]");
Files.writeString(outputPath, modified, StandardCharsets.UTF_8);
System.out.println("Method 3.4 completed. Output written to " + outputPath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.1 Code Explanation
The combined Java program demonstrates four different approaches to modifying a file’s content based on patterns, all using a single input file. The modifyUsingBufferedReaderWriter() method uses classic I/O with BufferedReader and BufferedWriter to read each line, apply a regular expression to replace email addresses, and write the updated lines to a new file. The modifyUsingNIO() method uses Java NIO’s Files.readAllLines() to load the entire file into memory and replace occurrences of the string “DEBUG” with “INFO,” showcasing a simple list-based transformation. The modifyUsingStreamAPI() method leverages Files.lines() and Java Streams to process file lines in a functional style, replacing IP addresses using a regex matcher and collecting modified lines to write them back. Finally, modifyUsingRegexAndNIO() reads the entire file content as a single string with Files.readString() and uses regex replacement to mask password values before writing the updated text using Files.writeString(). Together, these methods illustrate four efficient workflows—streaming I/O, list processing, functional streaming, and full-content regex transformation—while keeping the same input source but producing separate output files for each technique.
2.2 Code Output
We will use the following input file:
Hello team, Please contact john.doe@example.com for more details. The server is running at 192.168.10.25 2025-11-06 DEBUG - Application starting db_user=admin password=secret123 Backup server: 10.0.0.14 2025-11-06 DEBUG - Loading configuration Reach support at helpdesk@company.org password=testpass
and the following output appears for each generated file:
2.2.1 output_3_1.txt
This output shows the result after replacing all email addresses with the placeholder [EMAIL_HIDDEN].
Hello team, Please contact [EMAIL_HIDDEN] for more details. The server is running at 192.168.10.25 2025-11-06 DEBUG - Application starting db_user=admin password=secret123 Backup server: 10.0.0.14 2025-11-06 DEBUG - Loading configuration Reach support at [EMAIL_HIDDEN] password=testpass
2.2.2 output_3_2.txt
This output shows the result after replacing every occurrence of the keyword DEBUG with INFO.
Hello team, Please contact john.doe@example.com for more details. The server is running at 192.168.10.25 2025-11-06 INFO - Application starting db_user=admin password=secret123 Backup server: 10.0.0.14 2025-11-06 INFO - Loading configuration Reach support at helpdesk@company.org password=testpass
2.2.3 output_3_3.txt
This output shows the result after masking all detected IP addresses with the placeholder [IP_HIDDEN].
Hello team, Please contact john.doe@example.com for more details. The server is running at [IP_HIDDEN] 2025-11-06 DEBUG - Application starting db_user=admin password=secret123 Backup server: [IP_HIDDEN] 2025-11-06 DEBUG - Loading configuration Reach support at helpdesk@company.org password=testpass
2.2.4 output_3_4.txt
This output shows the result after scanning for password= patterns and replacing the values with [PROTECTED].
Hello team, Please contact john.doe@example.com for more details. The server is running at 192.168.10.25 2025-11-06 DEBUG - Application starting db_user=admin password=[PROTECTED] Backup server: 10.0.0.14 2025-11-06 DEBUG - Loading configuration Reach support at helpdesk@company.org password=[PROTECTED]
3. Conclusion
Modifying file content based on patterns in Java becomes straightforward with the combination of the java.nio.file package and regular expressions. Whether you need to redact sensitive data, reformat text, or perform bulk content updates, this approach provides a clean and efficient way to handle dynamic content transformation. For large-scale or streaming scenarios, you can extend this concept using BufferedReader and BufferedWriter to avoid loading the entire file into memory, ensuring better performance and scalability.

