IO流的学习

本文详细介绍了Java中FileWriter和FileReader的使用,包括如何写入和读取文件,以及如何实现文件的拷贝。同时,讲解了字节流和字符流的区别,并展示了如何利用缓冲流提高文件拷贝的效率。最后,通过实例展示了PrintStream和BufferedReader在模拟聊天功能中的应用。
摘要由CSDN通过智能技术生成

基本知识

在这里插入图片描述

在这里插入图片描述
主要用的是这些
在这里插入图片描述

各流详解

FileWriter

将文本内容写入文本文件中
在这里插入图片描述

write写入单个字符

示例如下:
若d:/a.txt不存在,FileWriter会自动创建一个新文件
若d:/a.txt存在,FileWriter会清空文件中的原有内容

public class FileWriterTest {

    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            //1.构造FileWriter类型的对象并与d:/a.txt相关联
            fw = new FileWriter("d:/a.txt");
            //2.通过流对象写入数据内容
            fw.write('a');
            System.out.println("写入数据成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流对象并释放有关资源
            if(null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

若想以追加的方式创建对象去关联文件

fw = new FileWriter("d:/a.txt");

改为

fw = new FileWriter("d:/a.txt",true);

就可以在原内容上追加内容,文件不存在也会创建新文件
在这里插入图片描述

写入多个字符
void write(char[] cbuf,int off,int len)

将指定字符数组从偏移量off开始的len个字符写入此文件输出流

public class FileWriterTest {

    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            //1.构造FileWriter类型的对象并与d:/a.txt相关联
            fw = new FileWriter("d:/a.txt");
            //2.通过流对象写入数据内容
            fw.write('a');


            //准备一个字符数组
            char[] cArr = new char[]{'A','B','C','D'};
            //将字符数组的一部分写进去
            fw.write(cArr,1,2);//BC
            //将整个字符数组写进去
            fw.write(cArr);//ABCD

            System.out.println("写入数据成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流对象并释放有关资源
            if(null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

结果如下
在这里插入图片描述
则每当写入一个字符后,文件中的读写位置自动后退一位
上面代码整个流程是fw = new FileWriter(“d:/a.txt”);创建连接后不断写入,直到close

FileReader

从文本文件中读取内容

public class FileReaderTest {
    public static void main(String[] args) {
        FileReader fr = null;

        try {
            //1.构造FileReader类型的对象与d:/a.txt文件连接
            fr = new FileReader("d:/a.txt");
            //2.读取数据内容并打印
            int fe = fr.read();
            System.out.println("读取的单个字符是"+(char)fe);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭流对象并释放资源
            if(null!=fr){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

在这里插入图片描述

FileReader中其他方法的使用
public class FileReaderTest {
    public static void main(String[] args) {
        FileReader fr = null;

        try {
            //准备一个字符数组来保存读到的字符
            fr = new FileReader("d:/a.txt");
            char[] cArr = new char[5];
            //期望读取字符数组中的一部分空间,也就是读取3个字符放入数组cArr中下标从1开始的位置上
            int res = fr.read(cArr,1,3);//所以cArr下标为0的地方空着
            System.out.println("实际读取到的字符个数是"+res);
            for(char cv:cArr){
                System.out.println("实际读取到的字符是"+(char)cv);
            }
            System.out.println("-----------------------------------");
            
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭流对象并释放资源
            if(null!=fr){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

在这里插入图片描述

文件字符流实现文件的拷贝

public class FileCharCopyTest {
    public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            //1.创建FileReader类型的对象与d:/a.txt关联
            fr = null;
            fr = new FileReader("d:/a.txt");
            //2.创建FileWriter类型的对象与d:/b.txt关联
            fw = null;
            fw = new FileWriter("d:/b.txt");
            //3.不断的从输入流中读取数据内容并写入输出流中
            System.out.println("开始拷贝!");
            int res = 0;
            while((res=fr.read())!=-1){
                fw.write(res);
            }
            System.out.println("拷贝成功!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流对象并释放资源
            try {
                if(null != fw) {
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(null!=fr) {
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

字节流

用于拷贝任意文件,如图片等

FileOutputStream&FileInputStream

在这里插入图片描述
在这里插入图片描述

实现图片的拷贝
public class PictureCpoyTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //1.创建FileInputStream类型的对象与d:/要复制的图片.png关联
            fis = null;
            fis = new FileInputStream("d:/要复制的图片.png");
            //2.创建FileOutputStream类型的对象与d:/复制成功的图片.png关联
            fos = null;
            fos = new FileOutputStream("d:/复制成功的图片.png");
            //3.不断的从输入流中读取数据内容并写入输出流中
            System.out.println("开始拷贝图片!");
            int res = 0;
            while((res = fis.read()) !=-1){
                fos.write(res);
            }
            System.out.println("拷贝图片完成!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流对象并释放资源
            try {
                if(null!=fos) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(null!=fis) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
拷贝视频文件
  • 方式一:如拷贝图片一样,按单个字节为单位来拷贝,每次读取一个字节写入一个字节。但这样文件大时拷贝效率低
  • 方式二:准备一个和文件大小一样的缓冲区,一次性将文件中所有内容取到缓冲区中然后一次性写进去
public class Mp4CopyTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {

            fis = null;
            fis = new FileInputStream("d:/要复制的视频.mp4");

            fos = null;
            fos = new FileOutputStream("d:/复制成功的视频.mp4");

            System.out.println("开始拷贝视频!");
            int len = fis.available();
            System.out.println("获取到的文件大小是:"+len);

            byte[] bArr = new byte[len];
            int res = fis.read(bArr);
            System.out.println("读取到的文件大小是:"+res);
            fos.write(bArr);

            System.out.println("拷贝视频完成!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null!=fos) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(null!=fis) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

方式二明显在效率上比方式一快很多
缺点:若文件过大时,无法申请和文件大小一样的缓冲区,因为真实内存不足

  • 方式三(推荐使用)
    准备一个相对适当的缓冲区,分多次将文件拷贝完成
public class RealMeathodCopyTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {

            fis = null;
            fis = new FileInputStream("d:/要复制的视频.mp4");

            fos = null;
            fos = new FileOutputStream("d:/复制成功的视频.mp4");

            System.out.println("开始拷贝视频!");

            byte[] bArr = new byte[1024];
            int res = 0;
            while((res = fis.read(bArr))!=-1){
                fos.write(bArr,0,res);
            }

            System.out.println("拷贝视频完成!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null!=fos) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(null!=fis) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

缓冲字节流

BufferedInputStream

java.io.BufferedInputStream类主要用于描述缓冲输入流

在这里插入图片描述

BufferedOutputStream

java.io.BufferedOutputStream类主要用于描述缓冲输出流,此时不用为写入的每个字节调用底层系统
在这里插入图片描述
在这里插入图片描述
BufferedInputStream自身会给给一个1024×8=8192的缓冲区

public class BufferedCopyTest {
    public static void main(String[] args) {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1.创建BufferedInputStream类型的对象与d:/要复制的视频.mp4关联
            bis = null;
            bis = new BufferedInputStream(new FileInputStream("d:/要复制的视频.mp4"));
            //2.创建BufferedOutputStream类型的对象与d:/复制成功的视频.mp4关联
            bos = null;
            bos = new BufferedOutputStream(new FileOutputStream("d:/复制成功的视频.mp4"));
            //3.不断的从输入流中读取数据并写入输出流中
            System.out.println("开始拷贝视频!");

            byte[] bArr = new byte[1024];
            int res = 0;
            while((res = bis.read(bArr))!=-1){
                bos.write(bArr,0,res);
            }

            System.out.println("拷贝视频完成!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流并释放有关资源
            if(null!=bos) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null!=bis) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

这段代码在copy中进一步再给一个1024的缓冲区
不给缓冲区的话中间那段就是这样的

System.out.println("开始拷贝视频!");
            int len = bis.available();
            byte[] bArr = new byte[len];
            //byte[] bArr = new byte[1024];
            int res = 0;
            while((res = bis.read(bArr))!=-1){
                bos.write(bArr,0,res);
            }

            System.out.println("拷贝视频完成!");

在以后开发中涉及到文件的拷贝使用缓冲流较好,效率高

缓冲字符流

字符流只能与文本文件关联
在这里插入图片描述

BufferedWriter类

java.io.BufferedWriter类主要用于写入单个字符、字符数组以及字符串到输出流中
在这里插入图片描述

BufferedReader类

在这里插入图片描述
行分隔符就是换行

缓冲字符流实现文件的拷贝
public class BufferedCharCopyTest {
    public static void main(String[] args) {
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            //1.创建BufferedReader类型的对象与d:/a.txt关联
            br = null;
            br = new BufferedReader(new FileReader("d:/a.txt"));
            //2.创建BufferedWriter类型的对象与d:/b.txt关联
            bw = null;
            bw = new BufferedWriter(new FileWriter("d:/b.txt"));
            //3.不断的从输入流中读取数据并写入输出流中
            System.out.println("开始拷贝视频!");
            String str = null;
            while((str = br.readLine()) !=null){
                bw.write(str);
                bw.newLine();//行分隔符
            }
            System.out.println("拷贝视频完成!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流并释放有关资源
            if(null!=bw) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null!=br){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

打印流和转换流模拟聊天的功能实现

PrintStream类

java.io.PrintStream类主要用于更加方便地打印各种数据内容。
在这里插入图片描述

PrintWriter类

java.io.PrintWriter类主要用于将对象的格式化形式打印到文本输出流。

在这里插入图片描述

案例题目

不断地提示用户输入要发送的内容,若发送的内容是"bye"则聊天结束,否则将用户输入的内容写
入到文件d:/a.txt中。
要求使用BufferedReader类来读取键盘的输入 System.in代表键盘输入
要求使用PrintStream类负责将数据写入文件

public class PrintStreamChatTest {
    public static void main(String[] args) {
        BufferedReader br = null;
        PrintStream ps = null;
        try {
            br = new BufferedReader(new InputStreamReader(System.in));
            ps = new PrintStream(new FileOutputStream("d:/a.txt"));
            while(true) {
                //1.提示用户输入要发送的聊天内容并使用变量来记录
                System.out.println("请输入聊天内容");
                //BufferedReader的构造方法需要的是Reader类型的引用,但Reader是抽象类,实参只能传递子类的对象 字符流
                //System.in是键盘输入,且是InputStream类型的 字节流

                String str = br.readLine();
                //2判断用户输入的内容是否为"bye",若是则结束
                if ("bye".equals(str)) {
                    System.out.println("聊天结束!");
                    break;
                }
                //3.若不是则将用户输入的内容写入d:/a.txt中
                else {

                    ps.println(str);

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流对象并释放有关资源
            if(null!=ps) {
                ps.close();
            }
            try {
                if(null!=br) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

优化一下


上面要用到 InputStreamReader类
java.io.InputStreamReader类主要用于实现从字节流到字符流的转换
在这里插入图片描述
顺便提到 OutputStreamWriter类
java.io.OutputStreamWriter类主要用于实现从字符流到字节流的转换
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值