Filter flow

Filter flow type

Filtering flow is an additional function on the basis of node flow

Treatment type Character stream Byte stream
Cache BufferedReader、BufferedWriter BufferedInputStream、 BuàeredOutputStream
Filter processing FilterReader、FilterWriter FilterInputStream、FilterOutputStream
Bridging InputStreamReader、 OutputStreamWriter
Object serialization processing ObjectInputStream、 ObjectOutputStream
Data conversion DataInputStream、DataOutputStream
Row count LineNumberReader LineNumberInputStream
Rollback processing PushbackReader PushbackInputStream
Print function PrintWriter PrintStream

Filter stream
FilterInputStream/FilterOutputStream and FilterReader/FilterWriter

 public class FilterInputStream extends InputStream {
    
     //典型的装饰模式 
 	protected volatile InputStream in; //被装饰目标 
 	protected FilterInputStream(InputStream in) {
    
     //通过构造器组装被装饰对象 
 		this.in = in; 
 	}
 	public int read() throws IOException {
    
    //调用Filter中的read方法时实际操作是由被装饰对象实现 的 
 		return in.read(); 
 	} 
 } 

The so-called filtering flow is actually similar to the above encryption processing, after the input (post-processing, the decorated object is executed first) or before the output (pre-processing, first processing and then executed by the decorated object) for some additional processing, and finally The actual operation is to call the method of the decorated object to complete the work, relying on this decoration mode to achieve additional functions on the basis of the node stream. Of course, it also allows multiple filter streams to be nested to achieve the purpose of function accumulation.
FilterInputStream is actually a decorative abstraction Character

Custom stream realizes loop 13 encryption:
read data unchanged: FileReader—BuàeredReader
writes out data Custom filter stream SecurityWriter (FilterWriter)

public class SecurityWriter extends FilterWriter {
    
     
	protected SecurityWriter(Writer out) {
    
     
		super(out); 
	}
	public void write(int c) throws IOException {
    
     
		if (c >= 'a' && c <= 'z') {
    
     
			c = (c - 'a' + 13) % 26 + 'a'; 
		} else if (c >= 'A' && c <= 'Z') {
    
     
			c = (c - 'A' + 13) % 26 + 'A'; 
		}
		super.write(c); 
	} 
}
public class SecurityReader extends FilterReader {
    
     
	protected SecurityReader(Reader in) {
    
     
		super(in); 
	}
	public int read() throws IOException {
    
     
		int c = super.read(); 
		if (c >= 'a' && c <= 'z') {
    
     
			c = (c - 'a' + 13) % 26 + 'a'; 
		} else if (c >= 'A' && c <= 'Z') {
    
     
			c = (c - 'A' + 13) % 26 + 'A'; 
		}
		return c; 
	} 
} 

Bridge conversion flow

InputStreamReader and OutputStreamWriter provide a bridge conversion function between byte stream and character stream, which is used to convert from byte data to character data, without programming to realize the splicing of bytes into characters

The conversion stream can specify its coded character set when constructing

InputStreamReader is used to automatically convert an InputStream type input stream into a Reader character stream.
OutputStreamWriter is used to convert a Writer character output stream to an OutputStream byte output stream.

InputStreamReader constructor

  • InputStreamReader(InputStream)
  • InputStreamReader(InputStream, String)
  • InputStreamReader(InputStream, Charset)
  • InputStreamReader(InputStream, CharsetDecorder)
Reader r=new InputStreamReader(System.in); 
int kk=r.read(); //例如输入的是“中国”,这里实际读取的是"中" 
//因为这里读取的是一个字节,所以输入"中国",实际读取的是"中"的一个字节,输出显示为? 
kk=System.in.read(); 
System.out.println("输入的是:"+(char)kk);

InputSteram is=new InputStreamReader(System.in,”iso8859-1”);

Reader r=new InputStreamReader(System.in, "gbk"); 
int kk=r.read(); //例如输入的是"中国",实际读取的是"中" 
System.out.println("输入的是:"+(char)kk); 

Note: It is generally not recommended to set the coded character set by yourself, unless it is necessary

Buffered stream

The buffer stream is socketed on the responding node stream, and provides a buffer function for the data to be written continuously, which improves the efficiency of reading and writing, and at the same time adds some new methods.

Taking the hard disk as the medium, the disadvantage of byte stream and character stream: every time you read and write, you will access the hard disk. If the frequency of reading and writing is relatively high, its performance is poor. In order to solve the above drawbacks, a buffered stream is used.

When the cache stream is read, more data will be read into the cache at one time, and every subsequent read will be accessed in the cache until the data in the cache is read, and then read from the hard disk.

