JAVA advanced (IO flow) - basic flow

In the next two articles, we will systematically study the contents of the IO stream in detail:

elementary stream JAVA Advanced (IO Stream) - Basic Stream
advanced stream JAVA Advanced (IO Stream) - Advanced Stream

Table of contents

I. Introduction

2. Classification of IO streams

3. Byte stream

1. Output stream FileOutputStream

 1.1 Three ways to write data in FileOutputStream

1.2 Two small problems in writing data with FileOutputStream

2. Input stream FileInputStream

2.1 FileInputStream cyclic reading

2.2 Two ways of reading data with FileInputStream

3. Exercise: File Copy

Fourth, the character stream

 1. Character input stream FileReader 

2. Character output stream FileWriter

3. Analysis of the principle of character flow

5. Comprehensive exercises

1. copy

2. File encryption

3. Modify the data in the file


I. Introduction

File : Indicates the path of a file or folder in the system. (For details, see: JAVA Advanced - File )

 Note: The File class can only operate on the file itself, and cannot write the data stored in the file .

IO stream: used to read and write data in files (you can read and write files, or data in the network . . . )

2. Classification of IO streams

According to the direction of flow According to the operation file type

 Plain text file: Windows' built-in Notepad opens a file that can be read.

3. Byte stream

 Note: When the byte stream reads the file, there should be no Chinese in the file.

1. Output stream FileOutputStream

By operating the byte output stream of the local file, the data in the program can be written to the local file.

Writing steps:

① Create a byte output stream object

  • Detail 1 : The parameter is either a path represented by a string or a File object .
  • Detail 2 : If the file does not exist, a new file will be created, but the parent path must exist.
  • Detail 3 : If the file already exists, the file will be emptied .

② Write data

  • Details : The parameter of the write method is an integer , but what is actually written to the local file is the corresponding character on the integer ASCII .

③ Release resources

  • Details : resources must be released after each use of the stream.
public class ByteStreamDemo1 {
	public static void main(String[] args) throws IOException {
		// 需求: 写一段文字到本地文件中

		// 1.创建对象
		// 写出 -> 输出流 OutputStream

		// 编译时期异常 throws FileNotFoundException
		FileOutputStream fos = new FileOutputStream("java02\\a.txt");
		// 2.写出数据
		fos.write(97);
		// 3.释放资源
		fos.close();
	}
}

 1.1 Three ways to write data in FileOutputStream

method name illustrate
void write ( int  b ) Write data one byte at a time
void write ( byte [ ]  b ) Write byte array data one at a time
void write ( byte [ ] b , int off, int len ) Write part of data one byte array at a time
public class ByteStreamDemo2 {
	public static void main(String[] args) throws IOException {
		// 1.创建对象
		FileOutputStream fos = new FileOutputStream("java02\\a.txt");
		// 2.写出数据
		// ①、一次写一个字符数据
		fos.write(97); // a
		fos.write(98); // b

		// ②、一次写入一个字符数组
		byte[] bytes = { 97, 98, 99, 100, 101 };
		fos.write(bytes);

		// ③、一次写一个字符数组的部分数据
		// 参数一:数组 ;参数二:起始索引 ; 参数三:个数
		fos.write(bytes, 1, 2); // b c

		// 3.释放资源
		fos.close();
	}
}

1.2 Two small problems in writing data with FileOutputStream

  • Newline writing: newline \r \n
  • Continuation: FileOutputStream("path", parameter);
  • public class ByteStreamDemo3 {
    	public static void main(String[] args) throws IOException {
    		// 1.创建对象
    		FileOutputStream fos = new FileOutputStream("java02\\a.txt", true);
    		// 2.写出数据
    		String str = "abcdefghijklmn";
    		byte[] bytes = str.getBytes(); // 字符串转换成字节数组
    		fos.write(bytes);
    
    		// 3.换行
    		// 换行符
    		// windows:00\r\n Linux: \n Mac:\r
    		String str3 = "\r\n";
    		byte[] bytes3 = str3.getBytes();
    		fos.write(bytes3);
    
    		String str2 = "666";
    		byte[] bytes2 = str2.getBytes();
    		fos.write(bytes2); // 此时一开始并没有换行 需要上写一个换行符
    
    		// 4.续写
    		// 如果想要续写,打开续写开关即可
    		// 打开位置,创建对象的第二个参数
    		// 默认false:表示关闭,此时创建对象会清空文件
    		// 手动true:表示打开续写,此时创建对象不会清空文件
    		// new FileOutputStream("java02\\a.txt",true);
    
    		// 5.释放资源
    		fos.close();
    	}
    }

