第一篇:IO,对象传输的基石(一)

文章目录

一、前言

二、文件字节流

2.1 概述

Java中,凡是涉及到Java程序的输入输出,一般都逃不过IO流,Java中的IO包括BIO和NIO,其中BIO只要是以四大基流基础的各种各样的阻塞流。BIO的四大基流是:InputStream OutputStream Reader Writer,但是它们都是抽象类,不能实例化对象来完成输入输出操作,直接使用的是它们的子类,本部分中,使用FileInputStream和FileOutputStream就可以完成输入输出。

BIO的四大基流

输入流输出流
字节流字节输入流InputStream字节输出流OutputStream
字符流字符输入流Reader字符输出流Writer

使用BIO流的四个步骤:
1):创建源或者目标对象(挖井).
输入操作: 把文件中的数据流向到程序中,此时文件是源,程序是目标.
输出操作: 把程序中的数据流向到文件中,此时文件是目标,程序是源.
2):创建IO流对象(水管).
输入操作: 创建输入流对象.
输出操作: 创建输出流对象.
3):具体的IO操作.
输入操作: 输入流对象的read方法.
输出操作: 输出流对象的write方法.
4):关闭资源(勿忘). 一旦资源关闭之后,就不能使用流对象了,否则报错.
输入操作: 输入流对象.close();
输出操作: 输出流对象.close().

关于BIO流的方向:
读进来,写出去。
读进来是指:从文件、网络、压缩包或其他数据源到Java程序;
写出去是指:从Java程序到文件、网络、压缩包或其他输出目标。
在这里插入图片描述

2.2 文件字节输入流FileInputStream、文件字节输出流FileOutputStream

注意,这里指的文件仅为纯文本文件txt,不包括doc docx等文件。

2.2.1 文件字节输出流

package mypackage;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

//文件字节输出流
public class Test {

	public static void main(String[] args) throws IOException {
		File target = new File("stream.txt");// 程序可以自动创建txt文件
		OutputStream outputStream = new FileOutputStream(target); // 四大基流不能直接实例化对象,实例化对象还要具体IO类,这里是FileOutputStream
		outputStream.write("hello world!".getBytes(), 0, 12);
		outputStream.close();
	}

}

输出1:

在这里插入图片描述

小结1:文件字节输出流,将文本从程序输出到stream.txt中。

2.2.2 文件字节输入流

package mypackage2;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

//文件字节输入流
public class Test {
	public static void main(String[] args) throws IOException {
		File file = new File("stream.txt");
		InputStream inputStream = new FileInputStream(file);

		byte[] buffer = new byte[1024];
		int len = -1;
		while ((len = inputStream.read(buffer)) != -1) {
			String string = new String(buffer, 0, len); // 每次读入一个缓冲大小然后输出
			System.out.println(string);
		}
		inputStream.close();
	}
}

输出2:

hello world!

小结2:文件字节输入流,将文本从stream.txt输入到程序中,并打印到控制台。

2.2.3 先读入再写出 从myStream.txt读入,写出到myStream_copy.txt中

package mypackage3;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Test {
	// 先读入再写出 从myStream.txt读入,写出到myStream_copy.txt中
	// 从myStream.txt中读入数据,然后写入到myStream_copy.txt中
	public static void main(String[] args) throws IOException {
		File srcFile = new File("myStream.txt"); // 源文件
		File destFile = new File("myStream_copy.txt");// 目标文件

		InputStream inputStream = new FileInputStream(srcFile);
		OutputStream outputStream = new FileOutputStream(destFile);

		byte[] buffer = new byte[10];
		int len = -1;
		while ((len = inputStream.read(buffer)) != -1) {
			outputStream.write(buffer, 0, len);
		}

		inputStream.close();
		outputStream.close();
	}

}

输出3:

在这里插入图片描述

小结3:先读入再写出,从myStream.txt读入,写出到myStream_copy.txt中,将输入输出流一起使用。

2.2.4 先写出再读入 写出到FileStream.txt,在读入到程序中,打印出来

