Java的IO流处理——简单总结知识点

前言

因为底层设备永远只接受字节数据,所以在数据传输的时候,都要把字符串或文件等数据转成二进制数据逐一输出到某个设备中,不管输入输出设备是什么,统一抽象成相同方式,这个方式起名为IO流,对应的抽象类为InputStream/OutputStream,不同实现类代表不同的输入和输出设备,它们都是针对字节进行操作的。

对于字符流:字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再写入底层设备,这为我们向IO设别写入或读取字符串提供了一点点方便。

  • 字节流继承inputStreamOutputStream
  • 字符流继承自ReaderWriter

InputStream提供的是字节流的读取,而非文本读取,这是和Reader类的根本区别。
即用Reader读取出来的是char数组或者String ,使用InputStream读取出来的是byte数组

io类

InputStream子类

  • ByteArrayInputStream:字节数组输入流,该类的功能就是从字节数组 byte[] 中进行以字节为单位的读取,也就是将资源文件都以字节形式存入到该类中的字节数组中去,我们拿数据也是从这个字节数组中拿。
  • PipedInputStream:管道字节输入流,它和 PipedOutputStream 一起使用,能实现多线程间的管道通信。
  • FilterInputStream:装饰者模式中充当装饰者的角色,具体的装饰者都要继承它,所以在该类的子类下都是用来装饰别的流的,也就是处理类。
  • BufferedInputStream:缓冲流,对处理流进行装饰、增强,内部会有一个缓冲区,用来存放字节,每次都是将缓冲区存满然后发送,而不是一个字节或两个字节这样发送,效率更高。
  • DataInputStream:数据输入流,用来装饰其他输入流,它允许通过数据流来读写Java基本类型。
  • FileInputStream:文件输入流,通常用于对文件进行读取操作。
  • File:对指定目录的文件进行操作。
  • ObjectInputStream:对象输入流,用来提供对“基本数据或对象”的持久存储。通俗点讲,就是能直接传输Java对象(序列化、反序列化用)。

一、举栗子

1. 字节流InputStream读取文件内容

    public static void readFileByInputStream(String fileName) {
        File file = new File(fileName);
        InputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[1024];
            // 每次读取到的字节数组的长度
            int bytesRead = 0;
            //从文件中按字节读取内容,到文件尾部时read方法将返回-1
            while ((bytesRead = in.read(buffer)) != -1) {
                String chunk = new String(buffer, 0, bytesRead);
                System.out.print(chunk);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                }
            }
        }
    }

2. 字节流OutputStream写入文件

    public static void writeFileByOutputStream(String fileName) {
        File file = new File(fileName);
        OutputStream os = null;
        try {
            // 加上BufferedInputStream是增强流,可以提高输出效率,也可以直接用FileOutputStream
            // FileOutputStream构造函数的第二个参数代表是否覆盖原有内容
            os = new BufferedOutputStream(new FileOutputStream(file, true));
            byte[] data = "append String by java program......".getBytes();
            os.write(data, 0, data.length);
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                }
            }
        }
    }

3. 字符流Reader读取文件内容

    public static void readFileByReader(String fileName) {
        File file = new File(fileName);
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            int line = 1;
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                // 显示行号
                System.out.println("line " + line + ": " + tempString);
                line++;
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
    }

4. 字符流Writer写入文件

    public static void writeFileByWriter(String fileName) {
        File file = new File(fileName);
        PrintWriter printWriter = null;
        try {
        	// FileWriter构造函数的第二个参数代表是否覆盖原有内容
            printWriter = new PrintWriter(new FileWriter(file, true), true);
            printWriter.println("testing Write to file......");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (printWriter != null) {
                printWriter.close();
            }
        }
    }

二、知识点复盘

阻塞方法

java中的阻塞式方法是指在程序调用改方法时,必须等待输入数据可用或者检测到输入结束或者抛出异常,否则程序会一直停留在该语句上,不会执行下面的语句。比如read()和readLine()方法。

InputStream方法解析

  • int read():从输入流中读取一个字节的二进制数据。

  • int read(byte[] b):将多个字节读到数组中,填满整个数组。

  • int read(byte[] b, int off, int len):从输入流中读取长度为 len 的数据,从数组 b 中下标为 off 的位置开始放置读入的数据,读完返回读取的字节数。

  • void close():关闭数据流。

  • int available():返回目前可以从数据流中读取的字节数(但实际的读操作所读得的字节数可能大于该返回值)。

  • long skip(long l):跳过数据流中指定数量的字节不读取,返回值表示实际跳过的字节数。
    对数据流中字节的读取通常是按从头到尾顺序进行的,如果需要以反方向读取,则需要使用回推(Push Back)操作。在支持回推操作的数据流中经常用到如下几个方法:

  • boolean markSupported():用于测试数据流是否支持回推操作,当一个数据流支持 mark() 和 reset() 方法时,返回 true,否则返回 false。

  • void mark(int readlimit):用于标记数据流的当前位置,并划出一个缓冲区,其大小至少为指定参数的大小。

  • void reset():将输入流重新定位到对此流最后调用 mark() 方法时的位置。

缓冲流工作原理

  • BufferedInputStream继承FilterInputStream
  • BufferedOutputStream继承FilterOutputStream
  • BufferedReader继承Reader
  • BufferedWriter继承Writer

提供缓冲输入流功能。缓冲输入流相对于普通输入流的优势是,它提供了一个缓冲数组,每次调用read方法的时候,它首先尝试从缓冲区里读取数据,若读取失败(缓冲区无可读数据),则选择从文件读取数据并放入到缓冲区中,最后再将缓冲区中的内容部分或全部返回给用户。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节(造成线程阻塞),并转换为字符后返回,而这是极其低效的。

简单解析FileReader

FileReader继承了InputStreamReaderFileReader 初始化时内部维护一个 FileInputStream,几乎所有的字符流都离不开某个字节流实例。 FileInputStream对象中的成员StreamDecoder是一个解码器,用于将字节的各种操作转换成字符的相应操作。

FileReader构造器

    public FileReader(File file) throws FileNotFoundException {
        super(new FileInputStream(file));
    }

InputStreamReader构造器

	...
	private final StreamDecoder sd;
    public InputStreamReader(InputStream in) {
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
        } catch (UnsupportedEncodingException e) {
            // The default encoding should always be available
            throw new Error(e);
        }
    }

装饰者模式

BufferedInputStream/OutputStream 和 BufferedReader/Writer 提供缓冲功能,使用了装饰者模式,用于IO流类的增强。

适配器模式

InputStreamReaderInputStreamReader的适配器,是字节流通向字符流的桥梁,它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

    public static void inputStream2Reader(String fileName) {
        File file = new File(fileName);
        Reader reader = null;
        BufferedReader bfreader = null;
        try {
            reader = new InputStreamReader(new FileInputStream(file), "UTF-8");
            bfreader = new BufferedReader(reader);
            String line;
            while ((line = bfreader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
            if (bfreader != null) {
                try {
                    bfreader.close();
                } catch (IOException e1) {
                }
            }
        }
    }

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值