IO stream
File class
File Is an abstract representation of a file or directory path. create File Object just creates a path object in memory and does not mean that files or directories on disk must exist.
constructor
File file1 = new File("d:/lesson/java2601/a.txt");
File file2 = new File("d:/lesson/java2601", "a.txt");
File parent = new File("d:/lesson/java2601");
File file3 = new File(parent, "a.txt");You can use escaped backslashes or forward slashes in Windows path strings.
create files and directories
create a file
File file = new File("d:/lesson/java2601/test/a.txt");
try {
boolean created = file.createNewFile();
System.out.println(created ? "创建成功" : "文件已存在");
} catch (IOException e) {
e.printStackTrace();
}createNewFile() Parent directories that do not exist are not automatically created.
File extensions are often used to help operating systems and applications identify file types, but the extensions themselves do not change file content.
create a directory
mkdir() A single-level directory can only be created when the parent directory already exists.
File directory = new File("d:/lesson/java2601/test/a");
directory.mkdir();mkdirs() You can create multiple levels of missing parent directories at the same time.
File directory = new File("d:/lesson/java2601/test/a/b/c");
directory.mkdirs();create temporary files
File directory = new File("d:/lesson/java2601/test");
try {
File tempFile = File.createTempFile("temp", ".txt", directory);
System.out.println(tempFile);
} catch (IOException e) {
e.printStackTrace();
}The temporary file name prefix requires at least three characters.
common methods
| method | role |
|---|---|
exists() | Determine whether a path exists |
isFile() | Determine whether it is an ordinary document |
isDirectory() | Determine whether it is a directory |
delete() | Delete files or empty directories |
getName() | Get file or directory name |
getParentFile() | Gets the corresponding to the parent path File object |
getPath() | Gets the path form used when constructing the object |
getAbsolutePath() | Gets the absolute path string |
length() | Gets the length of the ordinary file in bytes |
listFiles() | Get direct subitems in the directory |
listFiles() May be returned when the path is not a directory, an IO error occurs, or no access rights are available null, should be checked before use.
File directory = new File("d:/lesson/java2601");
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
System.out.println(file);
}
}File.equals() Comparing whether abstract path names are equal does not automatically add relative paths, symbolic links or include .. All paths are standardized. When you need to compare actual specification paths, you can use the getCanonicalFile(), and process IOException。
recursive
Recursion is when a method calls itself directly or indirectly. Recursion must have clear termination conditions and ensure that each call approaches the termination conditions gradually.
factorial
public static long factorial(int number) {
if (number < 0) {
throw new IllegalArgumentException("阶乘参数不能为负数");
}
if (number <= 1) {
return 1;
}
return number * factorial(number - 1);
}Fibonacci sequence
public static long fibonacci(int number) {
if (number < 0) {
throw new IllegalArgumentException("参数不能为负数");
}
if (number <= 1) {
return number;
}
return fibonacci(number - 1) + fibonacci(number - 2);
}This direct recursion will repeatedly compute a large number of subproblems and is only suitable for demonstrating recursion. Use circular loops or cached results when processing large data.
Recursively find files
public static void findPdfFiles(File path, List<File> result) {
if (path == null || !path.exists()) {
return;
}
if (path.isFile()) {
if (path.getName().toLowerCase().endsWith(".pdf")) {
result.add(path);
}
return;
}
File[] children = path.listFiles();
if (children == null) {
return;
}
for (File child : children) {
findPdfFiles(child, result);
}
}Recursively delete directory
public static boolean deleteRecursively(File path) {
if (path == null || !path.exists()) {
return true;
}
if (path.isDirectory()) {
File[] children = path.listFiles();
if (children == null) {
return false;
}
for (File child : children) {
if (!deleteRecursively(child)) {
return false;
}
}
}
return path.delete();
}When recursively processing directories, you should also be aware of access permissions, symbolic links, and possible stack overflows caused by excessively deep directories. Modern Java projects can also use java.nio.file.Files Provided file tree API.
IO Flow Overview
IO represents input and output. Using program memory as a reference:
- The input stream reads external data into the program.
- The output stream writes program data to external devices.
Classification by data unit
InputStreamandOutputStreamThe system is processed by bytes and is suitable for pictures, audio, video and other binary data.ReaderandWriterThe system processes characters and is suitable for text data.
Character stream requires decoding bytes into characters according to character encoding, or encoding characters into bytes.
Classified by connection target
- Node streams directly connect data sources or targets such as files, memory, and networks, such as
FileInputStream。 - Processing streams wrap other streams and add functions such as buffering, reading and writing data types, and object serialization, such as
BufferedInputStreamandObjectOutputStream。
Processing flows are not necessarily “more advanced” or “faster” than node flows and should be used in combination based on the required functionality.
using step
-
Determine whether input or output.
-
Determine whether to process bytes or characters.
-
Select the node flow corresponding to the actual data source.
-
Increase buffering, transcoding, or object processing streams as needed.
-
use
try-with-resourcesClose resources in a timely manner.
FileInputStream and FileOutputStream
read bytes
FileInputStream common read() The method is as follows:
read(): Read one byte, return0to255, return to the end-1。read(byte[] buffer): The maximum length of the array can be read in bytes, and the actual number of reads is returned.read(byte[] buffer, int offset, int length): Read the data to the specified range of the array.
When reading in batches, only the actual length read this time can be processed.
try (FileInputStream input = new FileInputStream(
"d:/lesson/java2601/test/a.txt")) {
byte[] buffer = new byte[1024];
int length;
while ((length = input.read(buffer)) != -1) {
for (int i = 0; i < length; i++) {
System.out.println(buffer[i]);
}
}
} catch (IOException e) {
e.printStackTrace();
}When outputting text content, you should not force any bytes to characters one by one. You should use a character stream and specify correct encoding.
write byte
FileOutputStream Overwrites the original file by default, and the second parameter of the constructor is true When it means adding.
try (FileOutputStream output = new FileOutputStream(
"d:/lesson/java2601/test/a.txt", true)) {
byte[] data = "ABCDEFG".getBytes(StandardCharsets.UTF_8);
output.write(data);
} catch (IOException e) {
e.printStackTrace();
}copy files
public static void copyFile(String source, String target) {
try (FileInputStream input = new FileInputStream(source);
FileOutputStream output = new FileOutputStream(target)) {
byte[] buffer = new byte[8192];
int length;
while ((length = input.read(buffer)) != -1) {
output.write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
}Copying binary files must use a byte stream.
BufferedInputStream and BufferedOutputStream
Buffered byte streams maintain buffers in memory and reduce the number of underlying read and write calls.
public static void copyFileWithBuffer(String source, String target) {
try (BufferedInputStream input = new BufferedInputStream(
new FileInputStream(source));
BufferedOutputStream output = new BufferedOutputStream(
new FileOutputStream(target))) {
byte[] buffer = new byte[8192];
int length;
while ((length = input.read(buffer)) != -1) {
output.write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
}The buffer is flushed first when the output stream is turned off. When you need to submit data to the underlying target immediately while the stream remains open, you can call flush()。
FileReader and FileWriter
FileReader and FileWriter Used to read and write text, but traditional constructors usually use the platform’s default character set. When the file code is fixed, it is recommended to use InputStreamReader and OutputStreamWriter Explicitly specify the character set.
try (FileReader reader = new FileReader(
"d:/lesson/java2601/test/a.txt")) {
char[] buffer = new char[1024];
int length;
while ((length = reader.read(buffer)) != -1) {
System.out.print(new String(buffer, 0, length));
}
} catch (IOException e) {
e.printStackTrace();
}FileReader itself is not BufferedReader, cannot be described as naturally having line buffering functions.
try (FileWriter writer = new FileWriter(
"d:/lesson/java2601/test/a.txt")) {
writer.write("1234567890");
} catch (IOException e) {
e.printStackTrace();
}BufferedReader and BufferedWriter
BufferedReader provide readLine(), you can read text per line. The returned string does not contain a line terminator and is returned when the end of the file is reached null。
try (BufferedReader reader = new BufferedReader(
new FileReader("d:/lesson/java2601/test/a.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}BufferedWriter provide newLine() Write the line separator corresponding to the platform.
try (BufferedWriter writer = new BufferedWriter(
new FileWriter("d:/lesson/java2601/test/a.txt"))) {
writer.write("第一行");
writer.newLine();
writer.write("第二行");
} catch (IOException e) {
e.printStackTrace();
}InputStreamReader and OutputStreamWriter
These two conversion streams connect the byte stream and the character stream and are responsible for character encoding conversions.
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream("d:/lesson/java2601/test/a.txt"),
StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}try (BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("d:/lesson/java2601/test/a.txt"),
StandardCharsets.UTF_8))) {
writer.write("使用 UTF-8 写入文本");
} catch (IOException e) {
e.printStackTrace();
}DataInputStream and DataOutputStream
The data stream can read and write data in binary format of Java’s basic type.
try (DataOutputStream output = new DataOutputStream(
new FileOutputStream("d:/lesson/java2601/test/data.bin"))) {
output.writeInt(1024);
output.writeDouble(100.0);
output.writeUTF("Java");
} catch (IOException e) {
e.printStackTrace();
}You must use the same order and type when reading, otherwise you will read wrong results or throw exceptions.
try (DataInputStream input = new DataInputStream(
new FileInputStream("d:/lesson/java2601/test/data.bin"))) {
int number = input.readInt();
double price = input.readDouble();
String text = input.readUTF();
System.out.println(number);
System.out.println(price);
System.out.println(text);
} catch (IOException e) {
e.printStackTrace();
}Object serialization and deserialization
Serialization converts an object and its serializable object graph into a byte sequence, and deserialization restores the object based on the byte sequence.
Class needs to be implemented Serializable Label the interface.
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String password;
}transient Fields do not participate in default serialization.serialVersionUID Used to determine whether serialized data is compatible with the current class version.
Serialize to byte array
public static byte[] serialize(Object object) throws IOException {
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ObjectOutputStream output = new ObjectOutputStream(bytes)) {
output.writeObject(object);
return bytes.toByteArray();
}
}deserialize from byte array
public static Object deserialize(byte[] data)
throws IOException, ClassNotFoundException {
try (ByteArrayInputStream bytes = new ByteArrayInputStream(data);
ObjectInputStream input = new ObjectInputStream(bytes)) {
return input.readObject();
}
}Serialization data does not require the JDK minor versions to be completely consistent, but class names, field structures,serialVersionUID and related classes must meet compatibility conditions.
deserializing untrusted data may trigger dangerous object behavior. Bytestreams from untrusted sources must not be directly deserialized in real projects.
PrintWriter
PrintWriter provide print()、println() and printf() and other convenient text output methods.
try (PrintWriter writer = new PrintWriter(
"d:/lesson/java2601/test/a.txt",
StandardCharsets.UTF_8.name())) {
writer.println("你好");
writer.println("中午吃什么");
} catch (FileNotFoundException | UnsupportedEncodingException e) {
e.printStackTrace();
}PrintWriter Some write errors will not be directly reported IOException Throw, which can be called when needed checkError() Check status. Closing the stream automatically flushes the buffer.
Properties Class
Properties Configuration used to save string key values, inherited from Hashtable<Object, Object>。Should be used first when reading configuration getProperty(), used when writing setProperty()。
Configuration files are suitable for holding data that can be adjusted by the deployment environment but should not be hard-coded into the program.
Common configuration formats
- XML has a clear structure, but it is relatively complex to write and parse.
- Properties use simple key value forms and have limited hierarchical expression capabilities.
- YAML has strong hierarchical expression capabilities and is often used in frameworks such as Spring Boot.
read configuration
p1.name=Tom
p1.age=20
p2.name=Jerry
p2.age=22Properties properties = new Properties();
try (Reader reader = new InputStreamReader(
new FileInputStream("src/myinfo.properties"),
StandardCharsets.UTF_8)) {
properties.load(reader);
Person person1 = new Person();
person1.name = properties.getProperty("p1.name");
person1.age = Integer.parseInt(properties.getProperty("p1.age"));
Person person2 = new Person();
person2.name = properties.getProperty("p2.name");
person2.age = Integer.parseInt(properties.getProperty("p2.age"));
} catch (IOException e) {
e.printStackTrace();
}use Reader You can explicitly select a character set. Direct use in Java 8 InputStream When reading Properties, traditional formats press ISO-8859-1 Rule processing, non-ASCII characters usually require Unicode escape.
writing configuration
properties.setProperty("p3.name", "Tom");
properties.setProperty("p3.age", "22");
try (Writer writer = new OutputStreamWriter(
new FileOutputStream("src/myinfo.properties"),
StandardCharsets.UTF_8)) {
properties.store(writer, "第三个人的信息");
} catch (IOException e) {
e.printStackTrace();
}
Apache POI
Apache POI is a Java project of the Apache Software Foundation that can read and write Microsoft Office formats such as Excel and Word.
A typical exercise is to read data from a student’s achievement workbook, calculate the average, and write the results to another worksheet. When processing Excel, you need to select the corresponding model according to the file format:
.xlsHSSF is usually used..xlsxXSSF is usually used.
When using POI to read and write workbooks, input streams, and output streams, you should also use the try-with-resources Turn off resources correctly and pay attention to the handling of cell types, empty cells, and formula cells.
If you enjoyed this, leave a comment~