Explain how to use basic I/O.
References:
Basic I/O
Reading and writing files in Java (Input/Output) - Tutorial
1. I/O Streams
- An I/O Stream represents and input source or an output destination.
- A stream is a sequence of data.
input stream
: is used to read data from source, once item at a time.outputs stream
: is used to write data to a destination, once item |at a time.
--stream-->
0101010101...
---------->
-
java.io package
-
Streams:
- Byte streams:
InputStream/OutputStream/FileInputStream/FileOutputStream
- Character streams:
Reader/Writer/FileReader/FileWriter
- Buffered streams:
BufferedReader/BufferedWriter/BufferedInputStream/BufferedOutputStream
- Byte streams:
-
Scanner:
Scanner.java
-
Formatter:
sys.printf/String.format
-
Always close streams.
-
Line Terminator:
- a carriage-return/line-feed sequences
\r\n
- a single carriage-return
\r
- a single line-feed
\n
- a carriage-return/line-feed sequences
1.1. Bytes Streams
-
Bytes Streams is used to perform input and output of
8-bit bytes
. -
All other stream types are built on byte streams.
-
All byte stream classes are descended from
InputStream.java
andOutputStream.java
-
Examples:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyBytes {
public static void main(String[] args) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("xanadu.txt");
out = new FileOutputStream("outagain.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
1.2. Character Streams
-
Character values is stored using Unicode conventions.
-
Character stream I/O automatically translates this internal format to and from the local character set.( E.g: Western: ASCII, Japan:Shift-JIS)
-
All character stream classes are descended[dɪˈsend] from
Reader.java
andWriter.java
-
Example:
private boolean writeXmlFile(Map<String, String> object, IPath filePath) {
try (FileOutputStream outputStream = new FileOutputStream(filePath.toFile())) {
XMLStreamWriter writer = XMLOutputFactory.newFactory().createXMLStreamWriter(outputStream,
StandardCharsets.UTF_8.name());
writer.writeStartDocument(StandardCharsets.UTF_8.name(), "1.0"); //$NON-NLS-1$
writer.writeStartElement("A");
writer.writeAttribute("xmlns:i", "http://www.w3.org/2001/XMLSchema-instance");
writer.writeAttribute("xmlns", "http://schemas.microsoft.com/2003/10/Serialization/Arrays");
for (Map.Entry<String, String> entry : object.entrySet()) {
writer.writeStartElement("A");
writer.writeStartElement("A");
writer.writeCharacters("A");
writer.writeEndElement();
writer.writeStartElement("A");
writer.writeCharacters("A");
writer.writeEndElement();
writer.writeEndElement();
}
writer.writeEndElement();
writer.writeEndDocument();
writer.flush();
return true;
} catch (IOException | XMLStreamException e) {
System.out("Error writing XML file", e); //$NON-NLS-1$
}
return false;
}
=> They are using the int variable to store the temp value.However, CopyBytes: int variable hold its last 8 bits , CopyCharacters hold 16bits.
UTF-8 là một encoding để biểu diễn ký tự Unicode dưới dạng 1–4 bytes. Ví dụ: Ký tự ASCII ‘A’ → 0x41 → lưu 1 byte trong file. Ký tự ‘é’ (U+00E9) → UTF-8 là 11000011 10101001 → lưu 2 byte. Ký tự ‘𠜎’ (U+2070E) → UTF-8 là 11110000 10100000 10011100 10001110 → lưu 4 byte. => Chung ta can encode/decode dung.
1.3. Buffered Streams
-
The unbuffered IO are much less efficient because they call directly to the OS/native I/O (triggers disk access etc.) => Should use the buffered IO streams to reduce system call -> faster for most of use cases
-
BufferedReader/BufferedWriter
: create bufferedcharacter streams
-
BufferedInputStream/BufferedOutputStream
: create the bufferedbytes streams
-
Flushing buffered streams: to write out a buffer
- the buffer full
- close stream
- flushing the buffer (.flush)
- auto flushing (.
println
orformat
)
1.4. Scanning and Formatting
- Scanning: API breaks input into individual tokens associated with bits of datas
- Formatting: API assembles data into nicely format, human-readable
1.4.1 Scanning: Scanner.java
- Breaking Input into Tokens: by default, we uses a scanner uses while space to separate tokens
- We can use a different token separator, invoke
useDelimiter()
, specifying a regular expression.
1.4.2 Formatting:
-
Bytes stream class:
PrintStream
, syserr,sysout , using String e.g.System.out.println("The square root of " + i + " is " + r + ".")
-
Character stream class:
PrintWriter
, printf, using formatSystem.out.format("The square root of %d is %f.%n", i, r)
-
%x
: conversions -
In the Java programming language, the
\n
escape always generates the linefeed character (\u000A). Don’t use\n
unless you specifically want a linefeed character. To get the correct line separator for the local platform, use%n
.
2. File I/O
- java.nio package
2.1. Path
- File systems store the files in a tree structure, included: One root nodes and files and directories (folders), subdirectories(subfolders)
- Delimiter is the character to separate the directories names: linux OS uses the
forwardslash
(/), windows using thebackslash
() - Root:
/
orC:\
- Folders:
/home/phong/myfolder
orC:\phong\myfolder
=> Path used to identify a file through the system file.
2.2. Relative/ Absolute:
- A path is either relative or absolute.
- Absolute path always contains the root element. e.g.
/home/phong/myfolder
- Relative needs to be combined with another path in order to access file. e.g.g
/phong/foo
2.3. Symbolic link
- A symbolic link is a special file that serves as a reference to another file.
- Reading or writing to a symbolic link is the same as reading or writing to any other file or directory. For example, resolving
logFile
yieldsdir/logs/HomeLogFile
(actual)
2.4. java.nio.file.Path.java
-
Path.java
: A Path instance contains the information used to specify the location of a file or directory -
Paths.java
: Helper class -
- Creating a Path
-
- Retrieving information
-
- Removing redundancies
-
- Converting a path
-
- Joining two paths
-
- Create a Path between two paths
-
- Comparing two paths
// 1. Creating a path
// String filePath = "resources/files"; // forward-slash
String filePath = "resources\\files"; // back-slash
Path path = Paths.get(filePath);
// 2. Retrieving the info
System.out.format("toString: %s%n", path.toString());
// 3. Removing Redundancies From a Path
// Path path.normalize();
// 4. Converting a Path
// path.torUr()
// 5. Joining two paths
Path parentPath = Paths.get(filePath);
String subFolderName = "subfolder";
Path subPath = parentPath.resolve(subFolderName);
System.out.format("subPath toString: %s%n", subPath.toString());
// 6. Creating a path between two paths
Path path1 = Paths.get("path1");
Path path2 = Paths.get("path2");
Path p2_to_p1 = path2.relativize(path1); // get relative path1 from path2
System.out.format("p2_to_p1 toString: %s%n", p2_to_p1.toString());
// 7. Comparing two paths
if (path1.equals(path2)) {
} else if (path1.endsWith(path2)) {
} else if (path1.startsWith(path2)) {
}
2.5. java.nio.file.Files.java
-
This class offers a rich set of static methods for reading, writing, and manipulating files and directories.
-
The methods works on instances of Path objects.
-
- Checking a File or Directory
-
- Deleting a File or Directory
-
- Copying a File or Directory
-
- Moving a File or Directory
public class FileOperations {
public static void main(String[] args) throws IOException {
// 1. Checking Files or Directory:
// Checking exist
Path path = Paths.get("resources/files");
if (Files.exists(path)) {
System.out.println(path.toString() + " is exist !!");
}
// Checking Accessis
boolean isRegularFile = Files.isDirectory(path) && Files.isReadable(path) && Files.isWritable(path);
if (isRegularFile) {
System.out.println(path.toString() + " is regular");
}
// Checking whether two paths locate the sample file
Path p1 = Paths.get("resources/files");
Path p2 = Paths.get("resources/files");
if (Files.isSameFile(p1, p2)) {
// Logic when the paths locate the same file
System.out.println("They are location the same file");
}
// 2. Deleting
try {
// Files.delete(p1);
} catch (Exception e) {
// TODO: handle exception
}
// 3. Copying
// Files.copy(source, target, REPLACE_EXISTING);
// 4. Moving
// Files.move(source, target, REPLACE_EXISTING);
}
}
2.5.1. Managing Metadata (File and File Store Attributes)
2.5.2 Reading, Writing, and Creating Files
-
There are a wide array of file I/O methods to choose
ReadAllBytes/ReadAllLines
: commonly used, small filesnewBuffedReader/newBufferedWriter
: text filesnewInputStream/newOutputStream
: streams, unbuffered,newByteChannel
: channel and byte buffersFileChannel
: advanced,file-locking
-
Creating regular/temporary files
-
Creating files:
Path file = ...;
try {
// Create the empty file with default permissions, etc.
Files.createFile(file);
} catch (FileAlreadyExistsException x) {
System.err.format("file named %s" +
" already exists%n", file);
} catch (IOException x) {
// Some other sort of failure, such as permissions.
System.err.format("createFile error: %s%n", x);
}
2.5.3 Walking the File Tree
- This will recursively visit all the files in a file tree.
- Create the FileVisitor
FileVisitor Interface
: interface has four methodspre/postVisitDirectory
:Invoked before/after a directory’s entries are visited.visitFile
: invoked on the file being visitedvisitFileFailed
: invoked when the file cannot be accessed.
SimpleFileVisitor
: class which implements FileVisitor interface, we can extend this
- Kickstarting the process
Path startingDir = ...;
PrintFiles pf = new PrintFiles();
Files.walkFileTree(startingDir, pf);
2.5.4 Others
-
- Random Access Files
-
- Creating and Reading Directories
-
- Links, Symbolic or Otherwise
-
- Finding Files
-
- Watching a Directory for Changes
-
- Other Useful Methods
-
- Legacy File I/O Code