目录
Java中IO的四大抽象类
常用流详解
缓冲字节流
文件字符流
缓冲字符流
InputStream/OutputStream和Reader/writer类是所有IO流类的抽 象父类,我们有必要简单了解一下这个四个抽象类的作用。然后, 通过它们具体的子类熟悉相关的用法。
InputStream
此抽象类是表示字节输入流的所有类的父类。InputSteam是一个抽 象类,它不可以实例化。 数据的读取需要由它的子类来实现。根据 节点的不同,它派生了不同的节点流子类 。 继承自InputSteam的流都是用于向程序中输入数据,且数据的单位 为字节(8 bit)。
常用方法:
OutputStream
此抽象类是表示字节输出流的所有类的父类。输出流接收输出字节 并将这些字节发送到某个目的地。
常用方法:
Reader
Reader用于读取的字符流抽象类,数据单位为字符。
Writer
Writer用于输出的字符流抽象类,数据单位为字符。
文件字节流
FileInputStream 通过字节的方式读取文件,适合读取所有类型的文 件(图像、视频、文本文件等)。
FileOutputStream 通过字节的方式写数据到文件中,适合所有类型 的文件(图像、视频、文本文件等)。
FileInputStream文件输入字节流
public class TestFileInputStream {
public static void main(String[] args) {
//使用try-with-resource方式关闭资源。
//在try中打开资源,不需要在代码中添加finally块关闭资源。
try(FileInputStream fis = new FileInputStream("d:/a.txt");){
StringBuilder sb = new StringBuilder();
int temp=0;
while((temp = fis.read()) != -1)
{
sb.append((char) temp);
}
System.out.println(sb);
}catch(Exception e){
e.printStackTrace();
}
}
FileOutputStream文件输出字节流
public class TestFileOutputStream {
public static void main(String[] args) {
String str = "Old Lu";
// true表示内容会追加到文件末尾;false表示重写整个文件内容。
try(FileOutputStream fos = new
FileOutputStream("d:/a.txt",true)){
//将整个字节数组写入到文件中。
fos.write(str.getBytes());
//将数据从内存中写入到磁盘中。
fos.flush();
}catch (IOException e){
e.printStackTrace();
}
}
}
通过字节缓冲区提高读写效率
通过创建一个指定长度的字节数组作为缓冲区,以此来提高IO流的 读写效率。该方式适用于读取较大文件时的缓冲区定义。注意:缓 冲区的长度一定是2的整数幂。一般情况下1024长度较为合适。
public class TestFileByteBuffer{
public static void main(String[] args) {
long time1 = System.currentTimeMillis();
copyFile("d:/1.jpg", "d:/2.jpg");
long time2 = System.currentTimeMillis();
System.out.println(time2 - time1);
}
/**
*
* @param src 源文件
* @param desc 目标文件
*/
public static void copyFile(String src,String desc){
//“后开的先关闭!”按照他们被创建顺序的逆序来关闭
try(FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(desc)){
//创建一个缓冲区,提高读写效率
byte[] buffer = new byte[1024];
int temp = 0;
while ((temp = fis.read(buffer)) != -1){
//将缓存数组中的数据写入文件中,注意:写入的是读取的真实长度;
fos.write(buffer,0,temp);
}
//将数据从内存中写入到磁盘中。
fos.flush();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
注意 在使用字节缓冲区时,我们需要注意:
1、为了减少对硬盘的读写次数,提高效率,通常设置缓存数组。相应地,读取时使用的方法 为:read(byte[] b);写入时的方法为:write(byte[ ] b, int off, int length)
2、程序中如果遇到多个流,每个流都要单独关闭,防止其中一个流出现异常后导致其他流无法 关闭的情况。
Java缓冲流本身并不具有IO流的读取与写入功能,只是在别的流 (节点流或其他处理流)上加上缓冲功能提高效率,就像是把别的 流包装起来一样,因此缓冲流是一种处理流(包装流)。 BufferedInputStream和BufferedOutputStream这两个流是缓冲 字节流,通过内部缓存数组来提高操作流的效率。
使用缓冲流实现文件的高效率复制
下面我们通过两种方式(普通文件字节流与缓冲文件字节流)实现 一个文件的复制,来体会一下缓冲流的好处。
public class TestFileBufferStream {
public static void main(String[] args) {
long time1 = System.currentTimeMillis();
copyFile("d:/1.jpg","d:/2.jpg");
long time2 = System.currentTimeMillis();
System.out.println(time2 - time1);
}
public static void copyFile(String source,String destination){
//实例化节点流
try(FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(destination);
//实例化处理流
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos)){
int temp = 0;
while ((temp = bis.read()) !=-1){
bos.write(temp);
}
bos.flush();
}catch(IOException e){
e.printStackTrace();
}
}
}
注意
1、在关闭流时,应该先关闭最外层的包装流,即“后开的先关闭”。
2、缓存区的大小默认是8192字节,也可以使用其它的构造方法自己指定大小。
前面介绍的文件字节流可以处理所有的文件,如果我们处理的是文 本文件,也可以使用文件字符流,它以字符为单位进行操作。
文件字符输入流
public class TestFileReader {
public static void main(String[] args) {
//创建文件字符输入流对象
try(FileReader fr = new FileReader("d:/a.txt")){
StringBuilder sb = new StringBuilder();
//读取文件
int temp = 0;
while((temp = fr.read()) != -1){
sb.append((char)temp);
}
System.out.println(sb);
}catch (IOException e){
e.printStackTrace();
}
}
}
文件字符输出流
public class TestFileWriter {
public static void main(String[] args) {
//创建文件字符输出流对象
try(FileWriter fw = new FileWriter("d:/aa.txt")){
fw.write("您好尚\r\n");
fw.write("您好Old Lu\r\n");
fw.flush();
}catch (IOException e){
e.printStackTrace();
}
}
}
BufferedReader/BufferedWriter增加了缓存机制,大大提高了读 写文本文件的效率。
字符输入缓冲流
BufferedReader是针对字符输入流的缓冲流对象,提供了更方便的 按行读取的方法:readLine(); 在使用字符流读取文本文件时,我们 可以使用该方法以行为单位进行读取。
public class TestBufferedReader {
public static void main(String[] args) {
//创建文件字符输入流对象
try(FileReader fr = new FileReader("d:/aa.txt");
//创建字符缓冲处理流。缓冲区默认大小为8192个字符。
BufferedReader br = new BufferedReader(fr)){
//操作流
String temp = "";
//readLine():读取一行文本。
while((temp = br.readLine()) != null){
System.out.println(temp);
}
}catch(IOException e){
e.printStackTrace();
}
}
}
字符输出缓冲流
BufferedWriter是针对字符输出流的缓冲流对象,在字符输出缓冲 流中可以使用newLine();方法实现换行处理。
public class TestBufferedWriter {
public static void main(String[] args) {
//创建文件字符输出流对象
try(FileWriter fw = new FileWriter("d:/sxt.txt");
//创建字符输出缓冲流对象
BufferedWriter bw = new BufferedWriter(fw)){
//操作缓冲流
bw.write("您好尚像素");
bw.write("您好Oldlu");
//换行
bw.newLine();
bw.write("何以解忧");
bw.newLine();
bw.write("唯有学堂");
bw.flush();
}catch (IOException e){
e.printStackTrace();
}
}
}
注意
readLine()方法是BufferedReader的方法,可以对文本文件进行更加方便的读取操作。 newLine()方法BufferedWriter的方法,可以使用newLine()方法换行。
为文件中的内容添加行号
public class TestLineNumber {
public static void main(String[] args) {
//创建字符输入缓冲流与文件字符输入流
try(BufferedReader br = new BufferedReader(new FileReader("d:/sxt.txt"));
//创建字符输出缓冲流与文件字符输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("d:/sxt2.txt"))){
String temp ="";
//定义序号变量
int i = 1;
while((temp = br.readLine()) != null){
//将读取到的内容添加序号,并输出到指定文件中。
bw.write(i+","+temp);
//换行处理
bw.newLine();
//序号变量累加
i++;
}
//刷新
bw.flush();
}catch(IOException e){
e.printStackTrace();
}
}
}