什么是字节流和字符流
字节流类间的继承关系
从图片上可以看出字节输入流InputStream和字节输出流OutputStream都实现了Closeable接口,这个接口中提供了一个close()方法,用来释放资源,在我们创建输入输出流并且用完时,我们需要关闭输入输出流。在关闭输出流之前,我们需要用Flush()方法刷新一下输出流,用来将输出流中的元素全部刷新,防止输出流中留有剩余没输出的元素,然后在关闭。
字符流类间的继承关系
FileInputStream类
FileInputStream是抽象类InputStream的实现类
我们想要读取某个文件,就需要先创建一个“输入流”,在创建流的时候会有异常,我们可以进行try catch 捕获处理也可以throws抛出,建议捕获处理。
public static void main(String[] args) {
FileInputStream fis=null;//创建字节输入流,先赋给它空值
try {
//要读取某个文件,先与这个文件创建一个“输入流”
//文件路径,此处赋给的是绝对路径
String FilePath="D:\\idea\\java code\\src\\learn\\IO\\temp01";//相对路径,相对当前而言,在当前路径下找
fis=new FileInputStream(FilePath);//创建一个字节输入流对象,并将文件路径穿进去
//开始读,read()方法,一次只能读取一个字节,并且输出该字节的时候会转换成Ascll码值
int i1=fis.read();
int i2=fis.read();
int i3=fis.read();
int i4=fis.read();
int i5=fis.read();
int i6=fis.read();
//因为传入的文件中只有abcdef,所以在读到第7次的时候文件已经读完了
int i7=fis.read();
System.out.println(i1);//97 a
System.out.println(i2);//98 b
System.out.println(i3);//99 c
System.out.println(i4);//100 d
System.out.println(i5);//101 e
System.out.println(i6);//102 f
//如果已经读取到文件的末尾就会返回-1
System.out.println(i7);//-1
}catch (FileNotFoundException e){//处理文件找不到异常
e.printStackTrace();//打印异常名称,基本信息,异常位置
} catch (IOException e) {
e.printStackTrace();
} finally {
//为了保证流一定会释放,所以在finally语句块中执行
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我们可以使用循环读取文件,就可以不用使用单一的read()方法那么麻烦了
public static void main(String[] args) {
FileInputStream fis=null;
try {
//创建流
fis=new FileInputStream("D:\\idea\\java code\\src\\learn\\IO\\temp01");
//读取
/*
while (true){
int temp=fis.read();
if(temp==-1){
break;
}
System.out.println(temp);
}
*/
//升级循环
int temp=0;//定义一个判定变量
while ((temp=fis.read())!=-1){//当read()方法的返回值为-1时,就代表文件已经读取完了,我们让他退出循环即可,当返回值不是-1时,我们输出temp,也就是输出文件的内容
System.out.println(temp);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭流
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
很显然一次读取一字节太慢了,用的久就会伤害硬盘,所以我们可以使用字节数组来进行高效读取
/*
int read(byte[] byte)
读取之前在内存中准备一个byte数组,每次读取多个字节存储到byte数组中
一次读取多个字节,不是单字节读取。
该方法返回的int类型的值代表的是这次读取的多少个字节
效率高
*/
public class FileInputStreamTest03 {
public static void main(String[] args) {
//创建输入流
FileInputStream fis=null;
try {
//创建输入流
fis=new FileInputStream("D:\\idea\\java code\\src\\learn\\IO\\temp01");
//读取数据
//准备一个byte数组
byte[] bytes=new byte[3];//每次最多读取三个字节
int i=fis.read(bytes);//3
//将byte数组转换成字符串,构造方法,多次的读取,后面读取会将之前读取的字节覆盖
System.out.println(new String(bytes));//abc
int i1=fis.read(bytes);//3
System.out.println(new String(bytes));//def
int i2=fis.read(bytes);//1
System.out.println(new String(bytes));//gef,ef已经被读取了。
System.out.println(new String(bytes,0,i2));//g String类的构造方法,可将byte数组的一部分转换成String类型
int i3=fis.read(bytes);//-1 已经到达文件的末尾返回-1
System.out.println(new String(bytes));//gef
System.out.println(i);
System.out.println(i1);
System.out.println(i2);
System.out.println(i3);
/*
//将while循环升级,用循环可以减少代码,高效的读取
int temp=0;
while (((temp=fis.read(bytes))!=-1)){
System.out.println(new String(bytes,0,temp));
}
*/
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//关闭输入流
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
FileInputStream类的其他方法
public static void main(String[] args) throws Exception {
//创建流
FileInputStream fis=new FileInputStream("D:\\idea\\java code\\src\\learn\\IO\\temp01");
//available()方法返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。可用来估计文件大概有多少字节
System.out.println(fis.available());//7
System.out.println(fis.read());//97
System.out.println(fis.available());//6
//将指针跳过两个字节
fis.skip(2);
System.out.println(fis.read());//100,因为跳过了98,99
//关闭
fis.close();
}
FileOutputStream类
FileOutputStream类是抽象类OutputStream的子类,用来创建一个字节输出流。
我们要将数据写入一个文件,就需要使用输出流来写入。
有一点需要注意的是,使用输出流写入文件时,如果该文件路径不存在,会自动创建文件,如果该文件存在且原文件中有数据的话,那么写入的时候就要使用追加的方式写入,不然会覆盖掉原文件的数据。
public static void main(String[] args) {
FileOutputStream fis=null;
try {
//1、创建文件字节输出流
//谨慎使用
// fis=new FileOutputStream("D:\\idea\\java code\\src\\learn\\IO\\temp02");//该文件不存在会自动创建
//以追加的方式写入文件(不会覆盖掉原文件内容)
fis=new FileOutputStream("D:\\idea\\java code\\src\\learn\\IO\\temp02",true);//append:true表示追加,false表示不追加
//2、开始写
String msg="HelloWorld";
byte[] bytes=msg.getBytes();
//将byte数组的所有数据全部写入
fis.write(bytes);
//将byte数组中的一部分数据写入
fis.write(bytes,0,3);
//推荐最后的时候为了保证数据完全写入硬盘,所以要刷新
fis.flush();//强制写入
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
} finally {
//关闭输出流
try {
if(fis!=null){
fis.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
使用输入输出流复制文件
public static void main(String[] args) {
//创建输入流
FileInputStream fis=null;
try {
fis=new FileInputStream("D:\\idea\\java code\\src\\learn\\IO\\temp01");
}catch (FileNotFoundException e){
e.printStackTrace();
}
//创建输出流
FileOutputStream fos=null;
try {
fos=new FileOutputStream("D:\\idea\\java code\\src\\learn\\IO\\temp02");
}catch (FileNotFoundException e){
e.printStackTrace();
}
//一边读,一边写
byte[] bytes=new byte[1024];//每次读写1KB
try {
int temp=0;
while ((temp=fis.read(bytes))!=-1){
fos.write(bytes,0,temp);
}
}catch (IOException e){
e.printStackTrace();
}
}
FlieReader类
FileReader类用来创建字符输入流,字符输入流只能读取纯文本文件。
public static void main(String[] args) {
FileReader fr=null;
try {
//创建文件字符流
fr=new FileReader("D:\\idea\\java code\\src\\learn\\IO\\temp01");
char[] chars=new char[512];//1KB
int temp=0;
while ((temp=fr.read(chars))!=-1){
//将char数组有效部分转换为字符串输出
System.out.println(new String(chars,0,temp));
}
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
} finally {
if(fr!=null);{
try {
fr.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
FileWriter类
FileWriter类用来创建字符输出流
public static void main(String[] args) throws Exception {
//创建文件字符输出流
//FileWriter fw=new FileWriter("D:\\idea\\java code\\src\\learn\\IO\\temp01");//覆盖文件
FileWriter fw1=new FileWriter("D:\\idea\\java code\\src\\learn\\IO\\temp01",true);//以追加的方式添加文件
FileReader fr=new FileReader("D:\\idea\\java code\\src\\learn\\IO\\temp02");
//一边读,一边写,只能复制纯文本文件
char[] c=new char[512];
int temp=0;
//读
if ((temp=fr.read(c))!=-1){
//写
fw1.write(c,0,temp);
}
/*
fw1.write("李海波!!!");
//将char数组的一部分写入
char[] chars={'我','是','中','国','人','!',',','.',};
fw1.write(chars,0,6);
*/
//刷新
fw1.flush();
//关闭
fw1.close();
fr.close();
}