Java之I/O流、字符流、字节流

本文详细介绍了Java中的I/O流,包括流的分类、常用流的类型及其用法,如字节流和字符流。通过FileInputStream、FileOutputStream、BufferedInputStream、BufferedReader等类展示了读写文件的实例。同时,提供了文件复制的综合案例,以及涉及字符编码的输出示例。

1.流(Stream)

我们可以把数据的读写操作抽象成数据在"管道"中流动,但需注意:
1.流只能单方向流动
2.输入流用来读取 → in
3.输出流用来写出 → out
4.数据只能从头到尾顺序的读写一次
所以以程序的角度来思考,In/out 相对于程序而言的输入(读取)/输出(写出)的过程

2.I/O流

2.1分类

  • 根据传输的方向进行分类,可以将流分为输入流和输出流。
  • 根据处理的数据单位不同,可以将流分为字节流和字符流。
  • 组合:字节输入流、字节输出流、字符输入流、字符输出流。

字节流:针对二进制文件,用来处理数据单位是二进制的文件。

字符流:针对文本文件,读写的时候容易出现乱码的现象,所以可以指定编码集为UTF-8。

2.2常用流

File
字节流:针对二进制文件
InputStream

  • FileInputStream
  • BufferedInputStream
  • ObjectInputStream

OutputStream

  • FileOutputStream
  • BufferedOutputStream
  • ObjectOutputStream

字符流:针对文本文件
Reader

  • FileReader
  • BufferedReader
  • InputStreamReader

Writer

  • FileWriter
  • BufferedWriter
  • OutputStreamWriter
  • PrintWriter一行行写出
     

3.File文件流

3.1创建文件对象

File(String pathname)通过将给定路径名字符串转换为抽象路径名来创建一个新的File实例
new File(“d:/abc/a.txt”);
new File(“d:/abc”,”a.txt”);pathname可以是文件路径、文件夹路径、不存在的路径

3.2常用方法

4.字节流读取

字节流是由字节组成的,字符流是由字符组成的。Java里字符由两个字节组成.字节流主要用在处理二进制数据。

4.1 InputStream抽象类

此抽象类是表示字节输入流的所有类的超类/抽象类,不可创建对象,需用其子类创建对象。读取结果为二进制形式。

常用方法:

  • abstract int read() 从输入流中读取数据的下一个字节
  • int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
  • int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组,off表示存时的偏移量
  • void close() 关闭此输入流并释放与该流关联的所有系统资源

4.2 FileInputStream子类

直接插在文件上,直接读取文件数据

创建对象

  • FileInputStream(File file)—直接传文件对象

通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定

  • FileInputStream(String pathname)—传路径

通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 pathname 指定

4.3 BufferedInputStream子类

BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组(默认8k大小)。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。

创建对象

  • BufferedInputStream(InputStream in)

创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

4.4 字节流读取案例

