Now I want to provide a facility that modifies the content of a file based on a regex pattern. That is, I want to provide a mechanism that opens a file, searches its contents based on a regex pattern, and changes every occurrence of that pattern with a replacement string. Because I already have code that will open and search a file, modifying the content of the file is fairly easy. The logic for doing so is shown in Figure 5-2.
Again, I decide to use a FileChannel for efficiency, as shown in Listing 5-11.
01 /**
02 * updates the content of the file. By default, the
03 * Pattern.MULTILINE is used. Also supports the
04 * $d notation in the replacement string, per the
05 * Matcher.replaceAll method
06 * @param the String fileName is the name and file path
07 * @param the String regex pattern to look for
08 * @param the String replacement for the regex
09 * @throws IOException if there is an IO error
10 *
11 * @return boolean true if the file was updated
12 */
13 public static boolean updateFileContent
14 (
15 String fileName,
16 String regex,
17 String replacement
18 ) throws IOException
19 {
20 boolean retval = false;
21 RandomAccessFile raf =
22 new RandomAccessFile(fileName,"rwd");
23 FileChannel fc = raf.getChannel();
24 String fileContent = getFileContent(fc);
25 //Activate the MULTILINE flag for this regex
26 regex = "(?m)"+regex;
27 String newFileContent =
28 fileContent.replaceAll(regex,replacement);
29 //if nothing changed, then don't update the file
30 if (!newFileContent.equals(fileContent))
31 {
32 setFileContent(newFileContent,fc);
33 retval = true;
34 }
35 //close up shop
36 fc.close();
37 fc = null;
38 raf = null;
39 return retval;
40 }
41 /**
42 * sets the content of a file. Completely
43 * overwrites previous file content, and truncates
44 * file to the length of the new content.
45 * @param the <code>String</code> newContent
46 * @param the <code>FileChannel</code> fc
47 * @throws <code>IOException</code>
48 *
49 * @author M Habibi
50 */
51 private static void setFileContent(
52 String newContent, FileChannel fc
53 )
54 throws IOException{
55 //write out the content to the file
56 ByteBuffer bb = ByteBuffer.wrap(newContent.getBytes());
57 //truncate the size of the file, in case the
58 //original file content was longer the new
59 //content
60 fc.truncate(newContent.length());
61 //start writing as position 0
62 fc.position(0);
63 fc.write(bb);
64 fc.close();
65 fc = null;
66 }
Listing 5-11 takes advantage of the getFileContent method defined earlier in line 29 of Listing 5-7. Otherwise, the example is self-contained.