Java I/O stream learning summary

1. Inheritance relationship and simple application of I/O stream basic classes

I/O streams can be divided into different types according to different attributes:

  • Input stream (InputStream, Reader); output stream (OutputStream, Writer)
  • Input and output streams (InputStream, OutputStream) for processing bytes; input and output streams (Reader, Writer) for processing characters

InputStream, OutputStream, Reader and Writer all belong to abstract base classes and cannot directly manipulate I/O streams with new objects. Therefore, we must use its implementation class for manipulation:

1. Commonly used implementation classes of InputStream: FileInputStream and ByteArrayInputStream

public static void main(String[] args) {
	//创建源文件
	File src = new File("D:/Java/abc.txt");
	//选择流
	InputStream is = null;
	try {
		is = new FileInputStream(src);
		//操作
		byte[] flush = new byte[1024];//缓冲容器
		int len = -1;//返回值为-1表示读完了
		while ( (len = is.read(flush)) != -1 ) {
			//字节数组-->字符串(解码)
			String str = new String(flush,0,len);
			System.out.println(str);
		}
	} catch (IOException e) {
		e.printStackTrace();
	}finally {
		//释放
		try {
			if (null != is) {
				is.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

//-------------------------------------------------
public static void main(String[] args) {
	//创建源:字节数组不要太大
	byte[] src = "talk is cheap show me the code".getBytes();		
	//选择流
	InputStream is = null;	
	try {
		//操作
		is = new ByteArrayInputStream(src);
		int len = -1;
		byte[] flush = new byte[5];
		while((len = is.read(flush)) != -1) {
			String str = new String(flush,0,len);
			System.out.println(str);
		}		
	} catch (IOException e) {
		e.printStackTrace();
	}finally {
		//释放
		try {
			if (null != is) {
				is.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

2. Commonly used implementation classes of OutputStream: FileOutputStream and ByteArrayOutputStream

public static void main(String[] args) {
	//1、创建源
	File src = new File("dest.txt");
	//2、选择流
	OutputStream os = null;
	try {
		os = new FileOutputStream(src,true);//追加
		//3、操作
		String str = "hhhhh";
		byte[] datas = str.getBytes();
		os.write(datas, 0, datas.length);
		os.flush();//刷新
	} catch (IOException e) {
		e.printStackTrace();
	}finally {
		try {
			if(null != os) {
				os.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

//--------------------------------------------
public static void main(String[] args) {
	byte[] dest = null;
	//2、选择流
	ByteArrayOutputStream bos = null;
	try {
		bos = new ByteArrayOutputStream();
		//3、操作
		String str = "show me the code";
		byte[] datas = str.getBytes();//编码
		bos.write(datas, 0, datas.length);
		bos.flush();
		//获取数据
		dest = bos.toByteArray();
		System.out.println(new String(dest,0,dest.length));
	} catch (IOException e) {
		e.printStackTrace();
	}finally {
		try {
			if(null != bos) {
				bos.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

3. Reader commonly used implementation classes: FileReader

public static void main(String[] args) {
	File src = new File("abc.txt");
	Reader reader = null;
	try {
		reader = new FileReader(src);
		int len = -1;
		char[] flush = new char[1024];
		while((len = reader.read(flush)) != -1) {
			String str = new String(flush,0,len);
			System.out.println(str);
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
}

4. Writer commonly used implementation classes: FileWriter

public static void main(String[] args) {
	File src = new File("abc.txt");
	Writer writer = null;
	try {
		writer = new FileWriter(src,true);
		String msg = "jjjjj";
        //第一种方式,转为字符数组进行写
		char[] datas = msg.toCharArray();
		writer.write(datas, 0, datas.length);
        //第二种方式,直接写
		writer.write(msg);
		writer.flush();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

2. Add buffer stream (decorator)

In order to speed up the I/O operation, the concept of buffer stream is added (its essence is the decorator of the I/O stream, which needs to use the ordinary I/O stream as the decoration object. In fact, the data is manipulated as mentioned in the first part. Four basic I/O operations), the buffered streams in I/O are: BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter

1. How unbuffered streams work:

  • When it reads a byte/character, it writes it to the path specified by the user. It reads one byte/character and writes one after another, so it is slow.

2. How buffered streams work:

  • After reading a byte/character, do not output it first, and then write it out at once after the maximum capacity of the buffer is reached, thereby improving work efficiency.
  • Advantages: Reduce the number of reads to the hard disk, reduce the wear and tear on the hard disk, and increase the input and output speed.
//以BufferedInputStream为例,其余类似
public static void main(String[] args) {
	//创建源
	File src = new File("abc.txt");
	//选择流
	InputStream is = null;
	try {
		is = new BufferedInputStream(new FileInputStream(src)); 
		//操作,一个字节的读取
		byte[] flush = new byte[1024];
		int len = -1;
		while ( (len = is.read(flush)) != -1 ) {
			String str = new String(flush,0,len);
			System.out.println(str);
		}
	} catch (IOException e) {
		e.printStackTrace();
	}finally {
		//释放
		try {
			if (null != is) {
				is.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

3. Conversion stream: the bridge connecting byte stream and character stream

InputStreamReader and OutputStreamWriter are the bridge between characters and bytes, and can also be called character conversion streams. Principle: byte stream + encoding.

FileReader and FileWriter, as subclasses, exist only as convenience classes for operating character files. When the character file being operated uses the default encoding table, you can use the subclass directly to complete the operation without using the parent class to simplify the code. Once you want to specify other encodings, you cannot use subclasses and must use character conversion streams. Otherwise, garbled codes may easily occur! ! !

Reader r = new InputStreamReader(System.in,"UTF-8");//指定CharSet防止乱码
  • Here we take the operation of network streams as an example to implement the basic operation of downloading file source code > web crawler (crawling the source code of Baidu homepage), using both the buffer stream and the conversion stream.
public static void main(String[] args){
	//try  with不用释放资源
	try(BufferedReader read = 
			new BufferedReader(
					new InputStreamReader(
							new URL("http://www.baidu.com").openStream(),"UTF-8"));
			BufferedWriter writer = 
					new BufferedWriter(
							new OutputStreamWriter(
									new FileOutputStream("baidu.html")));
	){
		String line = null;
		while((line = read.readLine()) != null) {
			writer.write(line);
			writer.newLine();
		}
		writer.flush();
	}catch (Exception e) {
		System.out.println("操作异常");
	}
}

4. Data flow: DataInputStream and DataOutputStream

  • DataInputStreams are subclasses of InputStream.
  • DataOutputStreams are subclasses of OutputStream.

Take DataOutputStreams as an example to explain (DataInputStreams is similar): This class inherits from the FillterOutputStream class and inherits the close and write methods; it also implements the DataOutput interface and defines a series of methods for writing various data in the DataOutput interface. DataOutputStreams is an extension of the function of ordinary streams, which can more easily read int, long, character and other types of data.

  • Function: Realize the input/output of eight basic types of data. At the same time, string input/output can also be realized.
  • Features: The eight basic types of data will keep their types unchanged during input/output. (Suitable for transferring basic type data and strings on the network)
  • The data stream is a processing stream and must be connected to the node stream. (Similar to BufferedOutputStream in status and usage)
  • Note: The order of data streams when reading and storing must be consistent. Otherwise, the read data will be distorted.
public static void main(String[] args) throws IOException {
	//写出
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
	dos.writeUTF("啊哈哈");
	dos.writeInt(66);
	dos.writeBoolean(true);
	dos.writeChar('a');
	dos.flush();
	byte[] datas = baos.toByteArray();
	//----------------------------------
	//按写出顺序读入
	ByteArrayInputStream bais = new ByteArrayInputStream(datas);
	DataInputStream dis = new DataInputStream(new BufferedInputStream(bais));
	String s =  dis.readUTF();
	int age = dis.readInt();
	boolean flag = dis.readBoolean();
	char ch = dis.readChar();
	System.out.println(s + age + flag + ch);
}

5. Object stream: ObjectInputStream and ObjectOutputSteam

Processing flow for storing and reading objects . Its power is that it can write objects in Java to the data source and restore objects from the data source.

Principle: The object serialization mechanism allows Java objects in memory to be converted into platform-independent binary streams, thereby allowing this binary stream to be persisted on disk or transmitted to another network node through the network. When other programs obtain this binary stream, they can be restored to the original Java object.

  • Serialize: Use the ObjectOutputStream class to write a Java object into an IO stream (the process of converting a specific data structure into a set of bytes)
  • Deserialize: Use the ObjectInputStream class to restore the Java object from the IO stream (the process of converting a set of bytes into a specific data structure)
  • Persistence: The process of writing data to the hard disk for long-term storage is called persistence.
  • Note: Only objects that support the java.io.Serializable interface can be written to the stream, so the object must implement the Serializable interface.

1. Object class Employee 

public class Employee implements Serializable{
	private int id;
	private transient String ename;//transient:该数据不许要序列化
	private double salary;
	
	public Employee(int id, String ename, double salary) {
		super();
		this.id = id;
		this.ename = ename;
		this.salary = salary;
	}
	
	@Override
	public String toString() {
		return super.toString();
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getEname() {
		return ename;
	}

	public void setEname(String ename) {
		this.ename = ename;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}
}

2. Writing (serialization) and reading (deserialization)

public static void main(String[] args) throws IOException, ClassNotFoundException {
	//写出--》序列化
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(baos));
	oos.writeObject(new Date());
	oos.writeObject(new Employee(11, "dada", 44.2));
	oos.flush();
	//-------------------------------
	//反序列化
	byte[] datas = baos.toByteArray();
	ByteArrayInputStream bais = new ByteArrayInputStream(datas);
	ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(bais));
	//数据还原
	Object date = ois.readObject();
	Object emp = ois.readObject();
	if(date instanceof Date) {
		Date dateObj = (Date)date;
		System.out.println(dateObj);
	}
	if(emp instanceof Employee) {
		Employee empObj = (Employee)emp;
        //name不能输出,因为未序列化
		System.out.println(empObj.getId() + "-" + empObj.getEname());
	}
}

6. Use I/O streams to implement simple file copy operations and create tool class FileUtils 

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FileUtils {
	/**
	 * try .. with .. resource,释放资源 jdk9之后
	  *  直接在try(is;os)释放资源
	  *  实现文件copy
	 * @param is:输入
	 * @param os:输出
	 */
	public static void copy(InputStream is, OutputStream os) {
		try {
			//操作
			int len = -1;
			byte[] flush = new byte[1024];
			while((len = is.read(flush)) != -1) {
				os.write(flush,0,len);
			}
			//编码
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//先打开的后关闭,分别关闭
			close(is,os);
		}
	}
	

	/**
	  * 传入可变参数,来几个closeable接几个
	  * 关闭IO流
	 * @param ios io流组
	 */
	public static void close(Closeable... ios) {
		for(Closeable io : ios) {
			try {
				if(null != io) {
					io.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

 

Guess you like

Origin blog.csdn.net/Jeff_fei/article/details/103313938