package mypackage4;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Test {
	// 先写出再读入 写出到FileStream.txt,在读入到程序中,打印出来
	public static void main(String[] args) throws IOException {
		File srcFile = new File("FileStream.txt");// 程序可以自动创建txt文件
		File destFile = new File("FileStream.txt");

		OutputStream outputStream = new FileOutputStream(srcFile); // 四大基流不能直接实例化对象,实例化对象还要具体IO类,这里是FileOutputStream
		InputStream inputStream = new FileInputStream(destFile);

		outputStream.write("hello world!".getBytes(), 0, 12);
		byte[] buffer = new byte[1024];
		int len = -1;
		while ((len = inputStream.read(buffer)) != -1) {
			String string = new String(buffer, 0, len); // 每次读入一个缓冲大小然后输出
			System.out.println(string);
		}

		outputStream.close();
		inputStream.close();
	}

}

输出4:

hello world!

在这里插入图片描述

小结4:先写出再读入,写出到FileStream.txt,再读入到程序中,打印出来,输入输出流一起使用。

2.3 面试金手指:文件字节输入流 + 文件字节输出流

Java中,凡是涉及到Java程序的输入输出,一般都逃不过IO流,Java中的IO包括BIO和NIO,其中BIO只要是以四大基流基础的各种各样的阻塞流。BIO的四大基流是:InputStream OutputStream Reader Writer,但是它们都是抽象类,不能实例化对象来完成输入输出操作,直接使用的是它们的子类,本部分中,使用FileInputStream和FileOutputStream就可以完成输入输出。

BIO的四大基流

输入流输出流
字节流字节输入流InputStream字节输出流OutputStream
字符流字符输入流Reader字符输出流Writer

使用BIO流的四个步骤:
1):创建源或者目标对象(挖井).
输入操作: 把文件中的数据流向到程序中,此时文件是源,程序是目标.
输出操作: 把程序中的数据流向到文件中,此时文件是目标,程序是源.
2):创建IO流对象(水管).
输入操作: 创建输入流对象.
输出操作: 创建输出流对象.
3):具体的IO操作.
输入操作: 输入流对象的read方法.
输出操作: 输出流对象的write方法.
4):关闭资源(勿忘). 一旦资源关闭之后,就不能使用流对象了,否则报错.
输入操作: 输入流对象.close();
输出操作: 输出流对象.close().

关于BIO流的方向:
读进来,写出去。
读进来是指:从文件、网络、压缩包或其他数据源到Java程序;
写出去是指:从Java程序到文件、网络、压缩包或其他输出目标。
在这里插入图片描述

三、文件字符流

3.1 引入:字符流

问题1:为什么有了字节流还要有字符流呢?
回答1:乱码问题引入字符流:上面操作的文本都是英文文本,不存在任何乱码问题,如果操作中文文本,字节流存在乱码问题,用字符流解决。使用字节流操作汉字或特殊的符号语言的时候,容易乱码,建议使用字符流.

问题2:为什么有了文件字节流还要有文件字符流呢?
回答2:字符流是字节流的补充:先有字节流,后有字符流,字符流是对字节流的补充.
使用记事本打开某个文件,可以看到内容的就是文本文件,否则可以理解二进制.
一般的,操作二进制文件(图片,音频,视频等)必须使用字节流.
一般的,操作文本文件使用字符流.
如果不清楚是哪一类型文件,使用字节流.

3.2 字符流

3.2.1 文件字符输入流

package mypackage;
 
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
 
//字符输入流
public class Test {
 
	public static void main(String[] args) throws IOException {
		File srcFile = new File("china.txt");
		Reader reader = new FileReader(srcFile);
		char[] buffer = new char[1024];
		int len = -1;
		while ((len = reader.read(buffer)) != -1) {
			System.out.println(buffer);
		}
		reader.close();
	}
 
}

输出1:

Java程序员就业前景好,薪资高!
一起来学习Java吧!

小结1:文件字符输入流,将文本内容从china.txt读入程序并打印出来。

3.2.2 文件字符输出流

package mypackage2;
 
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
 
//字符输出流
public class Test {
 
