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