Construction method

  • BufferedReader (Reader) does not define the buffer size, the default is 8192
  • BufferedReader(Reader in, int size) size is the size of the custom buffer
  • BufferedWriter(Writer)
  • BufferedWriter(Writer out, int size) size is the size of the custom buffer
  • BufferedInputStream(InputStream)
  • BufferedInputStream(InputStream in, int size) size is the size of the custom buffer
  • BufferedOutputStream(OutputStream)
  • BufferedOutputStream (OuputStream out, int size) size is the size of the custom buffer

Methods of buffering the input stream

BuffedReader provides a method readLine(): String, but there is no such method in BufferedInputStream

  • BufferedReader provides the readLine method to read a line of string, separated by \r or \n (newline character)
    • If the read content is null, it means that the end of the stream has been read
    • The readLine method will automatically remove the newline character at the end of the line content
  • BufferedWriter provides the newLine method to write a line separator.
    For the output buffer stream, the written data will be cached in the memory first, and the Öush method will cause the data in the memory to be written out immediately

Keyboard entry

System.in:InputStream is used to refer to the default input device of the system—the keyboard. The
method read():int can realize that the code execution will block and wait until the data is input.

BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("输入数据"); 
String temp=""; 
while((temp=br.readLine()).trim().length()>0){
    
     
	if("quit".equals(temp)) 
		break; 
	System.out.println(temp); 
}
br.close();
 BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); 
 bw.write("只有缓冲区满才自动进行输出显示"); 
 bw.flush(); //刷新缓冲区,否则看不到输出内容 
 System.in.read(); 
 bw.close(); //关闭输出时会首先自动进行刷新缓冲区 

data flow

DataInputStram and DataOutputStream are inherited from InputStream and OuputStream respectively. They are filtered streams and need to be socketed on the node streams of InputStream and OutputStream respectively.

  • There are only byte streams, no corresponding character streams.
    DataInputStream and DataOutputStream provide methods that can access machine-independent Java primitive data.
    DataInputSteram and DataOutputStream are constructed as
  • DataInputStream(InputStream)
  • DataOutputStream(OutputStream)

Read and write a double data to the file

//使用数据流就可以直接操作简单类型数据 
double dd=123.4567; 
FileOutputStream fos=new FileOutputStream("d:\\a.data"); 
fos.write((dd+"").getBytes()); 
fos.close(); 
//如果不使用数据流,则需要额外编码进行数据类型转换 
FileInputStream fis=new FileInputStream("d:/a.data"); 
byte[] buffer=new byte[8192]; 
int len=fis.read(buffer); 
fis.close(); 
String str=new String(buffer,0,len); 
double dd=Double.parseDouble(str); 
System.out.println(dd); 

Print stream

Both PrintStream and PrintWriter are output streams, and both
PrintWriter and PrintStream provide overloaded print and println methods for outputting multiple types of data
print(Object):void for bytes and characters .

  • Output reference type, in fact, the toString method of the calling object is converted to String for output
public void println(Object x) {
    
     
	String s = String.valueOf(x); //调用String类中的静态方法将object类型的数据转换为字符 串 
	synchronized (this) {
    
     
		print(s); 
		newLine(); //print('\n') 
	} 
}
//String中的valueOf方法的定义 
public static String valueOf(Object obj) {
    
     
	return (obj == null) ? "null" : obj.toString(); //如果输出对象非空,则调用对象的 toString方法 
}

println means automatic line break after output

  • The output operations of PrintWriter and PrintStream will not throw exceptions, and users can obtain error information by detecting the error status
  • PrintWriter and PrintStream have automatic flush function textOut.flushBuffer();
    PrintWriter(Writer) PrintWriter(Writer out, boolean autoFlush) automatic refresh----println
    DataOutputStream dos=new DataOutputStream(new FileOutputStream("data2.txt"));
PrintWriter(OutputStream out) //参数是一个字节流,但是不需要通过桥接处理 
PrintWriter(OutputStream out, boolean autoFlush) 
PrintStream(OutputStream) 
PrintStream(OutputStream out, boolean autoFlush)

Object stream

Use DataInputStream or DataOutputStream can read and write object data, but the operation is more cumbersome

//从文件中按照id值查找对应的对象 
int id=dis.readInt(); //用户id--用户标识 
int len=dis.readInt(); //用户名称的字符数 
StringBuilder username=new StringBuilder(); //用户名称 
for(int i=0;i<len;i++) //一次读取一个字符,然后拼接成完整的字符串 
	username.append(dis.readChar()); 
len=dis.readInt(); 
StringBuilder password=new StringBuilder(); //用户口令 
for(int i=0;i<len;i++) 
	password.append(dis.readChar()); 
double balance=dis.readDouble(); //用户余额 
if(dis==id){
    
     
	res=new Account(); //Account是一个自定义类型,用于封装账户信息 
	res.setUsername(username.toString()); 
	res.setPassword(password.toString()); 
	res.setBalance(balance); break; 
}

SUN provides ObjectInputStream/ObjectOutputStream which can directly write or read Object.
There are actually operation methods for 8 simple types and their packaging classes, as well as operation methods for String type.

  • readObject():Object
  • writeObject(Object):void