	public static void main(String[] args) throws IOException {
		File file = new File("china.txt");
		Writer writer = new FileWriter(file, false);
		writer.write("Java程序员就业前景好,薪资高!");
		writer.write("\n");
		writer.write("一起来学习Java吧!");
		writer.flush();
		writer.close();
	}
 
}

输出2:
在这里插入图片描述

小结2:文件字符输出流,将程序的文本写出到china.txt中。

2.2.3 先输入后输出 从mychina.txt文件输入,输出到mychina_copy.txt文件

package mypackage3;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
 
//先输入后输出    从mychina.txt文件输入,输出到mychina_copy.txt文件
public class Test {
 
	public static void main(String[] args) throws Exception {
		File srcFile = new File("mychina.txt");
		File destfile = new File("mychina_copy.txt");
 
		Reader reader = new FileReader(srcFile);
		Writer writer = new FileWriter(destfile, false);
 
		char[] buffer = new char[1024];
		int len = -1;
 
		while ((len = reader.read(buffer)) != -1) {
			writer.write(buffer, 0, len);
 
		}
 
		reader.close();
		writer.close();
	}
 
}

输出3:

小结3:先输入后输出,从mychina.txt文件输入,输出到mychina_copy.txt文件。

2.2.4 先输出后输入 先写出到mychinaChar,再从mychinaChar读入程序,打印到控制台:

package mypackage4;
 
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
 
//先输出后输入     先写出到mychinaChar,再从mychinaChar读入程序,打印到控制台
public class Test {
 
	public static void main(String[] args) throws Exception {
		File targetFile = new File("mychinaChar.txt");
 
		Writer writer = new FileWriter(targetFile, false);
		Reader reader = new FileReader(targetFile);
 
		// 写出到mychinaChar
		writer.write("Java程序员就业前景好,薪资高!");
		writer.write("\n");
		writer.write("一起来学习Java吧!");
 
		writer.flush(); // 字符写出 一定要刷新
 
		char[] buffer = new char[1024];
		int len = -1;
 
		while ((len = reader.read(buffer)) != -1) {
			System.out.println(buffer);
 
		}
 
		reader.close();
		writer.close();
 
	}
 
}

输出4:

Java程序员就业前景好,薪资高!
一起来学习Java吧!

小结4:先输出后输入,先写出到mychinaChar,再从mychinaChar读入程序,打印到控制台!

3.3 面试金手指:文件字符输入流 + 文件字符输出流

JavaIO流——文件字符流,包括文件字符输入流FileReader,文件字符输出流FileWriter,这两种流联合起来完成最基本的字符操作。

四、提交效率:缓冲流 + byte数组

4.1 引入:缓冲流 + byte数组,两种提高IO效率的方式

比较四种方式下,对于同一文件stream.txt,JavaIO流输入输出操作的总时间。分别是:不使用缓冲流不使用byte数组(代码1),使用缓冲流(代码2),使用byte数组(代码3),同时使用缓冲流和byte数组(代码4)。

注意:txt内容一定要足够大,否则效果不明显,IO流一下子就操作完了

4.2 缓冲流 + byte数组

4.2.1 不使用缓冲流不使用byte数组:直接使用文件字节输入和文件字节输出

package mypackage;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
 
//用缓冲流和缓冲数组提高读写效率   要将文本内容弄长一些效果才明显   同时拥有读入流和写出流
//先读入后写出    从stream.txt中读入,写出到stream_copy.txt中
public class Test {
 
	public static void main(String[] args) throws Exception {
		long begin = System.currentTimeMillis();
		File srcFile = new File("stream.txt");
		File destFile = new File("stream_copy.txt");
		InputStream inputStream = new FileInputStream(srcFile);
		OutputStream outputStream = new FileOutputStream(destFile);
 
		int len = -1;
		while ((len = inputStream.read()) != -1) {
			outputStream.write(len);
		}
 
		inputStream.close();
		outputStream.close();
		System.out.println(System.currentTimeMillis() - begin);
 
	}
 
}

输出1:

640

小结1:不使用缓冲流不使用byte数组,IO流操作速度最慢,640毫秒。

4.2.2 使用缓冲流包一层:缓冲流包裹文件字节输入和文件字节输出

