Character stream of learning notes Day20; Conversion flow [super detailed notes!!! Code learning attached]

1, Character stream

Problems with using byte stream:

1. Copy characters using byte stream
1) If it is a pure copy, there will be no problem
2) If manual reading is mixed in the middle of the copy, there will be garbled code during decoding due to the problem of the copied content bytes. If it is pure English, we can also parse it according to one byte. If it is pure Chinese and the platform is GBK character set, Chinese can be parsed according to two bytes. If it is UTF-8, Chinese can be parsed according to three bytes. However, if Chinese and English are mixed, it cannot be parsed according to the fixed routine

public static void main(String[] args) throws IOException {
		//Byte stream will not have problems in pure copy
		//If manual reading is mixed in the copy process, there will be a problem of garbled code, because the byte information read is incomplete
		FileInputStream fis = new FileInputStream("Demo01.txt");
		FileOutputStream fos = new FileOutputStream("Demo01_copy1.txt");
		//Define a small array
		byte[] arr = new byte[2];
		
		int len;
		
		while((len = fis.read(arr)) != -1) {
			//String is used because it is a text
			System.out.println(new String(arr));
			fos.write(len);
		}
		
		fis.close();
		fos.close();
	}

Solution
1. Causes of garbled Code:
(1) Chinese and English are mixed. Each time I don't know how many bytes to read, I can count as a complete character
(2) However, how many bytes of information are read each time in our code is written dead

2. Solution:
(1) You can dynamically judge what to read and decide how many bytes to read at a time
(2) It is not only possible to use Chinese characters, but also to recognize each language stream dynamically

(3) Use of character stream

1. Top level abstract parent class: Reader, Writer
2. Common methods:
(

1)Reader:

1)read() reads a character information and returns the code value of the character information. If it reaches the end of the file, it returns - 1
2)read(char[] arr) reads some characters into the array, returns the number of characters read, and returns - 1 at the end of the file(

2)Writer:

1)write(int c) writes out a character message
2)write(String str) writes out a string. 3)write(char[] arr) writes out all the character information in an array
4)write(char[] arr, int offset, int len) writes out some byte information in an array

3. Since both Reader and Writer are abstract classes and cannot be instantiated, you need to implement subclass creation object and call method
4. Implementation subclass:
(1) Character input stream: FileReader
(2) Character output stream: FileWriter

public class TestClass {

	@Test
	public void test1() throws IOException {
		/*
		 * The character stream is mixed with artificial reading in the copy process, which can perfectly solve the problem of garbled code
		 * */
		FileReader fr = new FileReader("Demo01.txt");
		FileWriter fw = new FileWriter("Demo01_copy2.txt");
		
		int ch;
		
		while((ch = fr.read()) != -1) {
			System.out.println((char)ch);
			fw.write(ch);
		}
		
		fr.close();
		fw.close();
	}
	
	@Test
	public void test2() throws IOException {
		/*
		 * From the perspective of efficiency, test whether the copy of character stream file is fast to confirm that it has buffer
		 * 
		 * It does prove that there is a buffer
		 * 
		 * From the perspective of never refreshing the buffer, it is also confirmed that there is a buffer, so the efficiency of character stream is very high
		 * */
		FileReader fr = new FileReader("Demo02.txt");
		FileWriter fw = new FileWriter("Demo02_copy1.txt");
		
		int ch;
		
		long start = System.currentTimeMillis();
		
		while((ch = fr.read()) != -1) {
			fw.write(ch);
		}
		
		long end = System.currentTimeMillis();
		
		fr.close();
		fw.close();
		
		System.out.println(end - start);
	}
}

(4) Copy of character stream

1. Using character stream to copy files, it is found that the efficiency is very high because the bottom layer has char [] as buffer
2. Necessity of character stream copying: if manual reading is mixed in the copying process, character stream needs to be used; If it is just a simple copy, there is no need to use character stream, but directly use byte stream. Because in the process of copying the character stream, it is essentially copying with the help of the byte stream. Only after the byte stream reads the byte information into the memory, it makes an additional set of encoding and decoding operations. If it is not mixed with manual reading, this encoding and decoding operation is redundant and will reduce the system efficiency.

(5) Can character stream copy non plain text files

1. Non plain text file: non character content can be stored in the file, such as picture, video, audio, etc
2. Non plain text files cannot be copied using character streams
3. Reason:

When the character stream copies the byte information to the memory with the help of the byte stream, the byte information will be decoded according to the character set first. However, if the copied image has no character information, the original byte information will be damaged when it must be parsed according to the character set. After a set of encoding and decoding operations, the original byte information is damaged. The byte information obtained in the target file may be inconsistent with or missing from the source file. The non plain text file cannot be displayed normally, so the character stream cannot be used to copy the non plain text file.

(6) Character streams use small array copies

