Download presentation
Presentation is loading. Please wait.
1
Lecture 20 File I/O D&D 14 Date
2
Goals By the end of this lesson, you should:
Retrieve metadata about files and directories with Java Be able to write text to and read text from text files. Be able to write serialized Java objects to binary files and read such objects from file. Be able to write and read arbitrary binary values to and from binary files.
3
Files and Streams in Java
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary Files in Java are simply streams of bytes. Writing a file means opening a stream and writing to it. Reading a file means opening a stream and reading from it. Purely byte-based streams are called binary files. Often, we will interact with text files, where the underlying byte stream is made up of characters, each of which is made up of two bytes – the size of the char type in Java. Interaction with files and directories takes place via the packages: java.io – Java’s “traditional” I/O classes and interfaces java.nio – Java’s “new” I/O classes and interfaces
4
Directories and File Metadata
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary The Paths class provides static methods that let us create objects implementing the Path interface, e.g., like so: Objects with the Path interface let us query, manipulate and convert paths: String s = path.getFileName(); boolean b = path.isAbsolute(); Path ap = path.toAbsolutePath(); Scanner keyboardInput = new Scanner(System.in); System.out.println("Enter a file or directory name:"); Path path = Paths.get(keyboardInput.nextLine());
5
Directories and File Metadata
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary The Files class provides static methods that let us access information about objects with the Path interface: boolean b = Files.exists(path); boolean isDir = Files.isDirectory(path); long size = Files.size(path); FileTime ft = Files.getLastModifiedTime(path); DirectoryStream<Path> ds = new Files.newDirectoryStream(path); A DirectoryStream<Path> object provides an iterable data structure of objects with the Path interface (much like an ArrayList). See the RecursiveDirectoryReader Java example.
6
Writing to text files File and directory info Text files
Serializing Java objects into binary files Reading/ writing binary files Summary import java.util.Formatter; import java.util.FormatterClosedException; import java.io.FileNotFoundException; import java.lang.SecurityException; … Formatter output = null; try { output = new Formatter(“myfile.txt"); } catch (SecurityException secExc) { System.err.println("Can't write to myfile.txt!"); System.exit(1); catch (FileNotFoundException fnfExc) { System.err.println("Can't find path to myfile.txt!"); } output.format("%s\n", stringToWrite); output.format("%s %d\n", anotherStringToWrite, anInt); output.close(); The Formatter class opens a text file for (over)writing. Multiple calls to its format() method do the actual writing (much like printf()). After writing, close() the Formatter.
7
Reading from text files
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary import java.util.Scanner; import java.io.IOException; … Scanner input = null; try { input = new Scanner(Paths.get("myfile.txt")); } catch (IOException ioExc) { // Nothing to do: File doesn't exist or isn't readable return; while (input.hasNext()) { // While there is data left.. String currentLine = input.nextLine(); // … read a line … // Do something with the line Open a text file with an object from our well-known Scanner class. The same methods, such as next() or nextLine() etc. that work for input streams from the console work for files, too. The hasNext() method checks whether there is any data left in the file that we haven’t read yet.
8
Example File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary The next version of our photo Album application can store image names, captions and paths to the image files in a text file. Simple concept: One photo record per line, with the different photo properties separated by commas. But: What do we do if a name or caption contain commas? Answer: Put a backslash in front of the comma, so we know this is not a separator comma. But: What do we do if a name or caption spans multiple lines? Answer: We can again use backslash escapes. Writing such a file is easy, reading a little harder. We will meet regular expressions again!
9
Binary files and objects
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary A common task in file I/O in Java applications is to save objects to files. Turning an object into a sequence of bytes that can be written to a file is called serialization. We will assume for simplicity that our objects’ classes will have no static variables. To be able to serialize an object, its class must implement the Serializable interface. This is a so-called tagging interface. This means we don’t have to implement any methods, provided all of its instance variables are either primitives or implement Serializable. If our class has instance variables that do not implement Serializable, we need to do extra work. In the following, we will use a modified version of our Album application, which stores the image, image icon, names and caption of each image in a single AlbumImage object.
10
A serializable class (I)
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary import java.awt.Image; import java.io.File; import java.io.Serializable; import java.io.ObjectStreamField; import java.io.IOException; import javax.swing.ImageIcon; public class AlbumImage implements Serializable { private Image image; // Image isn't Serializable private ImageIcon icon; // but ImageIcon is // (and contains an Image) private String caption; private String name; private String path; // Identify which fields should be serialized private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("icon", ImageIcon.class), new ObjectStreamField("caption", String.class), new ObjectStreamField("name", String.class), new ObjectStreamField("path", String.class) }; …
11
A serializable class (II)
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary … // This method gets called upon serialization private void writeObject(java.io.ObjectOutputStream stream) throws IOException { // Save full size image to a new icon to store // Remember, Image is not serializable but ImageIcon // is, and ImageIcon wraps an Image. icon = new ImageIcon(); icon.setImage(image); stream.defaultWriteObject(); } // This method gets called upon deserialization private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); // calls default constructor image = icon.getImage(); // additional configuration // (here: restore image) If we have non-serializable instance variables that need to be packed up before or restored after serialization, we can implement these two methods in the class to assist us.
12
A serializable class (III)
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary … // A default constructor is required for deserialization. // It needs to initialize all serialized fields. public AlbumImage() { path = ""; icon = new ImageIcon(); name = ""; caption = ""; } // Overloaded constructor for use in application public AlbumImage(File f, String name) { path = f.getAbsolutePath(); icon = new ImageIcon(path); image = icon.getImage(); this.name = name;
13
Opening an ObjectOutputStream
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary // Step 1: Open file for writing with an ObjectOutputStream ObjectOutputStream output = null; try { output = new ObjectOutputStream( Files.newOutputStream(Paths.get("album.bin"))); } catch (IOException ioExc1) { System.err.println("Can't open album.bin for writing!"); return; // Can’t save, but doesn’t crash the application … The ObjectOutputStream constructor throws an IOException if it is unable to open the file for writing (path to the file doesn’t exist or file is read-only). In this case, our Album can continue to run – we just can’t save the images for later startups. Challenge: Add a pop-up notice to alert the user.
14
Writing to the ObjectOutputStream
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary // Step 2: Write all entries to file (need to rewrite the // whole file) try { for (int i=0; i<images.size(); i++) { // Write AlbumImage objects to file: output.writeObject(images.get(i)); } catch (IOException ioExc2) { System.err.println("Unable to write to album.bin!"); … The writeObject() method also throws an IOException if it is unable to serialize the object passed to it as a parameter. In this case, our Album can also continue to run – we just won’t save the images again. If the objects in images are not serializable, then this is a problem with the code, not the file system! That is, there is no point telling the user. You as a developer need to fix it!
15
Writing to the ObjectOutputStream
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary // Step 3: Close the file try { output.close(); // prevent resource leak } catch (IOException ioExc3) { System.err.println("Unable to close album.bin!"); … This is the last step. Only by closing the ObjectOutputStream can we assure that the file is truly closed. This is especially important when we write to files that are on external media such as USB sticks.
16
Taking stock File and directory info Text files
Serializing Java objects into binary files Reading/ writing binary files Summary Our AlbumImage objects are now stored in the file in serialized format. This format contains information about the class of each object we have stored. When we want to read the objects from file, we need to ensure that we map them to the same class. In our Album application, this is not an issue, but in large systems, we need to ensure that we can uniquely identify that class and version of the class. For this purpose, we can give the class a static final long serialVersionUID i.e., a constant that reflects the class and / or version.
17
Opening an ObjectInputStream
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary // Step 1: Open an ObjectInputStream for the file ObjectInputStream input = null; try { input = new ObjectInputStream( Files.newInputStream(Paths.get("album.bin"))); } catch (IOException ioExc1) { // File doesn't exist or isn't readable // - nothing to load here return; … The ObjectInputStream constructor throws an IOException if it is unable to open the file for reading (path to the file doesn’t exist or no read permission for file). In this case, our Album can also continue to run – we just can’t read the images. Challenge: Add a pop-up notice to alert the user.
18
Reading from an ObjectInputStream
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary // Step 2: File is open, now read object by object until // we get an EOFException try { while (true) { AlbumImage image = (AlbumImage) input.readObject(); images.add(image); currentImageIndex = 0; } catch (EOFException eofExc) { // Nothing to do here catch (ClassNotFoundException cnfExc) { System.err.println("Class AlbumImage not found!"); catch (IOException ioExc) { System.err.println("Unable to read from album.bin!"); System.exit(1); … Note that we have to take care of three possible exceptions here, one of which we actually use for flow control…
19
Closing the ObjectInputStream
File and directory info Text files Serializing Java objects into binary files Reading/ writing binary files Summary // Step 3: Close the stream try { input.close(); } catch (IOException ioExc2) { System.err.println("Unable to close album.bin!"); System.exit(1); … This is the last step.
20
Other binary files File and directory info Text files
Serializing Java objects into binary files Reading/ writing binary files Summary Often, we’ll need to write or read binary files that don’t contain serialized Java objects. We can do so by using: A DataOutputStream instead of an ObjectOutputStream A DataInputStream instead of an ObjectInputStream Opening these streams is identical to their object versions. When writing to a DataOutputStream, we need to decided in which format we want to write the data. Methods available include writeByte(), writeInt(), writeDouble() etc. – too many to list here. Reading from a DataInputStream is done analogously with methods such as readByte(), readInt(), readDouble() etc. that return values of the respective types. See the MyByteWriter and MyByteReader examples.
21
What do we know File and directory info Text files
Serializing Java objects into binary files Reading/ writing binary files Summary The Java classes Path, Paths, Files, and DirectoryStream give us access to metadata of files and the directory structure. The Formatter and Scanner classes let us write and read text file data. Regular expressions help us parse input. Objects of classes that implement the Serializable interface can be stored sequentially in binary files. Implementing the Serializable interface does not mandate any methods, but we must ensure that either all instance variables in the object are serializable, or we need to specify which ones are to be serialized with the object. Serializable classes need a default constructor and may implement the writeObject() and readObject() methods to ensure correct serialization and deserialization. We can write and read arbitrary binary files with DataOutputStream and DataInputStream. Caution: Exceptions are being thrown all over the place and want to be handled!
22
Resources & Homework File and directory info Text files
Serializing Java objects into binary files Reading/ writing binary files Summary D&D Chapter 15 Serialization is a complex subject that goes beyond our treatment here: DataOutputStream and DataInputStream:
23
Next Lecture Sockets 1 (not in D&D)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.