package mypackage2缓冲流;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
 
//用缓冲流和缓冲数组提高读写效率   要将文本内容弄长一些效果才明显   同时拥有读入流和写出流
//先读入后写出    从stream.txt中读入,写出到stream_copy.txt中
public class Test {
 
	public static void main(String[] args) throws Exception {
		long begin = System.currentTimeMillis();
		File srcFile = new File("stream.txt");
		File destFile = new File("stream_copy.txt");
		InputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile));
		OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(destFile));
 
		int len = -1;
		while ((len = inputStream.read()) != -1) {
			outputStream.write(len);
		}
 
		inputStream.close();
		outputStream.close();
		System.out.println(System.currentTimeMillis() - begin);
 
	}
 
}

输出2:

8

小结2:使用缓冲流,加快了速度。

4.2.3 使用byte数组:文件字节读取和文件字节写出都是用byte数组

package mypackage3_1024数组;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
 
//用缓冲流和缓冲数组提高读写效率   要将文本内容弄长一些效果才明显   同时拥有读入流和写出流
//先读入后写出    从stream.txt中读入,写出到stream_copy.txt中
public class Test {
 
	public static void main(String[] args) throws Exception {
		long begin = System.currentTimeMillis();
		File srcFile = new File("stream.txt");
		File destFile = new File("stream_copy.txt");
		InputStream inputStream = new FileInputStream(srcFile);
		OutputStream outputStream = new FileOutputStream(destFile);
		byte[] buffer = new byte[1024]; // 每次1024个
		int len = -1;
		while ((len = inputStream.read(buffer)) != -1) {
			outputStream.write(buffer, 0, len);
		}
 
		inputStream.close();
		outputStream.close();
		System.out.println(System.currentTimeMillis() - begin);
 
	}
 
}

输出3:

1

小结3:使用了byte数组,加快了速度。

4.2.4 同时使用缓冲流和byte数组:缓冲流包一层,然后得到的缓冲流的读入和写出都用byte数组

package mypackage4缓冲流_1024数组;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
 
//用缓冲流和缓冲数组提高读写效率   要将文本内容弄长一些效果才明显   同时拥有读入流和写出流
//先读入后写出    从stream.txt中读入,写出到stream_copy.txt中
public class Test {
 
	public static void main(String[] args) throws Exception {
		long begin = System.currentTimeMillis();
		File srcFile = new File("stream.txt");
		File destFile = new File("stream_copy.txt");
		InputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile));
		OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(destFile));
		byte[] buffer = new byte[1024]; // 每次1024个
		int len = -1;
		while ((len = inputStream.read(buffer)) != -1) {
			outputStream.write(buffer, 0, len);
		}
 
		inputStream.close();
		outputStream.close();
		System.out.println(System.currentTimeMillis() - begin);
 
	}
 
}

输出4:

1

小结4:同时使用缓冲流和byte数组,大大加快速度。

4.3 面试金手指:缓冲流 + byte数组

缓冲流和byte数组(字节流byte数组,字符流char数组)都可以加速IO流读写速度,本程序(代码1、代码2、代码3、代码4)中由于stream.txt文本不够大,所以效果不是很明显。实际上,第四种方式,同时使用缓冲流和byte数组,速度是最快的,读者知道就好。
(1)不使用缓冲流不使用byte数组:直接使用文件字节输入和文件字节输出;
(2)使用缓冲流包一层:缓冲流包裹文件字节输入和文件字节输出;
(3)使用byte数组:文件字节读取和文件字节写出都是用byte数组;
(4)同时使用缓冲流和byte数组:缓冲流包一层,然后得到的缓冲流的读入和写出都用byte数组.

五、字符编码

5.1 编码和解码

编码: 把字符串转换为byte数组.
解码: 把byte数组转换为字符串.
一定要保证编码和解码的字符相同,否则乱码.

5.2 代码:编码和解码

5.2.1 字符串编码为byte数组,byte数组解码为字符串

代码1:

package mypackage;
 
import java.util.Arrays;
 
//编码:  把字符串转换为byte数组.
//解码:  把byte数组转换为字符串.
//一定要保证编码和解码的字符相同,否则乱码.
public class Test {
 
