IO_Parsing
IO_Parsing
●
Streams treat all external source and destinations of
data the same way: as "streams" of information
Input vs. Output Streams
●
Reading from an Input Stream
●
Writing to an Output Stream
Byte vs. Character Streams
●
Byte Streams are used to read and write data in
binary format (1's and 0's)
example data: images, sounds, executable
programs, word-processing documents, etc.
●
Character Streams are used to read and write
data in text format (characters)
example data: plain text files (txt extension), web
pages, user keyboard input, etc.
Java Classes
●
To connect to a stream, instantiate a subclass of
one of these abstract superclasses:
input output
byte InputStream OutputStream
character Reader Writer
Using a Stream Class
●
Recall: a Reader is used to read a
character input stream
●
Reader offers these methods to read
single characters and arrays of
characters:
int read()
int read(char cbuf[])
int read(char cbuf[], int offset, int length)
●
Reader is abstract so you must instantiate
a subclass of it to use these methods
How to Read from a Text File
public void readFile() {
FileReader fileReader = null;
try {
fileReader = new FileReader("input.txt");
int c = fileReader.read();
while (c != -1) {
// cast c to char and use it
c = fileReader.read();
}
} catch (FileNotFoundException e) {
System.out.println("File was not found");
} catch (IOException e) {
System.out.println("Error reading from file");
}
if (fileReader != null) {
try { fileReader.close(); }
catch (IOException e) { /* ignore */ }
}
}
Wrap in a BufferedReader
●
Offers write methods to write single characters,
arrays of characters, and strings
void write(int c)
void write(char cbuf[])
void write(String str)
●
BufferedWriter offers efficient writing and a
newLine() method to insert a blank line
●
Close writers with close() method when done
How to Write to a Text File
public void writeFileWithBufferedWriter() {
BufferedWriter buffWriter = null;
try {
FileWriter fw = new FileWriter("output.txt");
buffWriter = new BufferedWriter(fw);
while (/*still stuff to write */) {
String line = // get line to write
buffWriter.write(line);
buffWriter.newLine();
}
} catch (IOException e) {
System.out.println("Error writing to file");
}
if (buffWriter != null) {
try { buffWriter.close(); }
catch(IOException e) { /* ignore */ }
}
}
Example: Copying Text Files
void copyFiles(String inFilename, String outFilename)
throws FileNotFoundException {
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(inFilename));
bw = new BufferedWriter(new FileWriter(outFilename));
String line = br.readLine();
while(line != null) {
bw.write(line);
bw.newLine();
line = br.readLine();
}
} catch (IOException e) {
System.out.println("Error copying files");
}
if (br != null) {
try { br.close(); }
catch (IOException e) { /* ignore */ }
}
return line;
}
What We've Learned So Far
●
Types of Streams
– Input vs. output streams
– Byte vs. character streams
●
How to . . .
– Read from text files
– Write to text files
– Read text from keyboard input
– Use buffered streams
●
You are left on your own to figure out how to use other streams
Intro to Parsing
●
Programs often encode data in text format to store in files
●
Programs later need to decode the text in the files back into
the original data
●
Process of decoding text back into data is known as parsing
Delimiters
●
When data is stored in text format, delimiter
characters are used to separate tokens of the
data
●
A list of first names stored separated by the '#'
delimiter: Greg#Kwame#Sonya#Bobby
●
Same list with a newline delimiter: Greg
Kwame
Sonya
Bobby
StringTokenizer
●
java.util.StringTokenizer separates Strings at the
delimiters to extract tokens
●
Default constructor will assume any whitespace (spaces,
tabs, newlines) to be delimiters
●
Second constructor accepts String of any delimiter
characters
●
nextToken method returns the next data token between
delimiters in the text
●
hasMoreTokens returns true if the text has remaining tokens
Using StringTokenizer
●
Printing out every name from a file where names are
delimited by whitespace:
●
Wrapper classes for primitives provide static methods to
do so
int Integer.parseInt(String s)
double Double.parseDouble(String s)
●
Throw NumberFormatException if the specified String
cannot be converted into the primitive
Putting it All Together
●
File 1: Employee_May.dat
Format: Name, SSN, Hourly Rate, Salary to Date
Paul Njoroge, 555-12-3456, 65, 20000
Evelyn Eastmond, 555-22-2222, 70, 30000
Peilei Fan, 555-33-4444, 60, 15000
Ethan Howe, 555-44-5555, 80, 40000
Naveen Goela, 555-66-8888, 75, 20000
. . .
●
File 2: Hours_June.dat
Format: Consecutive integers, which are the number of hours each
employee has worked during June. The integers have the same
sequence as that of the employee records.
Content: 50 60 40 50 70 . . .
What We Need to Do . . .
if (empReader != null) {
try { empReader.close(); }
catch(IOException e) {}
}
} catch(IOException e) {
System.out.println("Error with employee files");
}
if (mayReader != null) {
try { mayReader.close(); } catch(IOException e) {}
}
if (juneWriter != null) {
try { juneWriter.close(); } catch(IOException e) {}
}
Writing the June Data
while(employeeStr != null) {
StringTokenizer empST =
new StringTokenizer(employeeStr, ",");
String name = empST.nextToken();
String ssn = empST.nextToken();
double rate = Double.parseDouble(empST.nextToken());
double salary = Double.parseDouble(empST.nextToken());