2. Input stream FileInputStream

  • Operate the character input stream of the local file, and read the data in the local file into the program.

Writing steps:

① Create a byte input stream object

  • Details: If the file does not exist, an error will be reported directly.

② Read data

  • Detail 1: Read one byte at a time , and what is read out is the number corresponding to the data in ASCII.
  • Detail 2: When the end of the file is read , the read method returns -1.

③ Release resources

  • Details: Resources must be released every time a stream is used.

public class ByteStreamDemo4 {
	public static void main(String[] args) throws IOException {
		// 1.创建对象
		FileInputStream fis = new FileInputStream("java02\\a.txt");
		// a.txt : abcde
		// 2.读取数据
		int b1 = fis.read();
		System.out.println(b1); // 97
		System.out.println((char) b1); // 强转: a
		// 读取不到就会返回 -1
		// 3.释放资源
		fis.close();
	}
}

2.1 FileInputStream cyclic reading

read method: read data, and read a data to move a pointer

public class ByteStreamDemo5 {
	public static void main(String[] args) throws IOException {
		// 1.创建对象
		FileInputStream fis = new FileInputStream("java02\\a.txt");
		// a.txt : abcde

		// 2.循环读取
		//定义第三方变量
		int b;
		while ((b = fis.read()) != -1) {
			System.out.println((char) b);
		}

		// 以下读取方式是错误的
		//read方法:读取数据,而且是读取一个数据移动一次指针
		//相当于迭代器的next方法
		// while (fis.read() != -1) {
		// System.out.println(fis.read()); // 98 100 -1
		// }

		// 释放资源
		fis.close();
	}
}

2.2 Two ways of reading data with FileInputStream

method name illustrate
public int read ( ) Read data one byte at a time
public int read ( byte [ ] buffer ) Read byte array data one at a time

 Note: Read the data of a byte array at a time, and each read will fill the array as much as possible.

public class ByteStreamDemo6 {
	public static void main(String[] args) throws IOException {
		// 1.创建对象
		FileInputStream fis = new FileInputStream("java02\\a.txt");
		

		// 2.读取数据
		byte[] bytes = new byte[2];
		//一次读取多个字节数据:具体读多少,跟数组的长度有关
		//返回值:本次读取到了多少个字节数据
		int len = fis.read(bytes);
		System.out.println(len);
		String str= new String(bytes);
		System.out.println(str);
		
		//3.释放资源
		fis.close();
	}
}

3. Exercise: File Copy

Requirement: Copy D: \aaa\movie . mp4 to the current module.
Note: Choose a relatively small file. Not too big.

public class ByteStreamDemo6 {
	public static void main(String[] args) throws IOException {
		// 1.创建对象
		FileInputStream fis = new FileInputStream("D:\\aaa\\movie.mp4");
		FileOutputStream fos = new FileOutputStream("java02\\copy.mp4");

		// 2.拷贝
		// 需要边读边写
		int b;
		while ((b = fis.read()) != -1) {
			fos.write(b);
		}
		// 3.释放资源
		// 规则: 先开的最后关闭
		fos.close();
		fis.close();
	}
}

 Disadvantages: FileInputStream reads and writes one byte at a time, which is slow.

 Solution: FileInputStream uses byte[] array to traverse multiple data at once.

public class ByteStreamDemo6 {
	public static void main(String[] args) throws IOException {
		long start = System.currentTimeMillis();
		
		// 1.创建对象
		FileInputStream fis = new FileInputStream("D:\\aaa\\movie.mp4");
		FileOutputStream fos = new FileOutputStream("java02\\copy.mp4");
		// 2.拷贝
		int len;
		byte[] bytes = new byte[1024 * 1024 * 5]; // 5兆大小
		while ((len = fis.read(bytes)) != -1) {
			fos.write(len);
		}
		// 3.释放资源
		fos.close();
		fis.close();
		
		long end = System.currentTimeMillis();
		//运行时间
		System.out.println(end - start);
	}
}