	public static void main(String[] args) throws Exception {
		String mString = "Java程序员就业前景好,薪资高";   // 字符串
		byte[] data = mString.getBytes("UTF-8");   // 字符串变为byte数组,编码
 
		// String ret=new String(data,"GBK"); //使用GBK解码乱码,一定要保证编码和解码的字符相同,否则乱码.
		// System.out.println(ret);
 
		String ret = new String(data, "UTF-8");    // byte数组变为字符串,解码
		System.out.println(ret);    // 打印解码
 
	}
 
}

输出1:

Java程序员就业前景好,薪资高

小结1:一定要保证编码和解码的字符相同,否则乱码.

5.2.2 困境:字符串UTF-8编码为byte数组,byte数组GBK解码为字符串

代码2——困境:

package mypackage1;
 
//编码:  把字符串转换为byte数组.
//解码:  把byte数组转换为字符串.
//一定要保证编码和解码的字符相同,否则乱码.
public class Test {
 
	public static void main(String[] args) throws Exception {
		String mString = "Java程序员就业前景好,薪资高";
		byte[] data = mString.getBytes("UTF-8"); // 编码UTF-8
 
		String ret = new String(data, "GBK"); // 解码GBK
 
	}
 
}

小结2:这里编码UTF-8,但是解码GBK,接下来怎么破,且看代码3.

5.2.3 解决:字符串UTF-8编码为byte数组,byte数组GBK解码为字符串,然后,字符串再次GBK编码一次得到byte数组,最后byte数组UTF-8解码一次得到字符串,打印出来

代码3——破解代码2的困境:

package mypackage1;
 
//编码:  把字符串转换为byte数组.
//解码:  把byte数组转换为字符串.
//一定要保证编码和解码的字符相同,否则乱码.
public class Test {
 
	public static void main(String[] args) throws Exception {
		String mString = "Java程序员就业前景好,薪资高";
		byte[] data = mString.getBytes("UTF-8"); // 编码UTF-8
 
		String ret = new String(data, "GBK"); // 解码GBK
 
		data = ret.getBytes("GBK"); // 编码
 
		ret = new String(data, "UTF-8");
		System.out.println(ret);
	}
 
}

输出3:

Java程序员就业前景好,薪资高

小结3:所谓的编码解码,无非就是正过来一次,反过来一次罢了,这里编码UTF-8,解码GBK,接下来只能编码GBK,解码UTF-8破解,就是破解方法和前面的编码解码反过来就好了。

5.3 面试金手指:字符编码

字符编码:只要记住两条,
第一,编码和解码的字符要相同,否则乱码;
第二,不管前面编码解码多么复杂,只要反过来操作就可以还原内容,打印出来。
2.1 字符串编码为byte数组,byte数组解码为字符串;
2.2 困境:字符串UTF-8编码为byte数组,byte数组GBK解码为字符串;
2.3 解决:字符串UTF-8编码为byte数组,byte数组GBK解码为字符串,然后,字符串再次GBK编码一次得到byte数组,最后byte数组UTF-8解码一次得到字符串,打印出来。

六、转换流

6.1 概述:转换流,将字节流转换为字符流

JavaIO流——转换流,将字节流转换为字符流。
InputStreamReader:把字节输入流转成字符输入流.
OutputStreamWriter:把字节输出流转成字符输出流.
为什么有字节转字符流,没有字符转字节流?
字节流可以操作一切文件(纯文本文件/二进制文件).字符流是用来操作中文纯文本使用的,本身是对字节流的增强.所以字节流转换为字符流是安全的,字符流转换为字节流不一定安全,所以没有字符流转换
为字节流,个人理解,非官方解释,皮!

在这里插入图片描述

解释上图:
字符流是接口,转化流是字符流的非抽象子类,可以实例化对象,但是使用字节流对象作为构造器参数,然后文件字符流和是转换流的子类,可以单独使用

6.2 代码:转换流,将字节流转换为字符流,一段代码,包裹使用,转换流包裹文件字节输入流和文件字节输出流

