Building Java Programs

Slides:



Advertisements
Similar presentations
Building Java Programs Chapter 6 File Processing Copyright (c) Pearson All rights reserved.
Advertisements

BUILDING JAVA PROGRAMS CHAPTER 6.4 FILE OUTPUT. 22 PrintStream : An object in the java.io package that lets you print output to a destination such as.
Copyright 2008 by Pearson Education Line-based file processing reading: 6.3 self-check: #7-11 exercises: #1-4, 8-11.
Copyright 2008 by Pearson Education Building Java Programs Chapter 6 Lecture 6-1: File Input with Scanner reading: , 5.3 self-check: Ch. 6 #1-6.
Copyright 2008 by Pearson Education Building Java Programs Chapter 7 Lecture 7-3: File Output; Reference Semantics reading: , 7.1, 4.3, 3.3 self-checks:
Copyright 2006 by Pearson Education 1 Building Java Programs Chapter 6: File Processing.
1 CSE 142 Lecture Notes File input using Scanner Suggested reading: , Suggested self-checks: Section 6.7 # 1-11, These lecture.
Copyright 2006 by Pearson Education 1 Building Java Programs Chapter 7: Arrays.
Copyright 2008 by Pearson Education Building Java Programs Chapter 7 Lecture 7-2: Tallying and Traversing Arrays reading: 7.1 self-checks: #1-9 videos:
Topic 20 more file processing Copyright Pearson Education, 2010 Based on slides bu Marty Stepp and Stuart Reges from
Copyright 2010 by Pearson Education Building Java Programs Chapter 7 Lecture 7-3: Arrays for Tallying; Text Processing reading: 4.3, 7.6.
1 Reference semantics. 2 A swap method? Does the following swap method work? Why or why not? public static void main(String[] args) { int a = 7; int b.
Copyright 2010 by Pearson Education Building Java Programs Chapter 6 Lecture 6-2: Line-Based File Input reading:
1 Hours question Given a file hours.txt with the following contents: 123 Kim Eric Stef
BUILDING JAVA PROGRAMS CHAPTER 6 File Processing.
1 BUILDING JAVA PROGRAMS CHAPTER 7 LECTURE 7-3: ARRAYS AS PARAMETERS; FILE OUTPUT.
Topic 19 file input, line based Copyright Pearson Education, 2010 Based on slides bu Marty Stepp and Stuart Reges from
Copyright 2008 by Pearson Education Building Java Programs Chapter 7 Lecture 7-3: Arrays as Parameters; File Output reading: 7.1, 4.3, 3.3 self-checks:
Building Java Programs Chapter 7 Lecture 7-3: Arrays for Tallying; Text Processing reading: 7.6, 4.3.
Copyright 2008 by Pearson Education Building Java Programs Chapter 6: File Processing Lecture 6-2: Advanced file input reading: self-check: #7-11.
1 Building Java Programs Chapter 6 Lecture 6-3: Section Problems reading:
Copyright 2006 by Pearson Education 1 Building Java Programs Chapter 7: Arrays.
Copyright 2010 by Pearson Education Building Java Programs Chapter 7 Lecture 7-3: Arrays for Tallying; Text Processing reading: 7.1, 4.4 self-checks: #1-9.
FILE PROCESSING. Reading files To read a file, pass a File when constructing a Scanner. Scanner name = new Scanner(new File(" file name ")); Example:
Building Java Programs Chapter 6 Lecture 6-2: Line-Based File Input reading:
1 Reminder: String Scanners A Scanner can be constructed to tokenize a particular String, such as one line of an input file. Scanner = new Scanner( );
File Processing Copyright Pearson Education, 2010 Based on slides bu Marty Stepp and Stuart Reges from "We can only.
Copyright 2010 by Pearson Education Building Java Programs Chapter 7 Lecture 17: Arrays for Tallying; Text Processing reading: 4.3, 7.6 (Slides adapted.
Topic 23 arrays - part 3 (tallying, text processing) Copyright Pearson Education, 2010 Based on slides bu Marty Stepp and Stuart Reges from
1 Line-based file processing suggested reading:6.3.
Copyright 2008 by Pearson Education Building Java Programs Chapter 7 Lecture 7-3: Arrays as Parameters; File Output reading: 7.1, 4.3, 3.3 self-checks:
Copyright 2008 by Pearson Education Building Java Programs Chapter 6 Lecture 6-3: Searching Files reading: 6.3, 6.5.
Building Java Programs Chapter 6 File Processing Copyright (c) Pearson All rights reserved.
1 Line-based file processing reading: 6.3 Use this if you seem to need line based processing for some aspects of your program and token based for others.
Building Java Programs
Building Java Programs Chapter 6
Building Java Programs
Hours question Given a file hours.txt with the following contents:
Line-based file processing
Topic 20 more file processing
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs Chapter 6
Building Java Programs
Building Java Programs
Lecture 7-3: Arrays for Tallying; Text Processing
Topic 23 arrays - part 3 (tallying, text processing)
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Hours question Given a file hours.txt with the following contents:
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Topic 19 file input, line based
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Building Java Programs
Presentation transcript:

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

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?

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?

Hours answer (flawed) import java.io.*; // for File import java.util.*; // 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)");

Flawed output The inner while loop is grabbing the next person's ID. 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

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... }

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)");

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)

Confusion w/ nextLine Using nextLine in conjunction with the token-based methods on the same Scanner can cause odd results. 23 3.14 Joe "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()); // 23 System.out.println(input.nextDouble()); // 3.14 System.out.println(input.nextLine()); // But the nextLine call produces no output! Why?

Mixing lines and tokens Don't read both tokens and lines from the same Scanner: 23 3.14 Joe "Hello world" 45.2 19 input.nextInt() // 23 23\t3.14\nJoe\t"Hello world"\n\t\t45.2 19\n ^ input.nextDouble() // 3.14 23\t3.14\nJoe\t"Hello world"\n\t\t45.2 19\n ^ input.nextLine() // "" (empty!) 23\t3.14\nJoe\t"Hello world"\n\t\t45.2 19\n ^ input.nextLine() // "Joe\t\"Hello world\"" 23\t3.14\nJoe\t"Hello world"\n\t\t45.2 19\n ^

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: 12\nSideshow Bob After nextInt(): 12\nSideshow Bob ^ After nextLine(): 12\nSideshow Bob ^

Array traversals, text processing reading: 7.1, 4.4 self-check: Ch. 7 #8, Ch. 4 #19-23

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

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 1 2 3 4 5 value 'M' 'r' '.' ' ' 'E'

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!"); }

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);

Section attendance problem Consider an input file of course attendance data: 111111101011111101001110110110110001110010100 111011111010100110101110101010101110101101010 110101011011011011110110101011010111011010101 Each line represents a section (5 students, 9 weeks). 1 means the student attended; 0 means absent. 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

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]

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)

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(); ...

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;

File input/output reading: 6.4 - 6.5

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?

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: "); 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

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).

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.

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]

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(); ...