1. Using the read(char[] arr) method in FileReader, multiple characters can be read into the array at one time. The returned value represents the number of valid characters read this time. When it reaches the end of the file, it returns - 1
2. Using the write(char[] cbuf, int off, int len) method in FileWriter, multiple characters can be output at one time. When we last read as many characters as are valid, we can output as many as are valid
3. Note: without using small array copy, the discovery efficiency is also very high. Because there is also a buffer array in FileWriter, the writing efficiency is relatively high. After using small arrays, efficiency can become higher

(7) Efficient buffered character stream

1. Top level abstract parent classes: BufferedReader, BufferedWriter

2. BufferedReader and BufferedWriter do not have read-write functions, but strengthen the flow objects with read-write functions. They are subclasses of Reader and Writer respectively, so they can directly use the methods of their parent classes

3. Reasons for high efficiency:

(1)BufferedReader: each time the read method is called, only 8192 characters are read from the disk for the first time, stored in the buffer array of the object, and a character is returned to the caller. When the read method is called again, there is no need to access the disk, but get a character from the buffer array, which improves the efficiency.
(2)BufferedWriter: each time the write method is called, the characters will not be directly output to the disk, but will be stored in the character array. The disk will not be accessed until the buffer is full, which reduces the interaction with the disk and improves the efficiency

4. Unique methods:

(1)BufferedReader: readLine() reads one line of text at a time. null returned at the end of the file
(2)BufferedWriter: newLine() line feed

@Test
	public void bufferedTest() throws IOException {
		BufferedReader br = new BufferedReader(new FileReader("Demo03.txt"));
		BufferedWriter bw = new BufferedWriter(new FileWriter("Demo03_copy.txt"));
		
		//int i;
		String str;
		
		long start = System.currentTimeMillis();
		
		while((str = br.readLine()) != null) {
			bw.write(str);
			bw.newLine();
		}
		
		long end = System.currentTimeMillis();
		
		br.close();
		bw.close();
		
		System.out.println(end - start);
	}

(8) Practice

Enter the path of a folder on the keyboard and reverse the changed file
Reverse: the first row becomes the last row, and the last row becomes the first row

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

/**
 * Enter the path of a file with the keyboard and reverse the file
	Reverse: the first row becomes the last row, and the last row becomes the first row
 * 
 * Idea: inversion, contact in array, set, string buffer
 * 		Combined with the idea of reversing the array, the first line changes to the last line, and the last line is everywhere. Therefore, the line is operated as an element
 *      Furthermore, when we read the file, we read it by line
 * 		Because of the combination of inversion, after reading by line, it is stored in a container. Because the number of lines of the file is inconsistent, it is best to use collection
 * 		
 * 
 * Note: when using IO streams, follow the principle of creating late and closing early
 * @author Zihuatanejo
 *
 */
public class Demo02_Exercise {

	public static void main(String[] args) throws IOException {
		File filePath = getFilePath();
		System.out.println(filePath);
		
		//Create a set, which is used to take each line in the file as an element. If you reverse the set in the future, the relationship of the lines will be reversed
		ArrayList<String> list = new ArrayList<>();
		
		//1. Use the high-efficiency buffered character input stream to read the file by line
		BufferedReader br = new BufferedReader(new FileReader(filePath));//1.java
		
		String str;
		
		while((str = br.readLine()) != null) {
			list.add(str);
		}
		
		br.close();
		
		//2. Reverse set
		Collections.reverse(list);
		
		//Use an efficient buffered character output stream to output the inverted line and wrap it
		BufferedWriter bw = new BufferedWriter(new FileWriter(filePath));//1.java
		
		//3. Traverse the set and get each row after inversion
		for (String line : list) {
			bw.write(line);
			bw.newLine();
		}
		
		bw.close();
	}
	
	public static File getFilePath() {
		Scanner sc = new Scanner(System.in);
		
		System.out.println("Please enter the path of a file:");
		
		while (true) {
			
			String strPath = sc.nextLine();
			
			//1. Encapsulate the File path of String as a File object
			File file = new File(strPath);
			
			if (file.isFile()) {
				return file;
			} else {
				System.out.println("Re recording:");
			} 
		}
	}
}

2, Conversion flow

(1) Coding table
1. GBK: national standard code, which defines English and Chinese characters. In the GBK coding table, English occupies 1 byte and Chinese occupies 2 bytes

2. UTF-8: universal code, which defines all language symbols in the world. English accounts for 1 byte and Chinese for 3 bytes

(2) Conversion flow

1. InputStreamReader is a bridge between byte flow and character flow. It can specify the character set in encoding form
(1) Construction method: InputStreamReader(InputStream in, String charsetName)
(2) Create a conversion stream object, which can decode the characters received in the future method into byte information through the specified charsetName
2. OutputStreamWriter is a bridge between character flow and byte flow. It can specify the character set in encoding form
(1) Construction method: OutputStreamWriter(OutputStream out, String charsetName)
(2) Create a conversion stream object, which can encode the characters in the future memory according to the specified character set, and output the encoded byte information to the specified file

