Files And Streams
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 1
File and Stream Overview Java has a rich set of classes to manipulate input and output. These are found in package java.io • Unless noted otherwise, classes below are part of package java.io A stream is simply data that is read or written in an ordered way. The methods used for input and output to files are very similar to the methods used for console input and output. • In fact, package System has setIn, setOut, and setErr methods that let the programmer redirect these streams. Similarly, these methods may be used for other forms of input and output. In examining files used for input and output, one thing to keep in mind is that Java Strings are represented as Unicode. • This represents a very wide variety of internationally used character sets. • Depending on the type of stream used, this may make ASCII tools hard to use Example: • Writing the string “Hello” as bytes (lowest 8-bits): —Hello
• Writing the string “Hello” as Chars (Unicode): — \0 H \0 e \0 l \0 l \0 o
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 2
URLs and URIs Files in Java can be named by • OS-specific names “c:\\java\\homework6\\data\\madlib.txt” • Constructed paths / => c => java => home => xyz.txt • Uniform Resource Locators “http://www.du.edu/~mschwart/” (web pages) • Uniform Resource Identifiers “file:/c:/java/homework6/data/madlib.txt” (others schemes)
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 3
Specifying A File One basic way of creating a stream is to start with a File Files may be constructed with one of 4 constructors • File(String pathname) • File(URI uri) • File(String parent, String child) • File(File parent, String child) Once the File is constructed, many operations are available, some below: • boolean canRead() True if the file may be read • boolean canWrite() True if the file may be written • boolean exists() True if the file exists • boolean isFile() True if the file is a regular file • boolean isDirectory() True if the file is a directory • long length() The length (in bytes) of the file. 0 if a directory • String[] list() The list of filenames in the directory, if it is a directory • File[] listFiles() The list of filenames in the directory, if it is a directory • boolean delete() Delete the file • void deleteOnExit() Delete the file upon exit • boolean renameTo(File f) Rename the file 1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 4
The java.io Streams
Diagram from http://www.particle.kth.se/~lindsey/JavaCourse/Book/index.html
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 5
Other Java I/O Packages ● java.io • Primary Java I/O classes ● java.nio, java.nio.* • A new set of packages (Java 1.4) that use channels to represent an open connection to a hardware device, file, or other entity. The central abstractions of the NIO APIs are — Buffers, which are containers for data; — Charsets and their associated decoders and encoders, which translate between bytes and Unicode characters; — Channels of various types, which represent connections to entities capable of performing I/O operations; and — Selectors and selection keys, which together with selectable channels define a multiplexed, non-blocking I/O facility.
● java.net • I/O over the network ● java.util.zip • Methods for representing and manipulating compressed ZIP and GZIP files. ● java.util.jar • Methods for reading from and writing to JAR files. ● javax.imageio, javax.imageio.* • Image I/O, including the encoding/decoding of images in particular formats. 1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 6
What About Writing Files? import java.io.*; public class File1 { public static void main(String[] args) { String [] myArgs = args; if ( myArgs == null || myArgs.length == 0 ) { myArgs = new String[1]; Note: PrintWriter is myArgs[0] = "Hello"; like System.out } try { PrintWriter out = new PrintWriter("output1.txt"); for ( String arg: myArgs) out.println(arg); out.close(); } catch (FileNotFoundException fnfe ) { System.out.println("Can't open file output1.txt: " + fnfe); } // continued on next page
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 7
Writing Continued try { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("output2.txt")); Note: for ( String arg: myArgs) out.writeBytes(arg); ObjectOutputStreams out.close(); do either byte or } catch (FileNotFoundException fnfe ) { character input/ output System.out.println("Can't open file output2.txt: " + fnfe); } catch (IOException ioe) { System.out.println("Can't open file output2.txt: " + ioe); } try { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("output3.txt")); for ( String arg: myArgs) out.writeChars(arg); out.close(); } catch (FileNotFoundException fnfe ) { System.out.println("Can't open file output3.txt: " + fnfe); } catch (IOException ioe) { System.out.println("Can't open file output3.txt: " + ioe); } 1/24/2016
}
© 2016, Schwartz Computer Consulting Services
Java
Slide 8
Formatter In addition to the stream output methods, one may also format output for text output. The Formatter class (java.util) has the same options as printf, to make output straightforward A Formatter may be constructed with a filename or a File object. By default, the Formatter outputs to a StringBuffer. Of course, the toString() method can be used to format output for many purposes using the same tools In this context, it is also worth noting that Dates can be formatted for both reading and writing very flexibly using SimpleDateFormat (java.text). This is especially useful for formatting Dates in locale-relevant ways, and reading dates in one of a variety of standard formats. It is also worth noting that number formats may be well-regulated for reading and writing using NumberFormat and DecimalFormat (java.text), and especially for displaying numbers in locale-relevant ways.
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 9
Reading Records The Scanner class may be used to parse a sequential file back into the objects it represents Scanners are constructed on Files, Streams, or even Strings. Scanners have many methods—here are a few important ones: • hasNext(), hasNextInt(), hasNextDouble(), hasNextFloat(), etc. — Boolean methods to determine if more input is available
• next(), nextInt(), nextDouble(), nextFloat(), etc. — Retrieve next input, or input of a given type
• close() — Close the Scanner for future operations
• skip() — Discard the input matching the provided pattern
• useDelimiter — Sets the delimiter used to split tokens from the input.
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 10
Writing and then Reading From A File ● Once data has been written to a file, how can it be retrieved and used to build the internal objects again? ● There are a couple approaches to this: • The Textual way: — Write text representations of the objects to the file — Read the file back as text (usually one line at a time) — Parse the text — Provide the text, or simple conversions of the text, to appropriate constructors
• The Binary (object) way: — Serialize the object and write it to a file — Read back the object
● The “Binary” way is the same way used to transfer Java objects around the network. ● We will discuss examples of both mechanisms following
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 11
Text Example (part 1) import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.PrintStream; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.LinkedList; import java.util.List; public class EmployeeText { private static List employeeList = new LinkedList(); private static final String filename = "employeeTextList.dat"; private String name; private long id; private int department; private Date birthday;
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 12
Text Example (part 2) public static EmployeeText[] getEmployees() { return employeeList.toArray(new EmployeeText[0]); } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } public int getDepartment() { return department; } public void setDepartment(int department) { this.department = department; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String toString() { SimpleDateFormat dFormat = new SimpleDateFormat("dd MMM yyyy"); return String.format("Name: %-20s; Id: %09d; Dept: %5d; Birthday: %s", name, id, department, dFormat.format(birthday)); } public EmployeeText(String name, long id, int department, Date birthday) { this.name = name; this.id = id; this.department = department; this.birthday = birthday;
employeeList.add(this); } 1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 13
Text Example (part 3) static public void readEmployees() { try { BufferedReader in = new BufferedReader(new FileReader(filename)); String line; while ( (line = in.readLine()) != null) { // Really simple for now // Name is at index 1, id at index 3, department at index 5, and birthday at index 7 String[] parts = line.split("[:;]"); EmployeeText e = new EmployeeText(parts[1].trim(), Long.parseLong(parts[3].trim(),10), Integer.parseInt(parts[5].trim(),10), new SimpleDateFormat("dd MMM yyyy").parse(parts[7].trim())); } in.close(); } catch (FileNotFoundException e) { System.err.println("Can't open input file"); } catch (IOException e) { System.err.println("Can't read input file"); } catch (NumberFormatException e) { System.err.println("Can't parse number in input: "+e); e.printStackTrace(); } catch (ParseException e) { System.err.println("Can't parse date in input: "+e); e.printStackTrace(); } 1/24/2016 } © 2016, Schwartz Computer Consulting Services
Java
Slide 14
Text Example (part 4) static public void writeEmployees() { PrintStream out; try { out = new PrintStream(filename); for ( EmployeeText e: employeeList ) { out.println(e); } out.close(); } catch (FileNotFoundException e1) { } } static public void printEmployees() { for ( EmployeeText e: employeeList ) { System.out.println(e); } }
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 15
Text Example (part 5) public static void main(String[] args) { Calendar c = Calendar.getInstance(); EmployeeText e; c.set(1954, 4, 15); e = new EmployeeText("Michael Schwartz", 22446, 300, c.getTime()); c.set(1984, 8, 5); e = new EmployeeText("Aaron Schwartz", 1555522, 212, c.getTime()); c.set(2007, 0, 1); e = new EmployeeText("Baby January", 2333422, 900, c.getTime()); System.out.println("Before: ");
printEmployees(); writeEmployees(); // Since our objects will not maintain identity, we'll have to empty our cache....
employeeList.clear(); readEmployees(); System.out.println("After: (should be identical)");
printEmployees(); }
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 16
Text Example (end) Before: Name: Michael Schwartz
; Id: 000022446; Dept:
300; Birthday: 15 May 1954
Name: Aaron Schwartz
; Id: 001555522; Dept:
212; Birthday: 05 Sep 1984
Name: Baby January
; Id: 002333422; Dept:
900; Birthday: 01 Jan 2007
After: (should be identical) Name: Michael Schwartz
; Id: 000022446; Dept:
300; Birthday: 15 May 1954
Name: Aaron Schwartz
; Id: 001555522; Dept:
212; Birthday: 05 Sep 1984
Name: Baby January
; Id: 002333422; Dept:
900; Birthday: 01 Jan 2007
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 17
Serializable If the file need not be human-readable, Java provides facilities to write and read files in Object format. Such objects should implement interface Serializable. • While this does not require any special methods be implemented, it is highly recommended that the program provide a static final long serialVersionUID to ensure the object can be deserialized portably. Example: import java.io.*; import java.util.Date; import java.util.List; import java.util.LinkedList; import java.util.Calendar; import java.text.SimpleDateFormat; public class Employee implements Serializable { static final long serialVersionUID = 1234321L; private static List employeeList = new LinkedList(); private static final String filename = "employeeList.dat"; private private private private
1/24/2016
String name; long id; int department; Date birthday;
© 2016, Schwartz Computer Consulting Services
Java
Slide 18
Example (part 2) public static Employee[] getEmployees() { return employeeList.toArray(new Employee[0]); } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } public int getDepartment() { return department; } public void setDepartment(int department) { this.department = department; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String toString() { SimpleDateFormat dFormat = new SimpleDateFormat("dd MMM yyyy"); return String.format("Name: %-20s; Id: %09d; Dept: %5d; Birthday: %s", name, id, department, dFormat.format(birthday)); } public Employee(String name, long id, int department, Date birthday) { this.name = name; this.id = id; this.department = department; this.birthday = birthday; employeeList.add(this); 1/24/2016 } © 2016, Schwartz Computer Consulting Services Java Slide 19
Example (part 3) static public void readEmployees() { try { ObjectInputStream in = new ObjectInputStream( new FileInputStream(filename)); employeeList.clear(); Employee e; try { while ( (e = (Employee)in.readObject()) != null ) employeeList.add(e); } catch (EOFException eof) { } in.close(); } catch (FileNotFoundException fnfe ) { System.out.println("Can't open file "+filename+": " + fnfe); } catch (IOException ioe) { System.out.println("Can't open file "+filename+": " + ioe); } catch (ClassNotFoundException cnfe) { System.out.println("Found non-Employee in "+filename+": " + cnfe); } }
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 20
Example (part 4) static public void writeEmployees() { try { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream(filename)); for ( Employee e: employeeList) out.writeObject(e); out.close(); } catch (FileNotFoundException fnfe ) { System.out.println("Can't open file "+filename+": " + fnfe); } catch (IOException ioe) { System.out.println("Can't open file "+filename+": " + ioe); } } public static void printEmployees() { for (Employee e: employeeList) System.out.println(e); }
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 21
Example (main program) public static void main(String[] args) { Calendar c = Calendar.getInstance(); Employee e; c.set(1954, 4, 15); e = new Employee("Michael Schwartz", 22446, 300, c.getTime()); c.set(1984, 8, 5); e = new Employee("Aaron Schwartz", 1555522, 212, c.getTime()); c.set(2007, 0, 1); e = new Employee("Baby January", 2333422, 900, c.getTime()); System.out.println("Before: "); printEmployees(); writeEmployees(); readEmployees(); System.out.println("After: (should be identical)"); printEmployees(); } }
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 22
Example (output) % java -cp . Employee Before: Name: Michael Schwartz ; Id: Name: Aaron Schwartz ; Id: Name: Baby January ; Id: After: (should be identical) Name: Michael Schwartz ; Id: Name: Aaron Schwartz ; Id: Name: Baby January ; Id:
000022446; Dept: 001555522; Dept: 002333422; Dept:
300; Birthday: 15 May 1954 212; Birthday: 05 Sep 1984 900; Birthday: 01 Jan 2007
000022446; Dept: 001555522; Dept: 002333422; Dept:
300; Birthday: 15 May 1954 212; Birthday: 05 Sep 1984 900; Birthday: 01 Jan 2007
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 23
Example (data file) % od -c employeeList.dat 0000000 254 355 \0 005 s r \0 \b E m 0000020 \0 \0 \0 \0 \0 022 325 221 002 \0 0000040 p a r t m e n t J \0 0000060 b i r t h d a y t \0 0000100 / u t i l / D a t e 0000120 m e t \0 022 L j a v a 0000140 S t r i n g ; x p \0 0000160 \0 \0 \0 W 256 s r \0 016 j 0000200 i l . D a t e h j 201 0000220 \0 \0 x p w \b 377 377 377 215 0000240 \0 020 M i c h a e l 0000260 t z s q \0 ~ \0 \0 \0 \0 0000300 \0 027 274 B s q \0 ~ \0 004 0000320 336 k 5 305 x t \0 016 A a 0000340 h w a r t z s q \0 ~ 0000360 \0 \0 \0 \0 \0 # 232 356 s q 0000400 \0 \0 001 017 341 J E x t 0000420 J a n u a r y 0000430
p l o y e e 004 I \0 \n d e 002 i d L \0 \b 020 L j a v a ; L \0 004 n a / l a n g / \0 001 , \0 \0 \0 a v a . u t 001 K Y t 031 003 ( 275 200 E x t S c h w a r \0 324 \0 \0 \0 \0 w \b \0 \0 \0 k r o n S c \0 \0 \0 \0 003 204 \0 ~ \0 004 w \b \0 \f B a b y
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 24
Random Access When a file is made up of regularly sized or spaced records, it is easy to implement a random-access file style on the data RandomAccessFile objects have a seek method that positions input or output at a certain offset in the file (typically a multiple of the object size), and reads or writes a single object at that location.
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 25
How Can I Have A User Choose A File The JFileChooser, in package javax.swing, provides the programmer a convenient way to allow the user to select a file name. Here is a code fragment that allows the user to select any file, adapted from the JFileChooser API: JFileChooser chooser = new JFileChooser(); int returnVal = chooser.showOpenDialog(parent); if ( returnVal == JFileChooser.APPROVE_OPTION ) { System.out.println("You chose to open this file: " + chooser.getSelectedFile().getName()); } // Note: getSelectedFile() returns a File object.
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 26
Adding A File Filter The previous example could add a file filter with the line: • chooser.addFileFilter(myFilter); if I have an object derived from FileFilter (in package javax.swing.filechooser) named myFilter. An example filter class: class ImageFilter extends FileFilter { public static final String[] exts = { ".gif", ".jpg" }; public boolean accept(File f) { if (f.isDirectory()) { // Accept all directories return true; } // Accept files with extensions above String s = f.getName(); for (String ext: exts ) if ( s.endsWith(ext) ) return true; return false; } public String getDescription() { return "Image File Filter (gif, jpg)"; } } 1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 27
What's newish in Files and Streams ● There are a few newly introduced classes and behaviors on files and streams, introduced in Java 7 and beyond that are now relevant to our Java discussion • New form of try • New io
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 28
Try With Resources ● You may guess that one of the “leaks” in Java memory occurs with files that are opened, but not closed. Because of the risk of this, not just with files, but with any resource worth protecting, a new form of the try block was added in Java 7. ● An exerpt from our first example in this set of slides: Original Code
Using try with resources
try { try ( PrintWriter out = new PrintWriter out = new PrintWriter("output1.txt") ) { PrintWriter("output1.txt"); for ( String arg: myArgs) for ( String arg: myArgs) out.println(arg); out.println(arg); } catch (FileNotFoundException fnfe ) { out.close(); System.out.println( } catch (FileNotFoundException fnfe ) { "Can't open file output1.txt: " System.out.println( + fnfe); "Can't open file output1.txt: " } + fnfe); }
Use the try with resources for resources implementing AutoClosable * * which promises to implement “close()” 1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 29
Example with multiple resources public class TryWithResources { private final String inputFileName; private final String outputFileName; public TryWithResources(String in, String out) { inputFileName=in; outputFileName=out; } public int copyFile() throws IOException { int bytesCopied = 0; try( FileInputStream
input
= new FileInputStream(inputFileName);
BufferedInputStream
bufferedInput
= new BufferedInputStream(input);
FileOutputStream
output
= new FileOutputStream(outputFileName);
BufferedOutputStream bufferedOutput = new BufferedOutputStream(output); ) { int data = bufferedInput.read(); while(data != -1){ bufferedOutput.write(data); data = bufferedInput.read(); ++bytesCopied; } } return bytesCopied; }
Package and imports (before class declaration)
package edu.du.ict4361.files; import java.io.*; // 5 imports condensed
Remainder of code is on next slide and in course example
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 30
Example with multiple resources (other code) public final static int copyFile(String fromName, String toName) { int result = 0; try { TryWithResources t = new TryWithResources(fromName,toName); result= t.copyFile(); } catch (IOException ioe) { System.out.println("Can't copy "+fromName+" to "+toName+": "+ioe); } return result; } public static void main(String[] args) { String myIn = "input.txt"; String myOut = "output.txt"; if ( args.length > 1) { myIn = args[0]; myOut = args[1]; } int result = copyFile(myIn,myOut); System.out.println("Copyfile return "+result);
Methods in the class from the previous page, and class end-brace
} } // End of class
1/24/2016
© 2016, Schwartz Computer Consulting Services
Java
Slide 31
Java nio ● As a segue from the program above, used to copy files, the newer revisions of the “new IO” package, java.nio, has this functionality built-in. • copy(Path, Path, CopyOption...) • java.nio.file.Files.copy(inputName, outputName, REPLACE_EXISTING); ● The Java nio package abstracts the Paths, Files, FileSystems, and has added support for alternate file systems and asynchronous I/O.
1/24/2016 © 2016, Schwartz Computer Consulting Services
Java
Slide 32