今天主要分享的知识点是java中的IO流。我们直接进入正题。
一.什么是IO流
所谓流,就是程序与文件之间的通道,它有一个源端和一个目的端,源端和目的端可以是内存的一段区域也可以是磁盘上的某些文件。
二.IO流的分类
1.根据流的方向分(输入与输出都是按程序来说的):
输入流——从文件流向程序
输出流——从程序流向文件
2.根据流的数据的单位分:
字节流——以字节为单位读取流中的数据
(InputStream抽象类和OutputStream抽象类)
字符流——以字符为单位读取流中的数据
(Reader抽象类和Writer抽象类)
3.根据流的功能分:
节点流
处理流
三.IO流的相关类简单列出如下表格
输入流 | 输出流 | |||
InputStream(字节流) | OutputStream(字节流) | |||
基本流(低级流/节点流) | FileInputStream | FileOutputStream | ||
包装流(高级流) | DataInputStream | BufferedInputStream | DataOutputStream | BufferedOutputStream |
读入流 | 写入流 | ||
Reader(字符流) | Writer(字符流) | ||
InputStreamReader | BufferedStreamReader | OutputStreamWriter | BufferedStreamWriter |
FileReader | FileWriter |
四.以下详细说明每一对IO字节流类的基本用法
(一).InputStream和OutputStream
1.InputStream抽象类提供了如下几个常用的方法:
(1)int read()读取一个字节以整数形式返回,如果返回-1已到输入流的末尾
(2)read(byte[] b) 一次读入尽可能多的字节去填满字节数组b,返回实际读到的字节数,-1表示已读不到
(3)read(byte[] b, int off, int len) 一次读入尽可能多的字节去填满字节数组b从off开始的len个空间
(4)void close()关闭流释放内存资源
(5)long skip(long n)跳过n 个字节不读
2.InputStream抽象类提供了如下几个常用的方法:
(1)void write(int b) 向输出流写入一个字节数据
(2)void flush() 将输出流中缓冲的数据全部写出到文件中
(二)基本流FileInputStream和FileOutputStream——用于象文件中输入输出字节
用下面的例子说明其使用方法以及一些基本方法的使用:
package io;
/*
* 对文件简单的操作
*/
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 FISFOS_Test {
public static void main(String[] args) throws IOException {
//输入流文件必须存在。或者报文件找不到异常。
File file=new File("d:\\a.txt");
InputStream is=new FileInputStream(file);
//读入一个字节并返回
int i=is.read();
System.out.println(i);
//返回一次性读到的字节数
byte[] b=new byte[10];
int length=is.read(b);
System.out.println(length);
//输出流:自己会新建一个文件
// true表示追加 false表示覆盖 默认是false
OutputStream os=new FileOutputStream(file,true);
os.write(97);
//关闭字节流
is.close();
os.close();
}
}
通过上面的例子我们可以再延伸一点,实现文件的复制:
package io;
/*
* 简单的文件复制操作
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopy {
public static void main(String[] args) throws IOException {
copyFile("d:\\照片.rar","d:\\照片(副本).rar");
}
public static void copyFile(String file1,String file2) throws IOException{
FileInputStream fis = new FileInputStream(new File(file1));
FileOutputStream fos = new FileOutputStream(new File(file2));
int b = 0;
//通过定义数组实现每次读取和写入8Byte的数据,加快读写速度
byte[] arrByte = new byte[8*1024];
// 读源文件,将读入的每个字节依次写入目标文件即可。
while((b=fis.read(arrByte))!=-1){
fos.write(arrByte,0,b);
}
fis.close();
fos.close();
}
}
(三).缓冲字节流:BufferedInputStream和BufferedOutputStream
——把输入输出的字节流先存入到缓冲区中,再一次性的送到磁盘上的文件里
同样实现文件的复制过程,代码如下:
package io;
/*
* 用缓冲流实现文件的复制过程
* 循环里虽然也是一个一个的字节写入缓冲区
* 但是由于操作内存速度比磁盘快得多
* 所以可以明显的看到复制过程快于一个一个字节的写入到文件
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BISBOS {
public static void main(String[] args) throws IOException {
File file1=new File("d:\\照片.rar");
FileInputStream fis = new FileInputStream(file1);
BufferedInputStream bis = new BufferedInputStream(fis);
//下面是另一种创建方法
//BufferedInputStream bis=new BufferedInputStream(new FileInputStream(new File("d:\\照片.rar")));
File file2=new File("d:\\照片(副本).rar");
FileOutputStream fos = new FileOutputStream(file2);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int i = 0;
while((i=bis.read())!=-1){
bos.write(i);
// flush不要放在循环中,不然没意义,相当于一个字节一个字节的写。
}
// 如果缓冲区满了,自动写入文件
bos.flush();// 冲刷缓冲区,强制将缓冲区中的内容写入文件
bos.close();// close关闭之前,先flush。
}
}
(注意:对于包装类,关闭时只关闭最外层流即可,外层流提供自动关闭其内部的流)
(四).数据字节流:DataInputStream和DataOutputStream
——提供了对八种基本数据类型的数据流的读写
1.DataInputStream类的主要方法如下(具体可参见API文档):
(1)read(byte[] b)
从包含的输入流中读取一定数量的字节,并将它们存储到缓冲区数组 b
中。
(2)readBoolean()
读取一个输入字节,如果该字节不是零,则返回 true
,如果是零,则返回 false
。
(3)readByte()
读取并返回一个输入字节。
(4)readChar()
读取两个输入字节并返回一个 char
值。
(5)readDouble()
读取八个输入字节并返回一个 double
值。
(6)readFloat()
读取四个输入字节并返回一个 float
值。
(7)readInt()
读取四个输入字节并返回一个 int
值。
(8)readLong()
读取八个输入字节并返回一个 long
值。
(9)readShort()
读取两个输入字节并返回一个 short
值。
(10)readLine()
从输入流中读取下一文本行。(这个方法已过时,具体使用在下面的BufferedReader字符流中会讲解)
(11)readUTF()
读入一个已使用 UTF-8 修改版格式编码的字符串。(通常用于网络程序的传输)。
2.DataOutputStream类的方法与DataInputStream类的方法基本一一对应,不过多说明
3.下面通过一个例子说明其中readDouble()方法和writeDouble()方法的使用:
package io;
/*
* 数据字节流的简单使用
*/
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DISDOSTest {
public static void main(String[] args) throws IOException{
File file=new File("d:\\a.txt");
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
//向文件中写入小数和utf编码的汉字
dos.writeDouble(3.14);
dos.writeUTF("中国");
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);
//读取数据
double d = dis.readDouble();
String s = dis.readUTF();
//小数只能在控制台上显示,在文件里显示的是乱码
System.out.println(d);
//汉字以UTF编码可以显示,其他编码也是乱码
System.out.println(s);
dos.close();
dis.close();
}
}
4.学到此时,我们可以利用BufferedInputStream与DataInputStream的结合使用实现对小数的快速读/写,例子代码如下:
package io;
/*
* 如何快速写小数
* BufferedOutputStream/DataOutputStream/FileOutputStream
* 把小数小写到缓冲区再一次性写到文件中
*/
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class DISDOS_Double {
public static void main(String[] args) throws IOException {
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File("d:\\c.txt"))));
out.writeDouble(3.1415);
// 对于包装流,关闭时候只关闭外层流就可以了,外层流中有对内层流的关闭。
out.close();
}
}
五.以下详细说明每一对IO字符流类的基本用法
(一).Reader和Writer作为字符流的抽象类(方法不再缀余);
(二).InputStreamReader和OutputStreamWriter
FileReader和FileWriter
都是用于实现与编码有关的字符流读写。
(1)FileReader=InputStreamReader+FileInputStream;
(2)FileWriter=OutputStreamWriter+FileOutputStream;
(注意:当仅仅使用FileReader/FileWriter时只能用默认的编码,并且不能包装其他流;但用后两者结合时可以自己选择使用编码格式)
这部分的例子如下面的代码:
package io;
/*
* 使用InputStreamReader+FileInputStream
* 和OutputStreamWriter+FileOutputStream的读写
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class BianMa {
public static void main(String[] args) throws IOException {
File file = new File("d:\\b.txt");
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis,"gbk");// 自己选择编码方式
// 对于汉字来说,gbk/gb2312占两个字节,utf-8占三个字节。
char i = (char)isr.read();
System.out.println(i);
FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
osw.write("中国");
//下面的代码是用来写入所有以gbk编码格式的字符,有汉字等
//for(int k=0;k<60000;k++){
//osw.write(k);
//}
osw.close();
fis.close();
}
}
package io;
/*
* 使用FileReader和FileWriter实现的读写
* 功能与上面的一样
* 唯一区别:只能使用系统默认的编码方式
*/
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FRFW {
public static void main(String[] args) throws IOException {
// 系统默认编码
File file = new File("d:\\b.txt");
FileReader fr = new FileReader(file);
char ch = (char) fr.read();
System.out.println(ch);
// 区别 1.不能指定编码格式,按系统编码格式。2.不能包装其他流
FileWriter fw = new FileWriter(file);
fw.write("一二三四五\r\n");
fw.write("六七八九十");
fr.close();
fw.close();
}
}
(三).BufferedReader和BufferedWriter
主要注意一个新的方法readLine()参加下列代码的使用:
package io;
/*
* 重点学会使用readLine()方法
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class BRBW {
public static void main(String[] args) throws IOException {
File file = new File("d:\\b.txt");
//两次包装
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String str = null;
str = br.readLine();//读一行字符
System.out.println(str);
FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fos);
BufferedWriter bw = new BufferedWriter(osw);
bw.write("一二三四五");
bw.newLine();// 新起一行。输出一个换行符
bw.write("六七八九十");
bw.flush();// 注意冲刷
bw.close();
isr.close();
}
}
(四).PrintStream
PrintStream中的println()经常与BufferedReader中的readline()一起使用;
在Scanner出现之前,也用于实现从控制台输入一行字符;
使用实例如下:
package io;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
/*
* PrintStream中的println()经常与BufferedReader中的readline()一起使用
* 作用分别是写一行(根据是否重定向来确定写到控制台还是指定的文件中)和读一行
*/
public class SISO {
public static void main(String[] args) throws IOException {
InputStream is=System.in;
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
String str=br.readLine();
System.out.println(str);
File file =new File("d:\\g.txt");
PrintStream ps=new PrintStream(file);
ps.println("Hello");//向文件中写一行
System.out.println("控制台:hello");
System.setOut(ps);//输出重定向,写到ps指定的文件中
System.out.println("文件:Hello World");
ps.close();
}
}
控制台输出:
hello
hello
控制台:hello
g.txt文件中写入:
Hello
文件:Hello World
关于IO流的相关知识,今天就先说到这里,还剩下一部分相关知识也是很重要的知识——对象序列化,我们明天不见不散
转载于:https://blog.51cto.com/wangzhaoli/1260005