先读入originStream.txt内容到程序,再将内容写出到targetStream.txt:

package mypackage_输入流输出流;
 
//转换流:把字节流转成字符流:
 
//InputStreamReader:把字节输入流转成字符输入流.
//OutputStreamWriter:把字节输出流转成字符输出流.
//为什么有字节转字符流,没有字符转字节流.
//  字节流可以操作一切文件(纯文本文件/二进制文件).
//  字符流是用来操作中文纯文本使用的,本身是对字节流的增强.
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
 
//先读入originStream.txt内容到程序,再将内容写出到targetStream.txt
public class Test {
 
	public static void main(String[] args) throws Exception {
		File originStream = new File("originStream.txt");
		File targetStream = new File("targetStream.txt");
		Reader reader = new InputStreamReader(new FileInputStream(originStream));
		Writer writer = new OutputStreamWriter(new FileOutputStream(targetStream));
 
		char[] buffer = new char[1024]; // 字节流用byte[1024]作为缓冲,字符流用char[1024]作为缓冲
		// 注意,这个缓冲buffer数组大小是任意的,可以是5,可以是10,可以是1000,可以是1024 仅表示一次读写的字节数或字符数
		int len = -1;
		while ((len = reader.read(buffer)) != -1) {
			writer.write(buffer, 0, len);
		}
		reader.close();
		writer.close();
	}
 
}

输入:
在这里插入图片描述

输出1:

在这里插入图片描述

小结1:上面的逻辑上没有特别之处,就是输入流+输出流,先读入originStream.txt内容到程序,再将内容写出到targetStream.txt。演示的意义在于加入了转换流,将字符操作变为字节操作,用于完成输入输出。

6.3 面试金手指:转换流,将字节流转换为字符流

Java BIO中的转换流,将字节流转换为字符流,为我们提供了一种字符操作变为字节操作,进而实现输入输出的方式。
代码演示的逻辑上没有特别之处,就是输入流+输出流,先读入originStream.txt内容到程序,再将内容写出到targetStream.txt。演示的意义在于加入了转换流,将字符操作变为字节操作,用于完成输入输出。

七、内存流/数组流/字符串流

7.1 概述:内存流

JavaIO流——内存流,内存流实际是数组流/字符串流
内存流(数组流):适配器模式:
1):字节内存流: ByteArrayInputStream/ByteArrayOutputStream 先将数据先临时存在byte数组中,待会再从byte数组中获取出来.
2):字符内存流: CharArrayReader/CharArrayWriter 先将数据先临时存在char数组中,待会再从char数组中获取出来.
3):字符串流:StringReader/StringWriter 先将数据(字符串)从程序写出到stringwriter中,即临时存储到字符串中,然后将stringwriter中的内容读入程序并打印出来。

7.2 代码:内存流,在内存中呆一会,三段代码,单独使用,ByteArrayXxx CharArrayXxx,StringXxx

7.2.1 字节内存流

package mypackage_字节数组流;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
 
//内存流(数组流):适配器模式:
//	   把数据先临时存在数组中,待会再从数组中获取出来.
//	   1):字节内存流: ByteArrayInputStream/ByteArrayOutputStream  数据临时存放到数组中
//	   2):字符内存流: CharArrayReader/CharArrayWriter    数据临时存放到数组中
//	   3):字符串流:StringReader/StringWriter(把数据临时存储到字符串中)
//字节内存流——字节数组流     内存流实际是数组流,字节内存流和字符内存流都是将数据存放到数组中,字符串流将数据存放到字符串中。
public class Test {
 
	public static void main(String[] args) throws Exception {
		// 数据从程序写出到内存(即数组)   内存字节输出流
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		byteArrayOutputStream.write("Java is the best language".getBytes());
		byte[] buffer = byteArrayOutputStream.toByteArray();
		byteArrayOutputStream.close();
 
		// 数据从内存(即数组)读入到程序   内存字节输入流
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buffer);
		byte[] _bytes = new byte[1024];// 字节缓冲为byte数组
		int len = -1;
		while ((len = byteArrayInputStream.read(_bytes)) != -1) {
			System.out.println(new String(_bytes, 0, len));
		}
		byteArrayInputStream.close();
	}
}

