English
Summary
Conclusions
A file is a sequence of bytes, and its meaning is defined by an agreed format: the encoding, field order, version, and allowed sizes. Path and Files from NIO.2 build paths and perform file operations, and a relative path depends on the process's working directory. Byte streams work with bytes and character streams with characters, and converting between them requires an explicit encoding, usually UTF-8. Resources are closed with try-with-resources, and reading into a buffer takes into account the number of bytes actually received. An existence check does not replace handling the actual failure of an operation, and traversing directories and extracting archives require control of bounds, links, and sizes. A reliable update writes a temporary file and moves it to the target only after checking it. Standard serialization stores an object graph but does not repeat the constructor's validation, so the restored state is checked, and a different format is chosen for untrusted data. A file-processing program is tested in a separate temporary directory with normal, empty, invalid, and truncated data.
Review questions
- How does normalize differ from toRealPath?
- Why is a resource closed even after an exception?
- When do you need a byte stream, and when a Reader?
- Which contract allows a simple split in the CSV example?
- Why must Files.walk be closed?
- What does ATOMIC_MOVE not guarantee on an arbitrary provider?
- Why doesn't Serializable perform all domain validation?
- What limitations does ObjectInputFilter have?