Java Program to Make Changes Based on Dictionary
Here is a Java program that will make delimited text
changes to an input file, based on a file of substitutions
and producing a new output file with the changes.
Here "delimited" means that only complete identifiers are changed,
so that below "xyz" is to be changed to "abc", but
"xyz123" and "xyz12" remain unchanged.
// Changes.java: apply a dictionary of changes to an input source file
// and write out result as a new file
import java.io.*;
class Changes {
// three files:
private SimpleReader reader; // source file to be changed
private ChangeTable changeTable; // class to hold table of changes
private SimpleWriter writer; // file for changed source
// Changes: constructor -- create ChangeTable, open input and output
public Changes() {
reader = new SimpleReader("source.txt"); // source for changes
changeTable = new ChangeTable("changes.txt"); // create table of changes
writer = new SimpleWriter("output.txt"); // changed file
}
// makeChanges: read the source file. Find identifiers.
// substitute for the identifiers if one is found as an
// entry in the change file. Copy rest of source to output
public void makeChanges() {
char ch; // input char
String id = ""; // string to hold each identifier
boolean inID = false; // are we inside an identifier?
while ((byte)(ch = reader.getNextChar()) != -1) { // till EOF
if (inID) { // inside an identifier (already found first char)
if (Character.isJavaIdentifierPart(ch)) // inside identifier
id += ch; // add current char to identifier
else { // end of identifier in source
inID = false; // now at end of identifier
String newID = changeTable.lookUp(id);
if (newID == null) writer.putNextString(id); // output old id
else writer.putNextString(newID); // output substitute
writer.putNextChar(ch); // don't forget ch just past id
}
}
else if (Character.isJavaIdentifierStart(ch)) { // start of ident
id = ch + ""; // ch starts a new identifier in the source
inID = true; // now inside an identifier
}
else writer.putNextChar(ch); // otherwise output ch
}
// flush output
writer.flushWriter();
}
public static void main(String[] args) throws IOException {
Changes changes = new Changes(); // create the Changes class
changes.makeChanges(); // read file and make substitutions
}
}
// Entry.java: entry in the ChangeTable class
public class Entry {
private String oldID; // old string, to be replaced
private String newID; // new string, to use for replacing
public Entry(String oldIdent, String newIdent) {
oldID = oldIdent; newID = newIdent;
}
public String getOld() { return oldID; }
public String getNew() { return newID; }
}
// ChangeTable.java: table of text changes to make
import java.io.*;
public class ChangeTable {
SimpleReader reader;
private final int CHANGE_TABLE_SIZE = 100; // max table size
private Entry[] changeTable; // the table of changes itself
private int count; // number of current entries
public ChangeTable(String fileName) {
reader = new SimpleReader(fileName); // create reader for input
count = 0; // start out with no entries
changeTable = new Entry[CHANGE_TABLE_SIZE]; // allocate table
buildChangeTable(); // read change entries and build table
}
// buildChangeTable: read the change input file and insert
// changes into changeTable
private void buildChangeTable() {
while (true) {
String oldStr = reader.getNextString(); // old string
if (oldStr == null) break; // quit when get to EOF
String newStr = reader.getNextString(); // new string
if (newStr == null) {
System.err.println("Inside ChangeTable, need pairs of strings");
System.exit(1);
}
insertEntry(oldStr, newStr); // insert new entry
}
}
// insertEntry: add a single entry to changeTable
private void insertEntry(String oldItem, String newItem) {
changeTable[count++] = new Entry(oldItem, newItem);
if (count == CHANGE_TABLE_SIZE) { // could add code here to double size
System.err.println("Table Overflow");
System.exit(0);
}
}
// lookUp: look up old string for possible replacement
public String lookUp(String oldItem) {
for (int i = 0; i < count; i++)
if ( (changeTable[i].getOld()).equals(oldItem))
return changeTable[i].getNew(); // return replacemetn
return null; // is case it's not there
}
public static void main(String[] args) {
ChangeTable changeTable = new ChangeTable("changes.txt");
System.out.println(changeTable.lookUp("BaseConversion"));
System.out.println(changeTable.lookUp("push"));
System.out.println(changeTable.lookUp("baseConversion"));
System.out.println(changeTable.lookUp("Baseconversion"));
}
}
// SimpleReader: fetch next char or string from file
import java.io.*;
public class SimpleReader {
private Reader inFile; // file to read
public SimpleReader(String fileName) {
try {
inFile = new FileReader(fileName);
} catch (IOException e) {
System.err.println("Exception opening file " + fileName);
}
}
// getNextChar: fetches next char from inFile
public char getNextChar() {
char ch = ' '; // = ' ' to keep compiler happy
try {
ch = (char)inFile.read();
} catch (IOException e) {
System.err.println("Exception reading character");
}
return ch;
}
// getNextString: fetch String from inFile
// delimited by whitespace
public String getNextString() {
char ch;
String s = "";
while (true) { // skip inital whitespace
ch = getNextChar();
if ((byte)ch == -1) return null;
if (!Character.isWhitespace(ch)) break;
}
s += ch; // first char of string
while (true) { // read non-whitespace chars
ch = getNextChar();
if ((byte)ch == -1) return s;
if (!Character.isWhitespace(ch)) s += ch;
else break;
}
return s;
}
public static void main(String[] args) {
SimpleReader reader = new SimpleReader("source.txt");
String s;
char ch;
// test reading strings one at a time until EOF (null string returned)
while (true) {
s = reader.getNextString();
if (s == null) break;
System.out.println(s);
}
// test writing chars one at a time until EOF (-1 returned)
/* while (true) {
ch = reader.getNextChar();
if ((byte)ch == -1) break;
System.out.print(ch);
} */
}
}
// SimpleWriter: fetch next char or string from file
import java.io.*;
public class SimpleWriter {
private Writer outFile; // file to read
public SimpleWriter(String fileName) {
try {
outFile = new FileWriter(fileName);
} catch (IOException e) {
System.err.println("Exception opening file " + fileName);
}
}
// putNextChar: output next char to outFile
public void putNextChar(char ch) {
try {
outFile.write((int)ch);
} catch (IOException e) {
System.err.println("Exception writing character");
}
}
// putNextString: output String to outFile
public void putNextString(String s) {
for (int i = 0; i < s.length(); i++)
putNextChar(s.charAt(i));
}
// flushWriter: flush outFile (must flush or close or both at end)
public void flushWriter() {
try {
outFile.flush();
} catch (IOException e) {
System.err.println("Exception flushing output");
}
}
// closeWriter: close outFile (must flush or close or both at end)
public void closeWriter() {
try {
outFile.close();
} catch (IOException e) {
System.err.println("Exception closing output");
}
}
public static void main(String[] args) {
SimpleReader reader = new SimpleReader("source.txt");
SimpleWriter writer = new SimpleWriter("output2.txt");
String s;
char ch;
// test writing strings one at a time to EOF (null string returned)
while (true) {
s = reader.getNextString();
if (s == null) break;
writer.putNextString(s + " ");
}
// test writing chars one at a time to EOF (65535 returned)
/* while (true) {
ch = reader.getNextChar();
if ((byte)ch == -1) break;
writer.putNextChar(ch);
} */
writer.flushWriter();
writer.closeWriter();
}
}
Here is the output of a sample run, showing first the source file
to be changed (source.txt), the file
containing a dictionary of changes to make (changes.txt),
and the output file that incorporates the changes
(output.txt). The old identifier to be
changed is shown in green
and the new identifier to substitute for the old is shown in
red.
// BaseConversion: convert to base 8
public class BaseConversion {
public int[] s = new int[100];
public int top = 0;
public int pop() { return s[--top]; }
public void push(int n) { s[top++] = n; }
public boolean empty() { return top == 0; }
public void writebase(int n) {
System.out.print(n + " in base 8 = ");
while (n > 0) {
push(n%8);
n = n/8;
}
while (!empty())
System.out.print(pop());
System.out.println("(base 8)");
}
public static void main(String[] args) {
BaseConversion baseConversion = new BaseConversion();
baseConversion.writebase(93);
}
}
BaseConversion ConvertToBase8
s myStack
top stackTop
pop popStack
push pushStack
n num
empty emptyStack
writebase writeBase
baseConversion convertToBase8
// ConvertToBase8: convert to base 8
public class ConvertToBase8 {
public int[] myStack = new int[100];
public int stackTop = 0;
public int popStack() { return myStack[--stackTop]; }
public void pushStack(int num) { myStack[stackTop++] = num; }
public boolean emptyStack() { return stackTop == 0; }
public void writeBase(int num) {
System.out.print(num + " in base 8 = ");
while (num > 0) {
pushStack(num%8);
num = num/8;
}
while (!emptyStack())
System.out.print(popStack());
System.out.println("(base 8)");
}
public static void main(String[] args) {
ConvertToBase8 convertToBase8 = new ConvertToBase8();
convertToBase8.writeBase(93);
}
}