输出1:

Java is the best language

小结1:这里演示字节内存流,先将“Java is the best language”从程序写出到内存数组buffer中,然后将buffer数组中的内容读入程序并打印出来。

7.2.2 字符内存流

package mypackage_字符数组流;
 
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
 
public class Test {
 
	public static void main(String[] args) throws Exception {
		// 数据从程序写出到内存(即数组)
		CharArrayWriter charArrayWriter = new CharArrayWriter();
		charArrayWriter.write("Java程序员就业前景好,薪资高!一起来学习Java吧!");
		char[] buffer = charArrayWriter.toCharArray();
		charArrayWriter.close();
 
		// 数据从内存(即数组)读入到程序
		CharArrayReader charArrayReader = new CharArrayReader(buffer);
		char[] _chars = new char[1024];// 字节缓冲为byte数组
		int len = -1;
		while ((len = charArrayReader.read(_chars)) != -1) {
			System.out.println(new String(_chars, 0, len));
		}
		charArrayReader.close();
	}
 
}

输出2:

Java程序员就业前景好,薪资高!一起来学习Java吧!

小结2:这里演示字符内存流,先将“Java程序员就业前景好,薪资高!一起来学习Java吧!”从程序写出到内存数组buffer中,然后将buffer数组中的内容读入程序并打印出来。不同的是,字节内存流用byte数组,字符内存流用char数组。

7.2.3 字符串流

package 字符串流;
 
import java.io.StringReader;
import java.io.StringWriter;
 
public class Test {
 
	public static void main(String[] args) throws Exception {
		// 数据从程序写出到内存(即数组)
		StringWriter stringWriter = new StringWriter();
		stringWriter.write("Java程序员就业前景好,薪资高!一起来学习Java吧!");
 
		// 数据从内存(即数组)读入到程序
		StringReader stringReader = new StringReader(stringWriter.toString());
		char[] _chars = new char[1024];// 字节缓冲为byte数组
		int len = -1;
		while ((len = stringReader.read(_chars)) != -1) {
			System.out.println(new String(_chars, 0, len));
		}
 
		stringReader.close();
		stringWriter.close();
	}
 
}

输出3:

Java程序员就业前景好,薪资高!一起来学习Java吧!

小结3:这里演示字符串流,先将“Java程序员就业前景好,薪资高!一起来学习Java吧!”从程序写出到stringwriter中,然后将stringwriter中的内容读入程序并打印出来。

7.3 面试金手指:内存流/数组流/字符串流

Java内存流分为三种字节内存流、字符内存流、字符串流,都分别有输入流和输出流,
1):字节内存流: ByteArrayInputStream/ByteArrayOutputStream 先将数据先临时存在byte数组中,待会再从byte数组中获取出来.
2):字符内存流: CharArrayReader/CharArrayWriter 先将数据先临时存在char数组中,待会再从char数组中获取出来.
3):字符串流:StringReader/StringWriter 先将数据(字符串)从程序写出到stringwriter中,即临时存储到字符串中,然后将stringwriter中的内容读入程序并打印出来。

八、面试金手指

8.1 文件字节输入流 + 文件字节输出流

Java中,凡是涉及到Java程序的输入输出,一般都逃不过IO流,Java中的IO包括BIO和NIO,其中BIO只要是以四大基流基础的各种各样的阻塞流。BIO的四大基流是:InputStream OutputStream Reader Writer,但是它们都是抽象类,不能实例化对象来完成输入输出操作,直接使用的是它们的子类,本部分中,使用FileInputStream和FileOutputStream就可以完成输入输出。

BIO的四大基流

输入流输出流
字节流字节输入流InputStream字节输出流OutputStream
字符流字符输入流Reader字符输出流Writer

使用BIO流的四个步骤:
1):创建源或者目标对象(挖井).
输入操作: 把文件中的数据流向到程序中,此时文件是源,程序是目标.
输出操作: 把程序中的数据流向到文件中,此时文件是目标,程序是源.
2):创建IO流对象(水管).
输入操作: 创建输入流对象.
输出操作: 创建输出流对象.
3):具体的IO操作.
输入操作: 输入流对象的read方法.
输出操作: 输出流对象的write方法.
4):关闭资源(勿忘). 一旦资源关闭之后,就不能使用流对象了,否则报错.
输入操作: 输入流对象.close();
输出操作: 输出流对象.close().

