name: inverse layout: true class: taylor msoe --- class: center, middle .title[ # File IO ] ??? * **P** speaker view * **C** clone slideshow * **?** help --- # File IO * `java.nio.file.Path` is an interface used to locate a file/directory in a file system -- * `Path.of(String)` — Returns a `Path` object -- * `java.nio.file.Files` is a class with a number of useful class methods for reading/writing small files: -- + `Files.readAllLines(Path)` — Returns `List
` of all lines in the file + `Files.write(Path, Iterable
)` — Writes a `List
` containing lines of `String`s to the file --- # Checked Exceptions * When working with files, must handle checked exceptions (`IOException`) -- * Two ways to handle a checked exception: + Catch the exception + Explictly declare that your method potentially throws the checked exception --- # Input/Output Streams * [`InputStream`](http://javadoc.taylorial.com/java.base/io/InputStream.html)s and [`OutputStream`](http://javadoc.taylorial.com/java.base/io/OutputStream.html)s can be used to move data into and out of a Java program. -- * Abstract classes with one abstract method: + [`read()`](http://javadoc.taylorial.com/java.base/io/InputStream.html#read%28%29) — Reads the next byte of data from the input stream + [`write()`](http://javadoc.taylorial.com/java.base/io/OutputStream.html#write%28int%29) — Writes the specified byte to the output stream -- * Subclasses for different data sources: + `AudioInputStream` + `ByteArrayInputStream` + `FileInputStream` + `FilterInputStream` + `ObjectInputStream` --- # Streams with Files * `Files` class provides methods for obtaining streams attached to files: + `Files.newInputStream(Path)` — Returns an `InputStream` attached to the file + `Files.newOutputStream(Path)` — Returns an `OutputStream` attached to the file --- # Write Raw Bytes to Binary File ``` public static void writeByte(Path path, int data) throws IOException { try (OutputStream out = Files.newOutputStream(path)) { out.write(data); } } public static byte readByte(Path path) throws IOException { try (InputStream in = Files.newInputStream(path)) { return (byte)in.read(); } } ``` -- * `writeByte(Path.of("stuff.bin"), 72)`; creates file with `0b01001000` in it. -- * Using try-with-resources causes file to be closed when `try` block completes -- * File closed even if exception propogates up to calling method --- # Open Options * Can specify zero or more open options when requesting a new stream: `newOutputStream(Path, OpenOption...)` -- * `...` after `OpenOption` indicates zero or more OpenOption objects may be passed -- * Appears as an array in the method implementation -- * `Files.newOutputStream(path);` — overwrite existing file, create if doesn't exist -- * `Files.newOutputStream(path, APPEND);` — append to existing file, fail if doesn't exist -- * `Files.newOutputStream(path, CREATE, APPEND);` — append to existing file, create if doesn't exist -- * `Files.newOutputStream(path, CREATE_NEW);` — fail if existing file, create if doesn't exist --- # `OpenOption` Interface * Empty interface - relies on implementing classes -- * `StandardOpenOption` — Enumerates standard opening options: `APPEND`, `CREATE`, `CREATE_NEW`, `READ`, `TRUNCATE_EXISTING`, `WRITE`, etc... -- * Must use static imports to reference open options directly: ``` import static java.nio.file.StandardOpenOption.APPEND; public static void writeAnotherByte(Path path, int data) throws NoSuchFileException, IOException { try (OutputStream out = Files.newOutputStream(path, APPEND)) { out.write(data); } } ``` --- # Decorator Classes * Decorator classes encapsulate a stream within an provide additional functionality + `DataInputStream` — Read primitive types from binary file + `CipherInputStream` — Read from an encrypted file + `ZipInputStream` — Read from a `.zip` compressed file + `GZIPInputStream` — Read from a `.gzip` compressed file -- * Text input/output + `Scanner` — Read text from input stream + `PrintWriter` — Write text to output stream --- # High-level Binary I/O * Decorate/wrap `InputStream` in a `DataInputStream` * Decorate/wrap `OutputStream` in a `DataOutputStream` -- * Gain access to read/write methods for primitives + `readBoolean()`, `readByte()`, `readChar()`, `readDouble()`, `readFloat()`, `readInt()`, etc... + `writeBoolean(boolean)`, `writeByte(int)`, `writeChar(int)`, etc... -- ``` public static void writeDouble(Path path, double data) throws IOException { try (OutputStream out = Files.newOutputStream(path); DataOutputStream dOut = new DataOutputStream(out)) { dOut.writeDouble(data); } } public static double readDouble(Path path) throws IOException { try (DataInputStream in = new DataInputStream(Files.newInputStream(path))) { return in.readDouble(); } } ``` --- # Text I/O * Much like using `System.in` and `System.out` -- ``` public static void writeLine(Path path, String line) throws IOException { try (PrintWriter out = new PrintWriter(Files.newOutputStream(path))) { out.println(line); } } public static String readLine(Path path) throws IOException { try (Scanner in = new Scanner(Files.newInputStream(path))) { return in.nextLine(); } } ``` --- # Object I/O * `ObjectOutputStream` and `ObjectInputStream` classes provide the ability to send entire objects as blobs of data via a stream * The object to be written/read to/from the stream must implement the `Serializable` interface * Care should be taken when reading/writing objects since it introduces security concerns -- ``` public static void writeDate(Path path, Date date) throws IOException { try (ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(path))) { out.writeObject(date); } } public static Date readDate(Path path) throws ClassNotFoundException, IOException { try (ObjectInputStream in = new ObjectInputStream(Files.newInputStream(path))) { return (Date)in.readObject(); } } ``` --- # Buffered Reader/Writer * `Files` class also provides methods for obtaining a buffered reader or writer attached to files: + `Files.newBufferedReader(Path)` — Returns a `BufferedReader` attached to the file + `Files.newBufferedWriter(Path)` — Returns a `BufferedWriter` attached to the file -- * `BufferedReader` and `BufferedWriter` read/write text from a buffered character stream. -- * Without buffering, each invocation of `read()` could cause bytes to be read from the file (requiring interaction with the OS) -- * OS interaction requires significant overhead. -- * Buffered I/O can be significantly more efficient.