public class TestIn {
    public static void main(String[] args) {
//        method();
        method2();
    }
    public static void method() {//测试FileInputStream
        InputStream in = null;
        try {
            in = new FileInputStream("e:/test/t.txt");
            int content = 0;
            while ((content=in.read())!=-1){
                System.out.println(content);//输出读取的文件内容
            }
        }
        catch (IOException e){
            e.printStackTrace();
        }
        finally {//用于必须要执行的任务,比如打开资源后必须要关闭资源
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void method2(){//测试BufferedInputStream
        InputStream in = null;
        try{
            in = new BufferedInputStream(new FileInputStream("e:/test/t.txt"));
            int con;
//            byte[] b = new byte[9];
//            System.out.println(in.read(b,1,8));//从文件中读取长度为len的字符,数组b从off位置开始接收
//            System.out.println(Arrays.toString(b));
            while ((con = in.read())!=-1){
                System.out.println(con);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
        finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

5 字符流读取

常用于处理纯文本数据

5.1 Reader抽象类

用于读取字符流的抽象类。读取结果为字符形式。

  • 常用方法:
  • int read() 读取单个字符
  • int read(char[] cbuf) 将字符读入数组
  • abstract int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分
  • int read(CharBuffer target) 试图将字符读入指定的字符缓冲区
  • abstract void close() 关闭该流并释放与之关联的所有资源

5.2 FileReader子类

用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。

创建对象

  • FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader
  • FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader

5.3 BufferedReader子类

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

创建对象

  • BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流

 5.4字符流读取案例

public class TestIn2 {
    public static void main(String[] args) {
        method();
        System.out.println();
        method2();
    }
    public static void method(){
        Reader in = null;
        try{
            in = new FileReader("e:/test/t.txt");
            int con = 0;
            while((con = in.read()) != -1){
                System.out.print((char) con);
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void method2(){
        Reader in = null;
        try{
            in = new BufferedReader(new FileReader("e:/test/t.txt"));
            int con = 0;
            while((con = in.read())!=-1){
                System.out.print((char) con);
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                in.close();
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }
}

6 字节流写出

6.1 OutputStream抽象类

此抽象类是表示输出字节流的所有类的超类.输出流接受输出字节并将这些字节发送到某个接收器.

常用方法:

  • Void close() 关闭此输出流并释放与此流相关的所有系统资源
  • Void flush() 刷新此输出流并强制写出所有缓冲的输出字节
  • Void write(byte[ ] b) 将b.length个字节从指定的byte数组写入此输出流
  • Void write(byte[ ] b,int off ,int len) 将指定byte数组中从偏移量off开始的len个字节写入输出流
  • Abstract void write(int b) 将指定的字节写入此输出流

6.2 FileOutputStream 子类

直接插在文件上,直接写出文件数据

构造方法(创建对象):

  • FileOutputStream(String name)
  • 创建一个向具有指定名称的文件中写入数据的文件输出流
  • FileOutStream(File file)
  • 创建一个向指定File对象表示的文件中写入数据的文件输出流
  • FileOutStream(File file,boolean append)—如果第二个参数为true,表示追加,不覆盖
  • 创建一个向指定File对象表示的文件中写入数据的文件输出流,后面的参数是指是否覆盖原文件内容

6.3 BufferedOutputstream 子类

该类实现缓冲的输出流,通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必每次针对字节写出调用底层系统

构造方法(创建对象):

  • BufferedOutputStream(OutputStream out)
  • 创建一个新的缓冲输出流,用以将数据写入指定的底层输出流

6.4 字节输出流测试

public class TestOut {
    public static void main(String[] args) {
//        method();
        method2();
    }
    public static void method(){
        OutputStream out = null;
        try{
            out = new FileOutputStream("e:/test/out.txt");
            byte[] b = {97,98,99};
            out.write(100);
            out.write(b);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void method2(){
        OutputStream out = null;
        try{
            out = new BufferedOutputStream(
new FileOutputStream(
new File("e:/test/out.txt"),true));//true表示追加写入,不是覆盖写入,不写true就是默认覆盖写入
            byte b[] = {97,98,99,100,101};
            out.write(b);
            out.write(100);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

7.字符流写出

7.1 Writer 抽象类

写入字符流的抽象类

常用方法:

  • Abstract void close() 关闭此流,但要先刷新它
  • Void write(char[ ] cbuf) 写入字符数组
  • Void write(int c) 写入单个字符
  • Void write(String str) 写入字符串
  • Void write(String str,int off,int len) 写入字符串的某一部分
  • Abstract void write(char[] cbuf,int off,int len)写入字符数组的某一部分

7.2 FileWriter 子类

用来写入字符文件的便捷类,此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的.如果需要自己自定义这些值,可以先在FileOutputStream上构造一个OutputStreamWriter.

构造方法(创建对象):

  • FileWriter(String filename)
  • 根据给定的文件名构造一个FileWriter对象
  • FileWriter(String filename,boolean append)
  • 根据给定的文件名以及指示是否附加写入数据的boolean值来构造FileWriter

7.3 BufferedWriter子类

将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组和字符串的高效写入.可以指定缓冲区的大小,或者接受默认的大小,在大多数情况下,默认值就足够大了

构造方法(创建对象):

  • BufferedWriter(Writer out)
  • 创建一个使用默认大小输出缓冲区的缓冲字符输出流

7.4 字符输出流测试

public class TestOut2 {
    public static void main(String[] args) {
        method();
        method2();
    }
    public static void method(){
        Writer out = null;
        try{
            out = new FileWriter("e:/test/out.txt");
            out.write(97);
            char[] b = {97,98,99,100};
            out.write(b);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void method2(){
        Writer out = null;
        try{
            out = new BufferedWriter(new FileWriter(new File("e:/test/out.txt"),true));
            char[] b = {65,66,67,68,69,70};
            out.write(b);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 8.综合案例---文件的复制

public class TestCopyFile {
    public static void main(String[] args) {
        System.out.print("请输入源文件路径:");
        String originFile = new Scanner(System.in).nextLine();
        System.out.print("请输入目标文件路径:");
        String aimFile = new Scanner(System.in).nextLine();
        System.out.println(aimFile);
        File ogF = new File(originFile);
        File aF = new File(aimFile);
        if (aF.exists()){
            System.out.println("目标文件存在");
        }else {
            System.out.println("目标文件不存在");
        }
        ZFCopy(ogF,aF);
    }
    private static void ZFCopy(File a ,File b){
//        Reader in = null;//负责数据读取
//        Writer out = null;//负责数据写出
        InputStream in = null;
        OutputStream out = null;
        try{
//            in = new BufferedReader(new FileReader(a));//读取流
//            out = new BufferedWriter(new FileWriter(b,true));//写出流,追加写出,不用覆盖
            in = new BufferedInputStream(new FileInputStream(a));
            out = new BufferedOutputStream(new FileOutputStream(b));
            int con;
            while ((con = in.read()) != -1){
                out.write(con);
            }
            System.out.println("复制成功!");
        }catch (IOException e){
            System.out.println("复制失败!");
            e.printStackTrace();
        }finally {
            try{
                out.close();//先创建的后关闭,多个关闭多个try
            }catch (IOException e){
                e.printStackTrace();
            }  try{
                in.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

换行输出

import java.io.*;
public class EncodingSet {
    public static void main(String[] args) {
        char c = 10;
        System.out.println(c);
    method();
    method2();//会打印出13和10,是换行符?
    }
    private static void method() {
//        File f1 = new File("e:/test/t.txt");
//        FileOutputStream f2 = new FileOutputStream(f1);//捕获异常
//        OutputStreamWriter f3 = new OutputStreamWriter(f2);
//        PrintWriter out = new PrintWriter(f3); //这几行与下面的一行等价
        PrintWriter out = null;
        try{
            out = new PrintWriter(new OutputStreamWriter(new FileOutputStream("e:/test/t.txt"),"UTF-8"));
            out.println("helloworld世界你好");//换行写出数据
            out.println("wofcbh我非常不好");
            System.out.println("成功");
        }catch (Exception e){
            System.out.println("失败");
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private static void method2(){
        InputStreamReader in = null;
        try{
            in = new InputStreamReader(new FileInputStream("e:/test/t.txt"),"UTF-8");
            int con ;
            while ((con = in.read()) != -1){
                System.out.println(con);
            }
            if(con == -1){
                System.out.println("输出成功");
            }
        }catch (Exception e){
            System.out.println("输出失败");
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}


————————————————
版权声明:本文为优快云博主「程序媛 泡泡」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/weixin_43884234/article/details/116952152

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值