关于BIO流的方向:
读进来,写出去。
读进来是指:从文件、网络、压缩包或其他数据源到Java程序;
写出去是指:从Java程序到文件、网络、压缩包或其他输出目标。
在这里插入图片描述

8.2 文件字符输入流 + 文件字符输出流

JavaIO流——文件字符流,包括文件字符输入流FileReader,文件字符输出流FileWriter,这两种流联合起来完成最基本的字符操作。

8.3 提高IO效率:缓冲流 + byte数组

缓冲流和byte数组(字节流byte数组,字符流char数组)都可以加速IO流读写速度,本程序(代码1、代码2、代码3、代码4)中由于stream.txt文本不够大,所以效果不是很明显。实际上,第四种方式,同时使用缓冲流和byte数组,速度是最快的,读者知道就好。
(1)不使用缓冲流不使用byte数组:直接使用文件字节输入和文件字节输出;
(2)使用缓冲流包一层:缓冲流包裹文件字节输入和文件字节输出;
(3)使用byte数组:文件字节读取和文件字节写出都是用byte数组;
(4)同时使用缓冲流和byte数组:缓冲流包一层,然后得到的缓冲流的读入和写出都用byte数组.

8.4 编码解码

字符编码:只要记住两条,
第一,编码和解码的字符要相同,否则乱码;
第二,不管前面编码解码多么复杂,只要反过来操作就可以还原内容,打印出来。
2.1 字符串编码为byte数组,byte数组解码为字符串;
2.2 困境:字符串UTF-8编码为byte数组,byte数组GBK解码为字符串;
2.3 解决:字符串UTF-8编码为byte数组,byte数组GBK解码为字符串,然后,字符串再次GBK编码一次得到byte数组,最后byte数组UTF-8解码一次得到字符串,打印出来。

8.5 转换流,字节输入输出转换为字符输入输出

JavaIO流——转换流,将字节流转换为字符流。
InputStreamReader:把字节输入流转成字符输入流.
OutputStreamWriter:把字节输出流转成字符输出流.
为什么有字节转字符流,没有字符转字节流?
字节流可以操作一切文件(纯文本文件/二进制文件).字符流是用来操作中文纯文本使用的,本身是对字节流的增强.所以字节流转换为字符流是安全的,字符流转换为字节流不一定安全,所以没有字符流转换为字节流,个人理解,非官方解释,皮!

在这里插入图片描述

字符流是接口,转化流是字符流的非抽象子类,可以实例化对象,但是使用字节流对象作为构造器参数,然后文件字符流和是转换流的子类,可以单独使用

Java BIO中的转换流,将字节流转换为字符流,为我们提供了一种字符操作变为字节操作,进而实现输入输出的方式。
代码演示的逻辑上没有特别之处,就是输入流+输出流,先读入originStream.txt内容到程序,再将内容写出到targetStream.txt。演示的意义在于加入了转换流,将字符操作变为字节操作,用于完成输入输出。

8.6 内存流,让数据在内存中呆一会,内存字节输入输出 + 内存字符输入输出 + 字符串输入输出

Java内存流就是让数据在内存中呆一会,分为三种字节内存流、字符内存流、字符串流,都分别有输入流和输出流,
1):字节内存流: ByteArrayInputStream/ByteArrayOutputStream 先将数据先临时存在byte数组中,待会再从byte数组中获取出来.
2):字符内存流: CharArrayReader/CharArrayWriter 先将数据先临时存在char数组中,待会再从char数组中获取出来.
3):字符串流:StringReader/StringWriter 先将数据(字符串)从程序写出到stringwriter中,即临时存储到字符串中,然后将stringwriter中的内容读入程序并打印出来。

九、尾声

IO,对象传输的基石(一),完成了。

天天打码,天天进步!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祖母绿宝石

打赏一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值