抽象基类: InputStream , OutputStream。
字节流可以操作任何数据。
注意:字符流使用的数组时字符数组。char[] chs
字节流使用的数组时字节数组。byte[] bt
FileOutputStream fos = new FileOutputStream("a.txt");
fos.write("abcde");//直接将数据写入到了目的地。
fos.close();//只关闭资源。
FileInputStream fis = new FileInputStream("a.txt");
//fis.available();//获取关联的文件的字节数。
//如果文件体积不是很大。
//可以这样操作。
byte[] buf = new byte[fis.available()];//创建一个刚刚好的缓冲区。
//但是这有一个弊端,就是文件过大,大小超过jvm的内容空间时,会内存溢出。
fis.read(buf);
System.out.println(new String(buf));
需求:copy一个图片。
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("1.jpg"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("2.jpg"));
int by = 0;
while((by = bufis.read()) != -1) {
bufos.write(by);
}
bufos.close();
bufis.close();
目前学习的流对象:
字符流:
FileReader
FileWriter
BufferedReader
BufferedWriter
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
字节流的read() 方法读取一个字节。为什么返回的不是byte类型,而是int类型呢?
因为read方法读到末尾时返回的是-1.
而在所操作的数据中很容易出现连续多个1的情况,而连续读到8个1,就是-1.
导致读取会提前停止。
所以将读到的一个字节给提升为一个int类型的数值,但是只保留原字节,并在剩余二进制位补0.
具体操作是:byte&255 or byte&0xff
对于write方法,可以一次写入一个字节,但接收的是一个int类型数值。
只写入该int类型的数值的最低一个字节(8位)。
简单说:read方法对读到的数据进行提升。write对操作的数据进行转换。
转换流:
特点:
1:是字节流和字符流之间的桥梁。
2:该流对象中可以对读取到的字节数据进行指定编码表的编码转换。
什么时候使用呢?
1:当字节和字符之间有转换动作时。
2:流操作的数据需要进行编码表的指定时。
具体的对象体现:
1:InputStreamReader:字节到字符的桥梁。
2:OutputStreamWriter:字符到字节的桥梁。
这两个流对象是字符流体系中的成员。
那么它们有转换作用,而本身又是字符流。所以在构造的时候,需要传入字节流对象进来。
构造函数:
InputStreamReader(InputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK
InputStreamReader(InputStream,String charSet):通过该构造函数初始化,可以指定编码表。
OutputStreamWriter(OutputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK。
OutputStreamWriter(OutputStream,String charSet):通过该构造函数初始化,可以指定编码表。
操作文件的字符流对象时转换流的子类。
Reader
--->InputStreamReader
--->FileReader
Writer
--->OutputStreamWriter
--->FileWriter
转换流中的read方法。已经融入了编码表,
在底层调用字节流的read方法时将获取的一个或者多个字节数据进行临时存储,并去查指定的编码表,如果编码表没有指定,查的是默认编码表。那么转换流的read方法就可以返回一个字符比如中文。
转换流已经完成了编码转换的动作,对于直接操作的文本文件的FileReader而言,就不用在重新定义了,只要继承该转换流,获取其方法,就可以直接操作文本文件中的字符数据了。
注意:
在使用FileReader操作文本数据时,该对象使用的是默认的编码表。如果要使用指定编码表时,必须使用转换流。
FileReader fr = new FileReader("a.txt");//操作a.txt中的数据使用本系统默认编码GBK。操作a.txt中的数据使用的也是本系统默认编码GBK。
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
这两句的代码的意义相同。
如果a.txt中的文件中的字符数据时通过utf-8的形式编码。
那么在读取时,就必须指定编码表。
那么转换流必须使用。
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"utf-8");
流操作的基本规律。
1:明确数据源和数据汇(数据目的)。
其实是为了明确输入流还是输出流。
2:明确操作的数据是否时纯文本数据。
其实是为了明确字符流还是字节流。
数据源:键盘System.int , 硬盘 File 开头的流对象,内存(数组)。
数据汇:控制台System.out,硬盘 File 开头的流对象 , 内存(数组)。
需求:
1:将键盘录入的数据存储到一个文件中。
数据源:System.in
既然是源,使用的就是输入流,可用的体系有InputStream , Reader.
因为键盘录入进来的一定时纯文本数据,所以可以使用专门操作字符数据的Reader。
发现System.in对应的流时字节读取流。所以要将其进行转换,将字节转成字符即可。
所以要使用Reader体系中:InputStreamReader
接下来,是否需要提高效率呢?如果需要,那么就加入字符流的缓冲区:BufferedReader
BufferedReader bur = new BufferedReader(new InputStreamReader(System.in));
数据汇:一个文件,硬盘。
既然时数据汇,那么一定时输出流,可以用的OutputStream,Writer.
往文件中存储的都是文本数据,那么可以使用字符流较为方便:Writer.
因为操作的是一个文件。所以使用Writer中的FileWriter。
是否要提高效率呢?是,那么就使用BufferedWriter.
BufferedWriter bufr = new BufferedWriter(new FileWriter("a.txt"));
附加需求:希望将这些文本数据按照指定的编码表存入文件中。
既然是文本数据,而且还是写入到文件中,那么使用的体系还是Writer。
因为要指定编码表,所以要使用Writer中的转换流,OutputStreamWriter。
是否要提高效率,是,选择BufferedWriter。
注意:虽然最终是文件,但是不可以选择FileWriter。因为该对象是使用默认编码表。
输出转换流要接收一个字节输出流进来,所以要使用OutputStream体系,而最终输出到一个文件中,
那么就要使用OutputStream体系中可以操作的文件的字节流对象:FileOutputStream。
//String charSet = System.getProperty("file.encoding");
String charSet = "utf-8";
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt"),charSet);