I/O系统

本文深入探讨Java中I/O操作的流机制,包括字节流与字符流的使用,详细介绍了InputStream、OutputStream、Reader、Writer等核心类及其方法,如read、read(byte[])、read(byte[],int,int)等,同时强调了错误处理、内存管理及流的关闭策略。文章还阐述了缓冲流、转换流、数据流的概念与用途,以及如何避免数据错乱和内存泄漏。通过实例展示了流在文件读写、字符串处理等场景的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Java程序中,对于数据的输入/输出操作以"流" stream 的方式进行,stream的意思其实就是一个管道,连接数据和数据要到达的地方。需要声明的是,在这里所谓的输入和输出都是针对程序而言的。比如说一个程序从一个文件读数据,这叫输入。将程序中的计算结果传递给文件,叫做输出。

I/O的操作几乎都会涉及到异常,所以要搞清楚相关异常的分类,大小,便于捕捉和调试。

java提供的所有流的类型都位于包java.io内,分别继承以下四种抽象流类型:

字节流:InputStream, OutputStream,一个字节一个字节读(8-bit)
字符流:Reader, Writer,一个字符(2个字节)一个字符读(1-bit)

1.InputStream---抽象类,字节输入流的所有类的超类
主要方法:
1) public abstract int read() throws IOException
从输入流中读取数据的下一个字节,返回0到255范围内的int字节值,以前这里没有太看懂,其实读取的是字节,也就是一个英文字母,但是最后要以Asic II码把它转换为int类型的数值返回。如果想要显示的话,那么就强制类型转换为char类型。
声明一下:换行符(\n)的码字为10
如果因为已经到达流末尾而没有可用的字节,则返回值为 -1(至于这个是怎么实现的,我还没有搞清楚)。子类必须提供此方法的一个实现。
返回值:下一个数据字节,即0到255的一个int值,如果已经到达流的末尾,则返回-1。当然,大部分情况下应该不会需要自己去实现,那么多已经实现的类,肯定有可以用到的。

2)public int read (byte[] b) throws IOException
从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。以整数的形式返回实际读取的字节数。如果因为流位于文件末尾而没有可用的字节,则返回值-1。
将读取的第一个字节存储在元素b[0]中,下一个存储在b[1]中,依次类推。读取的字节数最多等于b的长度。
// 需要注意的是有些异常,记得使用try catch 形式

为了避免内存泄漏,比如读到一半出错了,然后stream就一直开着,占用系统资源,无论如何都要在最后保证打开的streams被关闭掉。通常的做法就是在最后写一个finally块,判定stream对象是否不为null,如果是,那么调用其close方法。

3) public int read (byte[] b, int off, int len) throws IOException
将输入流中len个数据字节读入byte数组(实际读取的字节数可能小于该值)
将读取的第一个字节存储在元素b[off]中,下一个存储在b[off+1]中,依次类推。读取的字节数最多等于len。
其它的OutputStream,Reader, Writer都很类似,只不过可能有一些特殊的方法可以用,具体用的时候查看API就行。

2. OutputStream---抽象类,字节输出流的所有类的超类
其实读和写的操作基本上都是相互对应的。

需要注意的一点就是,有些共同使用的文件或者数据,需要在读或者写的时候进行同步,以免发生数据的错乱。

3. Reader
其实最常用的就是BufferReader,因为它有个方法叫做readLine(),直接读取一行,非常方便。

4. Writer
其中有一个write(String string)方法很有用,其实是调用了String类里面的toCharArray()方法将他们都转换成字符然后再写出去。

5.转换流,缓冲流,数据流
不想说太多细节的东西,前面4个抽象类的东西都很基础,比如说一个字节一个字节地读写,一个字符一个字符地读写。但是到了实际情况的时候就不一样了,这些方法可能并不方便。

1).首先这样读的话硬盘读写次数太多,损伤很大。所以呢,就出现了缓冲流,你可以先写到一个buffer里面,然后再读写,岂不是减少了硬盘的实际读写次数。这样就相当于一根管道插在文件上,然后再在这个管道外面包了一个更大的管道(或者说桶),等桶装满了再往外写。

2).第二个问题就是你本来定义了一个InputStream类型的对象,但是你发现你想一行一行的读,于是转换流的概念就出来了,你可以用转换流将其转换为Writer,它里面的一些方法就可以拿来用

3).第三个问题就是,读写字符串没问题,但是如果想读写原生数据的话怎么办呢,不可能一个个的先转换成字符再读写,太浪费空间而且效率很低,怎么解决呢,数据流的概念又出来了。无非就是在基础流对象的外面接一根数据流的管子,用它的方法读写就好。

4).关于编码问题

首先我前一段时间遇到的一个问题就是,我想传输图片,却使用了BufferedReader的readline方法,导致了编码不正确,图片读不出来。
其实问题不仅仅是readline方法,而是字符流和字节流的选择,对于图片来说,必须保证每一个字节都能正确地得到解析。如果用字符流,有可能按照转义字符给解析了,导致读不出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值