How the file was created
First look at the constructor of the File class, and conclude that there are three common ways to create
Directly pass in the constructed file path, through the constructor File(String pathname), directly pass in the file path, the following is the demonstration code (the operation of the IO stream is always accompanied by a compile-time exception, you can use the Alt+Enter shortcut key exception caught or thrown)
public void create01() {
String filePath = "d:\\IOTest\\test1.txt";
File file = new File(filePath);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
Specify the parent directory file, that is, the specified folder file + subpath file, and create the file through the constructor File(File parent, String child)
public void create02() {
File parentFile = new File("d:\\IOTest");
String fileName = "test2.txt";
File file = new File(parentFile, fileName);
try {
file.createNewFile();
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
Directly specify the parent directory and file name, through the constructor File(String parent,String child)
public void create03() {
String parentPath = "d:\\IOTest";
String fileName = "test3.txt";
File file = new File(parentPath, fileName);
try {
file.createNewFile();
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
Common File Operations
view file information
The api document of the File file class, from which we can see that the File class provides many APIs for us to view file information, no need to memorize it by rote, you need to consult the api document
The following is an api example for obtaining common information about files
public void info(){
File file = new File("d:\\IOTest\\test1.txt");
System.out.println("文件名字="+file.getName());
System.out.println("文件的绝对路径="+file.getAbsolutePath());
System.out.println("文件父级目录="+file.getParent());
System.out.println("文件大小(字节)="+file.length());
System.out.println("文件是否存在="+file.exists());
System.out.println("是不是一个文件="+file.isFile());
System.out.println("是不是一个目录="+file.isDirectory());
}
file deletion
Just specify the file path, create a File object, and call the delete method to complete the deletion. When deleting a directory, you need to ensure that the directory is empty, otherwise the deletion will fail, but no exception will be thrown
String filePath = "d:\\IOTest\\test2.txt";
File file = new File(filePath);
if(file.exists()){
if(file.delete()){
System.out.println(filePath+"删除成功");
}else{
System.out.println(filePath+"删除失败");
}
}else{
System.out.println("该文件不存在...");
}
Create a directory
To create a first-level directory, you can directly call mkdir() to create it successfully, but if you are creating a multi-level directory, you need to use mkdirs, otherwise the directory will fail to be created, but no exception will be thrown
public void m3(){
String directoryPath = "D:\\demo\\a\\b\\c";
File file = new File(directoryPath);
if(file.exists()){
System.out.println(directoryPath+"存在...");
}else{
if(file.mkdirs()){
System.out.println(directoryPath+"创建成功...");
}else{
System.out.println(directoryPath+"创建失败");
}
}
}
IO flow principle and flow classification
IO concept
I/O is the abbreviation of Input/Output. I/O technology is a very practical technology for processing data transmission, network communication, and reading and writing files. The java.io package provides classes and interfaces for various stream interfaces. Used to process different data and input or output data through api
Input Input: Refers to the data input from the disk into the memory
Output Output: Refers to the output of data from memory to disk
Classification of IO streams
Classified by operation data type: divided into byte stream (processing binary files such as audio, pictures, video, etc.) and character stream (processing text)
According to the flow direction of data flow: divided into input flow and output flow
Classified according to the role of flow: node flow, processing flow/packaging flow (decorator mode)
abstract base class | byte stream | character stream |
---|---|---|
input stream | InputStream | Reader |
output stream | OutputStream | Writer |
files and streams
Files and streams are equivalent to the relationship between commodities and packages. Commodities need to be packaged into packages before they can be transported, and the information in files also needs to be converted into streams before they can be transmitted between disk and memory. Packages already contain commodities. If you copy For commodities, you only need to copy an identical package. This is why when copying a file, you only need to copy the corresponding input stream of the file to the output stream. The reason is that the input stream already has all the information of the file before you can copy the file.
IO flow commonly used classes
byte input stream InputStream
InputStream as an abstract parent class mainly has the following subclasses
FileInputStream input stream
The hello.txt file with hello world is prepared in advance on disk d. At this time, the integers read in are the ASCII values of each character. The read method will return -1 after reading the end of the file, indicating that there are no more bytes to read.
String filePath = "d:\\hello.txt";
int readDate = 0;
//提升作用域,用于在finally关闭输入流
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(filePath);
//一次读入一个字节,读到最后返回-1,表示无数据
while ((readDate = fileInputStream.read()) != -1) {
//每次将读入的字节数据转化为字符并输出
System.out.print((char) readDate);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//关闭流
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
The above method brings about a problem, that is, each time accessing the disk from the memory, only one byte can be read, and 11 bytes need to access the disk 11 times. Students who have studied the operating system know that accessing the disk itself from the memory is very difficult. One action is very time-consuming, so in order to solve this problem, the designer of java provides a method overload of the buffer in the read() method of FileInputStream, which can specify the size of the buffer to determine the size of the buffer that can be read in one access to the disk. The number of bytes, thereby reducing the number of disk accesses and optimizing performance.
String filePath = "d:\\hello.txt";
int readDate = 0;
// 指定一个8字节的字节数组作为缓冲区
byte[] buf = new byte[8];
FileInputStream fileInputStream = null;
int readLen = 0;
try {
fileInputStream = new FileInputStream(filePath);
while ((readLen = fileInputStream.read(buf)) != -1) {
// 每次将读取到的字节数据转为字符串输出
System.out.print(new String (buf,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
We can see that 8 characters of ASCII are directly read in the buffer byte array
But without a buffer, only one can be read at a time, and the performance gap is large
Byte output stream OutputStream
FileOutputStream
By default, the writing method of FileOutputStream is to overwrite the content of the original file. If you want to use the append writing method, you must assign append to true when creating the object to enable the append writing mode. At the same time, when the file does not exist, the file will be created automatically, but Make sure the directory exists
String filePath = "d:\\IOTest\\outTest.txt";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(filePath,true);
String str = "hello,world";
fileOutputStream.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
Use FileOutputStream and FileInputStream to realize file copy
The overall steps are divided into two steps
- Create an input stream for a file and read the file into the program
- Create the output stream of the file, and write the read file data to the specified file
//文件路径
String srcFilePath = "D:\\IOTest\\3e405d5c5b640f81caac8b4e551f7f33841232cd_raw.jpg";
//拷贝的文件路径
String destFilePath = "D:\\IOTest\\kakaxi.jpg";
//输出流
FileOutputStream fileOutputStream = null;
//输入流
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(srcFilePath);
fileOutputStream = new FileOutputStream(destFilePath);
//开辟1024个字节的缓冲区
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = fileInputStream.read(buf)) != -1){
//将读到的文件信息写入新文件
fileOutputStream.write(buf,0,readLen);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//判断非空,防止出现空指针异常
if(fileInputStream!=null){
fileInputStream.close();
}
if(fileOutputStream!=null){
fileOutputStream.close();
}}catch (IOException e) {
e.printStackTrace();
}
}
normal file copy
Character input stream FileReader
Related APIs
code example
String filePath = "d:\\IOTest\\story.txt";
FileReader fileReader = null;
int date = 0;
try {
fileReader= new FileReader(filePath);
while((date = fileReader.read())!=-1){
System.out.print((char)date);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
The character stream is specially used to process text files. We can see the characters read by FileReader. There are no garbled characters in the Chinese characters. Note that the read method returns the ASCII value of the characters. FileReader can also specify the buffer, and the description will not be repeated here.
Character output stream FileWriter
Related APIs
code example
String filePath = "d:\\IOTest\\note.txt";
FileWriter fileWriter = null;
char[] chars = {
'a', 'b', 'c'};
try {
fileWriter = new FileWriter(filePath);
fileWriter.write('H');
fileWriter.write("学java狠狠赚一笔");
fileWriter.write(chars);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 对于FileWriter,一定要关闭流,或者flush才能真正将数据写入到文件中
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Why do you have to close the stream or execute flush before actually writing data?
The reason is that after executing close, FileWriter will actually call the underlying interface for data writing
Node Flow and Process Flow
concept
Node stream: can read and write data from a specific data source (file), such as the previous FileInputStream, FileWriter
Process flow: Based on the existing flow, provide more powerful read and write functions for the program, that is, use the decorator design pattern to expand the function of the original flow and make it more powerful, such as BufferedReader, BufferedWriter
Process Flow Principle
Why can the processing flow encapsulate the original node flow? Take BufferedWriter as an example
FileWriter inherits the Writer class, and BufferedWriter also inherits the Writer class
The data type of the member attribute out of BufferedWriter is the object that Writer can receive FilerWriter, which is the embodiment of polymorphism. This shows that we can encapsulate any node stream, as long as the node stream object is a subclass of Writer, and the same is true for BufferedReader.
processing flow
The function of processing streams is mainly reflected in the following two aspects:
- Performance improvement: mainly by increasing buffering to improve the efficiency of input and output.
- Convenience of operation: The processing stream may provide a series of convenient methods to input and output a large amount of data at one time, such as a built-in buffer, which improves reading performance and is more flexible and convenient to use.
BufferedReader
Related APIs
code example
When creating a BufferedReader object, you need to pass in the corresponding node stream object and close the outer stream. Calling the close method of BufferedReader will also call the close method of the node stream to close the stream.
String filePath = "d:\\IOTest\\note.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line = "";
//按行读取效率高,返回null时表示读取完成
while((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
//关闭外层流即可
bufferedReader.close();
BufferedWriter
Related APIs
code example
String filePath = "d:\\IOTest\\ok.txt";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write("hello,你好世界~");
bufferedWriter.newLine();//系统换行
bufferedWriter.write("hello,你好~");
bufferedWriter.newLine();
bufferedWriter.write("hello,你好世界~");
bufferedWriter.newLine();
bufferedWriter.close();
BufferedOutputStream与BufferedInputStream
BufferedInputStream: byte stream, when creating BufferedInputStream will automatically create a buffer array that is, we do not need to manually create a buffer
BufferedOutputStream: byte stream, which implements a buffered output stream, can write multiple bytes to the underlying output stream without having to call the underlying system for each byte write
object processing flow
use
When we need to save its type when saving data, and restore the object or the data type in the file, we must be able to serialize and deserialize the basic data type or object. At this time, we need to use the object processing stream Perform data manipulation
Serialization and deserialization
Serialization: Serialization is to save the value and data type of the data when saving the data
Deserialization: Deserialization is to restore the value and data type of the data when restoring the data
Conditions for realizing serialization
To achieve serialization, a class must implement the Serializable interface, and the wrapper classes of java's basic data types all implement the Serializable interface.
ObjectOutputStream
Related APIs
A series of APIs are provided to facilitate us to output basic data types and custom classes
code example
public static void main(String[] args) throws Exception{
String filePath = "d:\\IOTest\\data.dat";
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream(filePath));
oos.writeInt(100);
oos.writeBoolean(true);
oos.writeChar('a');
oos.writeDouble(9.5);
oos.writeUTF("jack");
oos.writeObject(new Dog("旺财",10));
oos.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
class Dog implements Serializable {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Because it is a byte stream, it is garbled because it has not been converted into an encoding, but we can still see that the type is Dog
ObjectInputStream
Related APIs
code example
String filePath = "d:\\IOTest\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
Object dog = ois.readObject();
System.out.println("运行类型为:"+dog.getClass());
System.out.println(dog);
ois.close();
System.out.println();
conversion flow
necessity
When we read a file through FileInputStream, when we read Chinese, there will be garbled characters, as shown in the figure, it will become garbled characters, so we need to convert the stream to specify the encoding format
InputStreamReader
InputStreamReader, as a subclass of Reader, can wrap InputStream (byte stream) into (convert) Reader (character stream)
Constructor and API
The biggest feature is that we can specify the encoding format of the stream
code example
String filePath = "d:\\IOTest\\note.txt";
//创建输入转化流InputStreamReader对象,同时指定编码为utf-8
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath), "utf-8");
//包装成BufferedReader对象进行字符读取操作
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String s = bufferedReader.readLine();
System.out.println("读取内容="+s);
bufferedReader.close();
We can see another big buck
OutputStreamWriter
OutputStreamWriter: A subclass of Writer, which realizes packaging OutputStream (byte stream into Writer
Construction methods and related APIs
code example
String filePath = "d:\\IOTest\\hello.txt";
//指定编码
String charSet="utf8";
//包装流
OutputStreamWriter outputStreamWriter =
new OutputStreamWriter(new FileOutputStream(filePath), charSet);
outputStreamWriter.write("hello world 你好世界");
outputStreamWriter.close();
System.out.println("按照 "+charSet+" 保存文件成功~");
print stream
PrintStream and PrintWriter
Related APIs
PrintStream prints the content to the display by default, but we can specify the output location through the constructor, such as outputting the content to a file
code example
PrintStream out = System.out;
out.print("john,hello");
out.write(" 你好".getBytes());
out.close();
//修改输出位置
System.setOut(new PrintStream("d:\\f1.txt"));
System.out.println("hello,你好世界");