Fourth, the character stream

The bottom layer of the character stream is actually the byte stream.

Features:

  • Input stream: read one byte at a time, when encountering Chinese, read multiple bytes at a time and then write to the file.
  • Output stream: The bottom layer will convert the data into bytes according to the specified encoding method and then write it to the file.

Usage scenario: Read and write operations on plain text files.

 1. Character input stream FileReader 

Writing steps:

① Create a character input stream object

Construction method illustrate
public FileReader ( File file ) Create a character input stream associated with a local file
public FileReader ( String pathname ) Create a character input stream associated with a local file
  • Details: If the file does not exist, an error will be reported directly.

② Read data

member method illustrate
public int read ( ) Read data, read to the end and return -1
public int read ( char [ ]  buffer ) Read multiple data, read to the end and return -1
  • Detail 1: Read by byte, when encountering Chinese, read multiple bytes at a time, decode after reading, and return an integer.
  • Detail 2: When the end of the file is read, the read method returns -1.

③ Release resources

member method illustrate
public int close ( ) Release resources / close streams
public class CharStreamDemo1 {
	public static void main(String[] args) throws IOException {
		// 1.创建对象并关联本地文件
		FileReader fr = new FileReader("java02\\a.txt");
		// 2.读取数据 
		// 细节1:字符流的底层就是字节流
		// 默认一个字节一个字节的读取的
		// 如果遇到中文,就会一次读取多个字节,GBK一次两个字节 UTF-8一次三个字节

		// 细节2:读取之后,方法底层会进行解码并转换成十进制
		// 十进制作为返回值 并作为字符集上的数字
		
		// 细节3:想要看中文 可以对十进制进行强转
		
		//空参read
		int ch;
		while ((ch - fr.read()) != -1) {
			// System.out.println(ch);
			System.out.println((char) ch);
		}
		
		//带参read:读取数据、解码、强转三者合并,把强转之后字符放进数组
		//空参的read + 强转类型转换
		char[] chars = new char[2];
		int len;
		while((len = fr.read(chars)) != -1) {
			//把数组中的数据变成字符串再进行打印
			System.out.println(new String(chars,0,len));
		}
		// 3.释放资源
		fr.close();
	}
}

2. Character output stream FileWriter

Writing steps:

① Create a character output stream object

Construction method illustrate
public Filewriter ( File file ) Create a character output stream associated with a local file
public Filewriter ( String pathname ) Create a character output stream associated with a local file
public Filewriter ( File file , Boolean append ) Create a character output stream associated with a local file, continue writing
public Filewriter ( String pathname , Boolean append ) Create a character output stream associated with a local file, continue writing
  • Detail 1: The parameter is either a path represented by a string or a File object .
  • Detail 2: If the file does not exist, a new file will be created, but the parent path must exist .
  • Detail 3: If the file already exists, it will be cleared. If you don't want to clear it, you can turn on the switch to continue writing.

② Write data

member method illustrate
void write ( int c ) write a character
void write ( String str ) write out a string
void write( String str, int off,int len ) write out part of a string
void write( char [ ] cbuf) write out a character array
void write( char [ ] cbuf,int off, int len) write out part of a character array
  • 细节:如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符。

③ 释放资源

  • 细节:每次使用完流之后都要释放资源
public class CharStreamDemo2 {
	public static void main(String[] args) throws IOException {
		// 1.创建对象 续写开关打开
		FileWriter fw = new FileWriter("java02\\a.txt", true);
		// 2.写数据
		fw.write(25105); // 写一个字符
		fw.write("你好?"); // 写一个字符串 9个字节
		char[] chars = { 'a', 'b', 'c', '我' };
		fw.write(chars); // 写一个字符数组
		// 3.释放资源
		fw.close();
	}
}

3. 字符流原理分析

① 创建字符输入流对象

  • 底层:关联文件,并创建缓冲区(长度为8192的字节数组)