4. Summary: when copying files across character sets, if you want to avoid garbled code, when reading, decode according to what character set the source file is. When outputting, encode according to what character set the target file is, and then output the corresponding byte information. It won't cause garbled code

public class Demo03_Transition {

	public static void main(String[] args) throws IOException {
		//InputStreamReader isr = new InputStreamReader(new FileInputStream("x.txt"), "GBK");
		
		FileReader fr = new FileReader("x.txt");
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("y.txt"), "utf-8");
		
		int i;
		
		while((i = fr.read()) != -1) {
			osw.write(i);
		}
		
		fr.close();
		osw.close();
	}

	public static void test2() throws FileNotFoundException, IOException {
		FileReader fr = new FileReader("x.txt");
		FileWriter fw = new FileWriter("y.txt");
		
		int i;
		
		while((i = fr.read()) != -1) {
			fw.write(i);
		}
		
		fr.close();
		fw.close();
	}
	
	//Because x.txt is a GBK code, each Chinese character takes up 2 bytes, and a total of 4 Chinese characters have 8 bytes
	//y.txt is utf-8 encoding, and each Chinese character occupies 3 bytes
	//Directly use the byte stream to copy the original 8 bytes into y.txt. If you normally parse 4 Chinese characters, it takes 12 bytes, but now there are only 8, so it is garbled
	public static void test1() throws FileNotFoundException, IOException {
		FileInputStream fis = new FileInputStream("x.txt");
		FileOutputStream fos = new FileOutputStream("y.txt");
		
		int i;
		
		while((i = fis.read()) != -1) {
			fos.write(i);
		}
		
		fis.close();
		fos.close();
	}
}

3, Properties class

(1) Overview
1. The Properties object represents a persistent set of Properties.

(1) Attribute set: it is also a double column set, which represents the corresponding relationship between attribute name and attribute value
(2) Persistence: the file stored on the disk can be read into the Properties by stream, or the property set in the Properties can be output to the file by stream

2. Properties have no generics because the key values of properties are all strings, so there is no need to write generics
3. Properties is a subclass of Hashtable and can also act as a common map collection

**

(2) Unique methods in Properties

**

1. String getProperty(String key) obtains the value of its corresponding string according to the key of string type
2. setProperty(String key, String value) calls the put method of Hashtable
3. stringPropertyNames() returns the keyset

public class Demo03_Properties {

	public static void main(String[] args) {
		test1();
		
	}

	public static void test2() {
		Properties p = new Properties();
		
		p.put("className", "com.offcn.demos.Person");
		p.put("name", "zhangsan");
		p.put("age", "23");
		
		System.out.println(p.getProperty("className"));
	}

	public static void test1() {
		//Properties can actually store any type of key value pair
		//Properties are generally not used as a map
		//Properties in more scenarios, the configuration file is actually loaded. The contents in the configuration file are all strings, and the key value pairs used are all used as strings
		Properties p = new Properties();
		
		p.put(123, 3.5);
		p.put("Beijing", "1");
		p.put("Zhengzhou", "2");
		p.put("Lanzhou", "3");
		p.put("Eergu'Na", "4");
		p.put("Yinchuan", "13");
		
		//Set<Entry<Object,Object>> set = p.entrySet();
		
		Set<String> set = p.stringPropertyNames();
		
		Iterator<String> it = set.iterator();
		
		while(it.hasNext()) {
			String key = it.next();
			
			System.out.println(key + "..." + p.getProperty(key));
		}
	}
}

(3) Configuration file interaction in Properties

1. load(InputStream inStream) reads the key value pair information in the configuration file into the Properties object
2. store(OutputStream out, String comments) outputs the property set and specified comments in the Properties object to the configuration file

public class Demo04_LoadPropertiesFile {

	public static void main(String[] args) throws FileNotFoundException, IOException {
		Properties p = new Properties();
		
		//1. Use the load method to load the property set into the Properties object
		p.load(new FileInputStream("config.properties"));
		
		//2. Use getProperty(String key) to obtain the value corresponding to the key in the property set
		System.out.println(p.getProperty("className"));
		System.out.println(p.getProperty("name"));
		System.out.println(p.getProperty("age"));
		
		//Modify profile
		//3. Modify the property set in the Properties object
		p.setProperty("name", "lisi");
		p.setProperty("age", "24");
		
		//4.store(OutputStream os, String comments) modifies the property set in the configuration file
		p.store(new FileOutputStream("config.properties"), "update name zhangsan to lisi, age 23 to 24");
		
	}
}

Tags: Java

Posted by psr540 on Sun, 08 May 2022 03:00:02 +0300