//简单写法,应该使用try/finally结构或者使用try/resource的写法 
Date now=new Date(); 
ObjectOutputStream oos=new ObjectOutputStream( new BufferedOutputStream(new FileOutputStream("data3.txt"))); 
oos.writeObject(now); 
oos.close(); 
ObjectInputStream ois=new ObjectInputStream( new BufferedInputStream(new FileInputStream("data3.txt")));
Object obj=ois.readObject(); 
if(obj!=null && obj instanceof Date) {
    
     
	Date dd=(Date)obj; 
	System.out.println(dd); 
}
ois.close();

The premise of reading and writing an object is that this type of object can be serialized;

  • NotSerializableException

Object serialization [in short, it means that the object can be directly converted into a binary data stream]/deserialization of the object [the binary data stream can be converted into an object], this is generally implemented by the JVM, and only the object serialization is declared in programming The goal is to save the object to disk, or to allow the object to be transferred directly over the network. The object serialization mechanism allows the Java objects in memory to be converted into platform-independent binary streams, thereby allowing this binary stream to be persistently stored on the disk, and the binary stream is transmitted to another network node through the network, and other programs once Get this kind of binary stream, you can restore this kind of binary stream to the original Java object

1. How to declare that the class to which the object belongs can be serialized and deserialized Serializable/Externalizable interface

The interface does not have any definition, only played an illustrative role, this kind of interface is called a flag interface or a flag interface

2. You can directly manipulate the object through the methods provided by ObjectInputStream[readObject():Object] and ObjectOutputStream[writeObject(Object):void]

3. Output object

User user = new User(); 
user.setId(100L); 
user.setUsername("zhangsan"); 
user.setPassword("123456"); 
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("users.data")); 
oos.writeObject(user); 
oos.close();

4. Read the object

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users.data")); 
Object temp = ois.readObject(); 
if (temp != null && temp instanceof User) {
    
     
	User user = (User) temp; 
	System.out.println(user); 
}
ois.close();

Coding details

1. Objects that need to be read and written through the object stream must implement the serialization interface, otherwise java.io.NotSerializableException

class User implements Serializable

2. The Serializable interface is a logo interface, and there is no method to be implemented. All serialization and deserialization operations are implemented by the VM.

The Externalizable interface is defined as public interface Externalizable extends java.io.Serializable. This interface contains two methods that need to implement the serialization of writeExternal custom implementation objects, and the deserialization of readExternal custom implementation objects. Unless there are special needs, the Externalizable interface is generally not used, because there is no need to customize

class User implements Externalizable {
    
     
	@Override 
	public void writeExternal(ObjectOutput out) throws IOException {
    
     
		// 写出对象的操作 
			System.out.println("现在需要写出对象:" + this); 
			out.writeLong(this.id); 
			out.writeUTF(this.username); 
			out.writeUTF(this.password); 
		}
	@Override 
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    
     
		// 读取对象的操作 
		this.id = in.readLong(); 
		this.username = in.readUTF(); 
		this.password = in.readUTF(); 
	}
	public User(){
    
    }
}

3. Type conversion issues:

Object temp = ois.readObject(); 
if (temp != null && temp instanceof User) {
    
     
	User user = (User) temp; 
	System.out.println(user); 
}

4、private static final long serialVersionUID = 6889840055394511246L

If you do not add the serial number, there will be a warning message, but not an error message

Generally choosing Add generated serial version ID will generate a serial version number that will never be repeated in the project

The serial version number does not need to be added. This serial version number is a simple method to quickly identify the type in serialization and deserialization, which is more efficient than the identification without a serial number. The introduced function is that if the version number does not correspond, the type identification will not be performed, but the exception InvalidClassException will be reported directly.

5. Generally, serialization operations should not be performed for sensitive data. For attributes that do not require sequence operations, a keyword transient can be added to indicate that the attribute does not participate in serialization and deserialization operations.

class User implements Serializable {
    
     
	private transient String password; //transient用于声明该属性不支持序列化操作
class User implements Serializable {
    
     
	private String username; 
	private transient String password; 
	private Role role;//因为Role没有实现序列化接口,所以写出user对象时会有报错 NotSerializableException。处理报错的方法有:1、可以给Role类定义添加序列接口。2、在role属性上添加 transient表示这个属性不序列化处理

6. Judgment of reading files: When reading files, EOFException can be used to judge the end of file reading

try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users.data"));) {
    
     
	while (true) {
    
     
		try {
    
    
			Object temp = ois.readObject(); 
			if (temp != null && temp instanceof User) {
    
     
				User user = (User) temp; 
				System.out.println(user); 
			} 
		} catch (EOFException ex) {
    
     // 这个异常是用于判断文件结尾,所以不需要进行处理 
			break; 
		} 
	} 
}

Guess you like

Origin blog.csdn.net/qq_43480434/article/details/113406451