② 读取数据

  • 底层:
  • 1. 判断缓冲区中是否有数据可以读取
  • 2. 缓冲区没有数据:就从文件中获取数据,装到缓冲区中,每次尽可能装满缓冲区;如果文件中也没用数据时,返回 -1。
  • 3. 缓冲区有数据:就从缓冲区中读取。  空参的read方法:一次读取一个字节,遇到中文一次读多个字节,把字节解码并转成十进制返回。  有参的read方法:把读取字节、解码、强转三步合并,强转之后的字符放到数组当中。

五、综合练习

1. 拷贝

需求:拷贝一个文件夹,考虑子文件夹。

public class Test01 {
	public static void main(String[] args) {
		// 1.创建对象表示数据源
		File src = new File("D:\\aaa\\src");
		// 2.创建对象表示目的地
		File dest = new File("D:\\aaa\\dest");

		// 3.调用方法开始拷贝
		copydir(src, dest);
	}

	public static void copydir(File src, File dest) throws IOException {
		// 判断目的文件夹是否存在
		dest.mkdir();

		// 递归
		// 1.进入数据源
		File[] files = src.listFiles();
		// 2.遍历数组
		for (File file : files) {
			if (file.isFile()) {
				// 是文件 开始拷贝
				FileInputStream fis = new FileInputStream(file);
				//dest 是文件夹 不是最终目的地 需要从文件开始到文件结束
 				FileOutputStream fos = new FileOutputStream
                                   (new File(dest, file.getName()));
 				byte[] bytes = new byte[1024];
				int len;
				while ((len = fis.read(bytes)) != -1) {
					fos.write(bytes, 0, len);
				}
				fos.close();
				fis.close();
			} else {
				// 是文件夹 递归
				copydir(file, new File(dest, file.getName()));
			}
		}
	}
}

2. 文件加密

需求:
为了保证文件的安全性,就需要对原始文件进行加密存储,再使用的时候再对其进行解密处理。

加密原理:
               对原始文件中的每一个字节数据进行更改,然后将更改以后的数据存储到新的文件中。
解密原理:
               读取加密之后的文件,按照加密的规则反向操作,变成原始文件。

public class Test2 {
	public static void main(String[] args) throws IOException {
		// ^ 异或:两边相同false 两边不同true
		// 1.创建对象关联原始文件
		FileInputStream fis = new FileInputStream("java02\\girl.jpg");
		// 2.创建对象关联加密文件
		FileOutputStream fos = new FileOutputStream("java02\\ency.jpg");
		// 3.机密过程
		int b;
		while ((b = fis.read()) != -1) {
			fos.write(b ^ 2);
		}
		// 4.释放资源
		fos.close();
		fis.close();

		// 解密过程
		FileInputStream fis = new FileInputStream("java02\\ency.jpg");
		FileOutputStream fos = new FileOutputStream("java02\\redu.jpg");
		int b;
		while ((b = fis.read()) != -1) {
			fos.write(b ^ 2);
		}
		fos.close();
		fis.close();
	}
}

3. 修改文件中的数据

需求:

There is the following data in the text file:
             2-1-9-4-7-8
Sort the data in the file into the following data:
             1-2-4-7-8-9

​
public class Test3 {
	public static void main(String[] args) throws IOException {
		// 1.读取数据
		FileReader fr = new FileReader("java02\\a.txt");
		StringBuilder sb = new StringBuilder();
		int ch;
		while ((ch = fr.read()) != -1) {
			sb.append((char) ch);
		}
		fr.close();
		System.out.println(sb);
		// 2.排序
		String str = sb.toString();
		String[] arrStr = str.split("-");

		// 定义数组用于存储数据进行排序
		ArrayList<Integer> list = new ArrayList<>();
		for (String s : arrStr) {
			int i = Integer.parseInt(s);
			list.add(i);
		}
		System.out.println(list);
		// sort: 默认升序排序
		Collections.sort(list);
		System.out.println(list);

		// 3.写出数据
		FileWriter fw = new FileWriter("java02\\a.txt");
		// 打印结果: 1-2-4-7-8-9 通过索引遍历 -》 普通for循环
		for (int i = 0; i < list.size(); i++) {
			if (i == list.size() - 1) {
				fw.write(list.get(i) + "-");
			} else {
				fw.write(list.get(i));
			}
		}
		fw.close();
	}
}

​

Guess you like

Origin blog.csdn.net/hdakj22/article/details/129493191