JAVA IO流
一. 字节流
1.计算机中都是二进制数据,一个字节是8个2进制位.字节可以表示所有的数据,比如文本,音频,视频.图片,都是作为字节存在的.也就是说字节流处理的数据非常多。在文本文件中存储的数据是以我们能读懂的方式表示的。而在二进制文件中存储的数据是用二进制形式表示的。我们是读不懂二进制文件的,因为二进制文件是为了让程序来读取而设计的。例如,Java的源程序(.java源文件)存储在文本文件中,可以使用文本编辑器阅读,但是Java的类(字节码文件)存储在二进制文件中,可以被Java虚拟机阅读。二进制文件的优势在于它的处理效率比文本文件高。
2.输入字节流:
--------| InputStream 所有输入字节流的基类 抽象类
------------| FileInputStream 读取文件数据的输入字节流
------------| FilterInputStream
---------- –-----| BufferedInputStream 缓冲输入字节流 缓冲输入字节流的出现主要是为了提高读取文件数据的效率。 其实该类内部只不过是维护了一个8kb的字节数组而已。
2.1 使用FileInputStream读取文件数据的步骤:
1. 找到目标文件
2. 建立数据的输入通道。
3. 读取文件中的数据。
4. 关闭 资源.
2.1.1 使用read()方法一次读取一个字节
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class ioTest {
public static void main(String [] args) throws IOException {
FileInputStream fis = new FileInputStream("/home/coolboy/test");
int len = 0;
while((len=fis.read())!=-1){
System.out.println((char)len);
}
}
}
2.1.2 使用read(byte[] b) 方法。
使用缓冲区(关键是缓冲区大小的确定)使用read方法的时候,流需要读一次就处理一次,可以将读到的数据装入到字节数组中,一次性的操作数组,可以提高效率。
为了避免缓冲字符数组太小造成数据读取不完,一般建议将缓冲字符数组的大小定义为1024的倍数
FileInputStream fis = new FileInputStream("/home/coolboy/test");
byte[] byt = new byte[1024];
int len = fis.read(byt);
for(int i = 0 ;i<len ;i++)
System.out.println((char)byt[i]);
}
发现:一旦数据超过1024个字节,数组就存储不下。
如何将文件的剩余内容读完?
我们可以通过通过循环保证文件读取完。
FileInputStream fis = new FileInputStream(path);
byte[] byt = newbyte[1024];
int len = 0;
while ((len = fis.read(byt)) != -1) {
System.out.println(new String(byt, 0, len));
}
2.2 输入字节缓冲流
上述程序中我们为了提高流的使用效率,自定义了字节数组,作为缓冲区.Java其实提供了专门的字节流缓冲来提高效率.BufferedInputStream类可以通过减少读写次数来提高输入和输出的速度。它们内部有一个缓冲区,用来提高处理效率。查看API文档,发现可以指定缓冲区的大小。其实内部也是封装了字节数组。没有指定缓冲区大小,默认的字节是8192。显然缓冲区输入流和缓冲区输出流要配合使用。首先缓冲区输入流会将读取到的数据读入缓冲区,当缓冲区满时,或者调用flush方法,缓冲输出流会将数据写出。
注意:当然使用缓冲流来进行提高效率时,对于小文件可能看不到性能的提升。但是文件稍微大一些的话,就可以看到实质的性能提升了。
FileInputStream fis = new FileInputStream("/home/coolboy/test");
BufferedInputStream bi = new BufferedInputStream(fis);
int len = 0;
while((len=bi.read())!=-1){
System.out.println((char)len);
}
3.输出字节流
--------| OutputStream 是所有输出字节流 的父类。 抽象类
-----------| FileOutStream 向文件输出数据的输出字节流。
-------| FiterOutputStream
------------| BufferedOutputstream 缓冲输出字节流 BufferedOutputStream出现的目的是为了提高写数据的效率。内部也是维护了一个8kb的字节数组而已。
3.1 FileOutputStream
1. 找到目标文件
2. 建立数据的输出通道。
3. 把数据转换成字节数组写出。
4. 关闭资源
FileOutputStream fos = new FileOutputStream("/home/coolboy/test",true);
int len = 0;
byte [] buffer = "123hahaha".getBytes();
fos.write(buffer);
fos.close();
}
3.2 输出缓冲字节流 BufferedOutputStream
注:BufferedOutputStream 要注意的细节
1. 使用BufferedOutStream写数据的时候,它的write方法是是先把数据写到它内部维护的字节数组中。
2.如果需要把数据真正的写到硬盘上面,需要调用flush方法或者是close方法、 或者是内部维护的字节数组已经填满数据的时候。
3. 使用FileOutputStream写数据的时候,调用完write()方法就把数据写到硬盘上了;
FileInputStream fis = new FileInputStream("/home/coolboy/1.jpg");
FileOutputStream fos = new FileOutputStream("/home/coolboy/a/1.jpg");
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int len = 0;
while((len=bis.read())!=-1){
bos.write(len);
}
bis.close();
bos.close();
}
二.字符流
计算机并不区分二进制文件与文本文件。所有的文件都是以二进制形式来存储的,因此,从本质上说,所有的文件都是二进制文件。所以字符流是建立在字节流之上的,它能够提供字符层次的编码和解码。例如,在写入一个字符时,Java虚拟机会将字符转为文件指定的编码(默认是系统默认编码),在读取字符时,再将文件指定的编码转化为字符。
字符流 = 字节流+编码/解码
例如:使用GBK将中文保存在计算机中“中国”,其中中文占用两个字节,如果使用字节流进行输出时会显示乱码,我们的FileInputStream输入流的read() 一次是读一个字节的,
使用:"中国".getBytes() 即可得到字符串对应的字节数组,是[-42, -48, -71, -6],那么中国对应的是-42, -48, -71, -6是4个字节。那就是一个中文占2个字节,(这个
和编码是有关系的)很显然,我们的中文就不能够再一个字节一个字节的读了。
输入字符流:
---------| Reader 所有输入字符流的基类。 抽象类。
----------|java.io.InputStreamReader
----------------| FileReader 读取文件数据的输入字符流。 (是转换流的子类)
----------------| BufferedReader 缓冲输入字符流,该类出现的目的是为了提高读取文件数据的效率与 拓展FileReader的(readLine)功能。 这个类的也只不过是在内部维护了一个8kb的字符数组而已。
Reader reader = new FileReader(path);
int len = 0;
while ((len = reader.read()) != -1) {
System.out.print((char) len);
}
reader.close();
}
输出字符流:
---------| Writer 所有输出字符流的基类。 抽象类
----------------| FileWriter 向文件输出数据的输出字符流 (是转换流的子类)
----------------| BufferedWriter 缓冲输出字符流,该类出现的目的是为了提高写文件数据的效率与 拓展FileWriter的(newLine)功能.newLine() 换行。