19-ch06-2-linebased

Download Report

Transcript 19-ch06-2-linebased

Building Java Programs
Chapter 6: File Processing
Lecture 6-2: Advanced file input
reading: 6.3 - 6.5
self-check: #7-11
exercises: #1-4, 8-11
Copyright 2009 by Pearson Education
Hours question
 Given a file hours.txt with the following contents:
123 Susan 12.5 8.1 7.6 3.2
456 Brad 4.0 11.6 6.5 2.7 12
789 Jenn 8.0 8.0 8.0 8.0 7.5
 Consider the task of computing hours worked by each
person:
Susan (ID#123) worked 31.4 hours (7.85 hours/day)
Brad (ID#456) worked 36.8 hours (7.36 hours/day)
Jenn (ID#789) worked 39.5 hours (7.9 hours/day)
 Can we produce this data token by token?
Copyright 2009 by Pearson Education
2
Hours program strategy
123 Susan 12.5 8.1 7.6 3.2
456 Brad 4.0 11.6 6.5 2.7 12
789 Jenn 8.0 8.0 8.0 8.0 7.5
 We want to process the tokens, but we also care about
the line breaks (they mark the end of a person's data).
 A better solution:
 First, break the overall input into lines.
 Then break each line into tokens.
 What if you tried it token by token first?
Copyright 2009 by Pearson Education
3
Hours answer (flawed)
import java.io.*;
import java.util.*;
// for File
// for Scanner
public class HoursWorked {
// a non-working solution
public static void main(String[] args)
throws FileNotFoundException {
Scanner input = new Scanner(new File("hours.txt"));
while (input.hasNext()) {
// process one person
int id = input.nextInt();
String name = input.next();
double totalHours = 0.0;
int days = 0;
while (input.hasNextDouble()) {
totalHours += input.nextDouble();
days++;
}
System.out.println(name + " (ID#" + id +
") worked " + totalHours + " hours (" +
(totalHours / days) + " hours/day)");
}
}
}
Copyright 2009 by Pearson Education
4
Flawed output
Susan (ID#123) worked 487.4 hours (97.48 hours/day)
Exception in thread "main"
java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextInt(Scanner.java:2091)
at HoursWorked.main(HoursBad.java:9)
 The inner while loop is grabbing the next person's ID.
 Hard to tell it where to stop!
 The line breaks indicate the end of the data
 Much easier and more natural to process by asking for a line of
input at a time, then only concentrating on that line
Copyright 2009 by Pearson Education
5
Tokenizing lines of a file
 A Scanner object can also be used to process a String
 Scanner lineScan = new Scanner(string);
 A String Scanner can tokenize each line of a file.
Scanner input = new Scanner(new File("file name"));
while (input.hasNextLine()) {
String line = input.nextLine();
Scanner lineScan = new Scanner(line);
process the contents of this line...
}
Copyright 2009 by Pearson Education
6
Hours program solution
// Processes an employee input file and outputs each employee's hours data.
import java.io.*;
// for File
import java.util.*; // for Scanner
public class Hours {
public static void main(String[] args) throws FileNotFoundException {
Scanner input = new Scanner(new File("hours.txt"));
while (input.hasNextLine()) {
String line = input.nextLine();
Scanner lineScan = new Scanner(line);
int id = lineScan.nextInt();
// e.g. 456
String name = lineScan.next();
// e.g. "Brad"
double sum = 0.0;
int count = 0;
while (lineScan.hasNextDouble()) {
sum = sum + lineScan.nextDouble();
count++;
}
double average = sum / count;
System.out.println(name + " (ID#" + id + ") worked " +
sum + " hours (" + average + " hours/day)");
}
}
}
Copyright 2009 by Pearson Education
7
File Processing Summary
 Token-based file processing:
 Breaks up entire file into tokens to process data
Scanner input = new Scanner(new File("midterm.txt"));
while(input.hasNext()) {
... (use methods from input to process file)
}
 Line-based file processing:
 Breaks up file into lines to process data
Scanner input = new Scanner(new File("hours.txt"));
while(input.hasNextLine()) {
String line = input.nextLine();
Scanner lineScan = new Scanner(line);
... (use methods from lineScan to process file)
}
Copyright 2009 by Pearson Education
8
Confusion w/ nextLine
 Using nextLine in conjunction with the token-based
methods on the same Scanner can cause odd results.
23
Joe
3.14
"Hello world"
45.2
19
 You'd think you could read 23 and 3.14 with nextInt and
nextDouble, then read Joe "Hello world" with
nextLine .
System.out.println(input.nextInt());
System.out.println(input.nextDouble());
System.out.println(input.nextLine());
// 23
// 3.14
//
 But the nextLine call produces no output! Why?
Copyright 2009 by Pearson Education
9
Mixing lines and tokens
 Don't read both tokens and lines from the same
Scanner:
23
Joe
3.14
"Hello world"
45.2
19
input.nextInt()
23\t3.14\nJoe\t"Hello world"\n\t\t45.2
^
input.nextDouble()
23\t3.14\nJoe\t"Hello world"\n\t\t45.2
^
input.nextLine()
23\t3.14\nJoe\t"Hello world"\n\t\t45.2
^
// 23
19\n
// 3.14
19\n
// "" (empty!)
19\n
input.nextLine()
// "Joe\t\"Hello world\""
23\t3.14\nJoe\t"Hello world"\n\t\t45.2 19\n
^
Copyright 2009 by Pearson Education
10
Line-and-token example
Scanner console = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = console.nextInt();
System.out.print("Now enter your name: ");
String name = console.nextLine();
System.out.println(name + " is " + age + " years old.");
Log of execution (user input underlined):
Enter your age: 12
Now enter your name: Sideshow Bob
is 12 years old.
 Why?
 User's overall input:
 After nextInt():
 After nextLine():
Copyright 2009 by Pearson Education
12\nSideshow Bob
12\nSideshow Bob
^
12\nSideshow Bob
^
11
Array traversals,
text processing
reading: 7.1, 4.4
self-check: Ch. 7 #8, Ch. 4 #19-23
Copyright 2009 by Pearson Education
Text processing
 text processing: Examining, editing, formatting text.
 Often involves for loops to break up and examine a String
 Examples:



Count the number of times 's' occurs in a file
Find which letter is most common in a file
Count A, C, T and Gs in Strings representing DNA strands
Copyright 2009 by Pearson Education
13
Strings as arrays
 Strings are represented internally as arrays.
 Each character is stored as a value of primitive type char.
 Strings use 0-based indexes, like arrays.
 We can write algorithms to traverse Strings.
 Example:
String str = "Mr. E.";
index
0
1
2
3
4
5
value
'M'
'r'
'.'
' '
'E'
'.'
Copyright 2009 by Pearson Education
14
Recall: type char
 char: A primitive type representing a single character.
 Values are surrounded with apostrophes: 'a' or '4' or '\n'
 Access a string's characters with its charAt method.
String word = console.next();
char firstLetter = word.charAt(0);
if (firstLetter == 'c') {
System.out.println("That's good enough for me!");
}
Copyright 2009 by Pearson Education
15
String traversals
 traversal: An examination of each element of an array.
for (int i = 0; i < array.length; i++) {
do something with array[i];
}
 Use for loops to examine each character.
for (int i = 0; i < string.length(); i++) {
do something with string.charAt(i);
}
Copyright 2009 by Pearson Education
16
Section attendance problem
 Consider an input file of course attendance data:
111111101011111101001110110110110001110010100
111011111010100110101110101010101110101101010
110101011011011011110110101011010111011010101
week1 week2 week3 week4 week5 week6 week7 week8 week9
11111 11010 11111 10100 11101 10110 11000 11100 10100
week2
student1 student2 student3 student4 student5
1
1
0
1
0
 Each line represents a section (5 students, 9 weeks).
 1 means the student attended; 0 means absent.
Copyright 2009 by Pearson Education
17
Section attendance problem
 Write a program that reads the preceding section data file
and produces the following output:
Section #1:
Sections attended: [9, 6, 7, 4, 3]
Student scores: [20, 18, 20, 12, 9]
Student grades: [100.0, 90.0, 100.0, 60.0, 45.0]
Section #2:
Sections attended: [6, 7, 5, 6, 4]
Student scores: [18, 20, 15, 18, 12]
Student grades: [90.0, 100.0, 75.0, 90.0, 60.0]
Section #3:
Sections attended: [5, 6, 5, 7, 6]
Student scores: [15, 18, 15, 20, 18]
Student grades: [75.0, 90.0, 75.0, 100.0, 90.0]
Copyright 2009 by Pearson Education
18
Data transformations
 In this problem we go from 0s and 1s to student grades
 This is called transforming the data.
 Often each transformation is stored in its own array.
 We must map between the data and array indexes.
Examples:
 by position
(store the i th value we read at index i )
 tally
(if input value is i, store it at array index i )
 explicit mapping (count 'M' at index 0, count 'O' at index 1)
Copyright 2009 by Pearson Education
19
Section attendance answer
// This program reads a file representing which students attended
// which discussion sections and produces output of the students'
// section attendance and scores.
import java.io.*;
import java.util.*;
public class Sections {
public static void main(String[] args) throws FileNotFoundException {
Scanner input = new Scanner(new File("sections.txt"));
while (input.hasNextLine()) {
// process one section
String line = input.nextLine();
int[] attended = countAttended(line);
int[] points = computePoints(attended);
double[] grades = computeGrades(points);
results(attended, points, grades);
}
}
// Produces all output about a particular section.
public static void results(int[] attended, int[] points, double[] grades) {
System.out.println("Sections attended: " + Arrays.toString(attended));
System.out.println("Sections scores: " + Arrays.toString(points));
System.out.println("Sections grades: " + Arrays.toString(grades));
System.out.println();
}
...
Copyright 2009 by Pearson Education
20
Section attendance answer 2
}
...
// Counts the sections attended by each student for a particular section.
public static int[] countAttended(String line) {
int[] attended = new int[5];
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
// c == '1' or c == '0'
if (c == '1') {
// student attended their section
attended[i % 5]++;
}
}
return attended;
}
// Computes the points earned for each student for a particular section.
public static int[] computePoints(int[] attended) {
int[] points = new int[5];
for (int i = 0; i < attended.length; i++) {
points[i] = Math.min(20, 3 * attended[i]);
}
return points;
}
// Computes the percentage for each student for a particular section.
public static double[] computeGrades(int[] points) {
double[] grades = new double[5];
for (int i = 0; i < points.length; i++) {
grades[i] = 100.0 * points[i] / 20.0;
}
return grades;
}
Copyright 2009 by Pearson Education
21
File input/output
reading: 6.4 - 6.5

Copyright 2009 by Pearson Education
22
Prompting for a file name
 We can ask the user to tell us the file to read.
 The file name might have spaces: use nextLine()
// prompt for the file name
Scanner console = new Scanner(System.in);
System.out.print("Type a file name to use: ");
String filename = console.nextLine();
Scanner input = new Scanner(new File(filename));
 What if the user types a file name that does not exist?
Copyright 2009 by Pearson Education
23
Fixing file-not-found issues
 File objects have an exists method we can use:
Scanner console = new Scanner(System.in);
System.out.print("Type a file name to use: ");
String filename = console.nextLine();
File file = new File(filename);
while (!file.exists()) {
System.out.print("File not found! Try again: ");
String filename = console.nextLine();
file = new File(filename);
}
Scanner input = new Scanner(file); // open the file
Output:
Type a file name to use: hourz.text
File not found! Try again: h0urz.txt
File not found! Try again: hours.txt
Copyright 2009 by Pearson Education
24
Output to files
 PrintStream: An object in the java.io package that
lets you print output to a destination such as a file.
 System.out is also a PrintStream.
 Any methods you have used on System.out
(such as print, println) will work on every PrintStream.
 Do not open a file for reading (Scanner) and writing
(PrintStream) at the same time.
 You could overwrite your input file by accident!
 The result can be an empty file (size 0 bytes).
Copyright 2009 by Pearson Education
25
Printing to files, example
 Printing into an output file, general syntax:
PrintStream name =
new PrintStream(new File("file name"));
...
 If the given file does not exist, it is created.
 If the given file already exists, it is overwritten.
PrintStream output = new PrintStream(new File("output.txt"));
output.println("Hello, file!");
output.println("This is a second line of output.");
 Can use similar ideas about prompting for file names here.
Copyright 2009 by Pearson Education
26
PrintStream question
 Modify our previous Sections program to use a
PrintStream to output to the file section_output.txt.
Section #1:
Sections attended: [9, 6, 7, 4, 3]
Student scores: [20, 18, 20, 12, 9]
Student grades: [100.0, 90.0, 100.0, 60.0, 45.0]
Section #2:
Sections attended: [6, 7, 5, 6, 4]
Student scores: [18, 20, 15, 18, 12]
Student grades: [90.0, 100.0, 75.0, 90.0, 60.0]
Section #3:
Sections attended: [5, 6, 5, 7, 6]
Student scores: [15, 18, 15, 20, 18]
Student grades: [75.0, 90.0, 75.0, 100.0, 90.0]
Copyright 2009 by Pearson Education
27
PrintStream answer
// Section attendance
// This version uses a PrintStream for output.
import java.io.*;
import java.util.*;
public class Sections {
public static void main(String[] args) throws FileNotFoundException {
Scanner input = new Scanner(new File("sections.txt"));
PrintStream out = new PrintStream(new File("section_output.txt"));
while (input.hasNextLine()) {
// process one section
String line = input.nextLine();
int[] attended = countAttended(line);
int[] points = computePoints(attended);
double[] grades = computeGrades(points);
results(attended, points, grades, out);
}
}
// Produces all output about a particular section.
public static void results(int[] attended, int[] points,
double[] grades, PrintStream out) {
out.println("Sections attended: " + Arrays.toString(attended));
out.println("Sections scores: " + Arrays.toString(points));
out.println("Sections grades: " + Arrays.toString(grades));
out.println();
}
...
Copyright 2009 by Pearson Education
28