JAVA io 详细介绍 目录一、什么是IO?1.1 IO的介绍1.2 流的介绍1.2.1 流的特征1.2.2 数据流的特征1.2.3 输入流的特征1.2.4 输出流的特征 二、
IO是指对数据流的输入和输出,也称为IO流。Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。
IO流的好处是简单易用,缺点是效率较低。
数据流是一组有序,有起点和终点的字节的数据序列(如图),它包括输入流和输出流。
输入流是程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道。比较通俗的来讲就是外部的文件通过输入流,传入到咱们的程序当中,程序去读取输入流内容(如图)。
输出流是程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道。比较通俗的来讲就是程序中的内容通过输出流,输出给外部(如图)。
通过第一点描述得知,其实Java的IO类库总体来说其实并不复杂。从是读写的的维度看,Java IO可以分为
从其处理流的类型的维度上看,Java IO又可以分为:
下面这幅图就清晰的描述了JavaiO的分类:
字节流 | 字符流 | |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
上面我们介绍了Java IO中的四各类:InputStream、OutputStream、Reader、Writer,其实在我们的实际应用中,我们用到的一般是它们的子类,之所以设计这么多子类,目的就是让每一个类都负责不同的功能,以方便我们开发各种应用。各类用途汇总如下:
下面按I/O类型来总体分类:
下面就以这张图来大体了解一下这些类的继承关系
InputStream 为字节输入流,它本身为一个抽象类,必须依靠其子类实现各种功能。继承自InputStream 的流都是向程序中输入数据的,且数据单位为字节(8bit),InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法.以下是Inputstream类中的常用方法:
主要的子类:
OutputStream提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。
主要的子类:
FileInputStream可以使用read()方法一次读入一个字节,并以int类型返回,或者是使用read()方法时读入至一个byte数组,byte数组的元素有多少个,就读入多少个字节。在将整个文件读取完成或写入完毕的过程中,这么一个byte数组通常被当作缓冲区,因为这么一个byte数组通常扮演承接数据的中间角色。
例:用字节流去读文件
public static void main(String[] args) throws Exception { //在E盘中新建一个Test.txt文件,内容填入 “hello China!” File file = new File("E:\\Test.txt"); byte[] byteArray = new byte[(int) file.length()]; //因为媒介对象是文件,所以用到子类是FileInputStream InputStream is = new FileInputStream(file); int size = is.read(byteArray); System.out.println("大小:" + size + ";内容:" + new String(byteArray)); //输出为:大小:14;内容:hello China! is.close(); }
用来处理以文件作为数据输出目的数据流;或者说是从内存区读数据入文件
例:用字节流去写文件
public static void main(String[] args) throws Exception { String hello = "hello China!"; byte[] byteArray = hello.getBytes(); File file = new File("E:/Test.txt"); //因为媒介对象是文件,所以用到子类是FileOutputStream OutputStream os = new FileOutputStream(file); os.write(byteArray); //执行后,观察E盘是否新建了一个Test.txt的文本文件,文件内容为"hello China!" os.close(); }
在第一大点有提到就是流它的读取效率是比较低的,原始的InputStream对数据读取的过程都是一个字节一个字节操作的,而BufferedInputStream在其内部提供了一个buffer,在读数据时,会一次读取一大块数据到buffer中,这样比单字节的操作效率要高的多,特别是进程磁盘IO和对大量数据进行读写的时候。所以BufferedInputStream顾名思义,就是在对流进行写入时提供一个buffer来提高IO效率。
BufferedInputStream: BufferedInputStream比FileInputStream多了一个缓冲区。它提供了一个缓冲数组,每次调用read方法的时候,它首先尝试从缓冲区里读取数据,若读取失败(缓冲区无可读数据),则选择从物理数据源(譬如文件)读取新数据(这里会尝试尽可能读取多的字节)放入到缓冲区中,最后再将缓冲区中的内容部分或全部返回给用户.由于从缓冲区里读取数据远比直接从物理数据源(譬如文件)读取速度快。BufferedInputStream的默认缓冲区大小是8192字节。当每次读取的数据量很小时,FileInputStream每次都是从硬盘读入,而BufferedInputStream大部分是从缓冲区读入。读取内存速度比读取硬盘速度快得多,因此BufferedInputStream效率高.
使用BufferedInputStream十分简单,只要把普通的输入流和BufferedInputStream组合到一起即可。我们把上面的例子改造成用BufferedInputStream进行读文件,请看下面例子:
public static void main(String[] args) throws Exception { //在E盘中新建一个Test.txt文件,内容填入 “hello China!” File file = new File("E:\\Test.txt"); byte[] byteArray = new byte[(int) file.length()]; //可以在构造参数中传入buffer大小 InputStream is = new BufferedInputStream( new FileInputStream(file),2*1024); int size = is.read(byteArray); System.out.println("大小:" + size + ";内容:" + new String(byteArray)); //输出为:大小:14;内容:hello China! is.close(); }
BufferedOutputStream进行写文件,同理,请看下面例子:
public static void main(String[] args) throws Exception { String hello = "hello China!"; byte[] byteArray = hello.getBytes(); File file = new File("E:/Test.txt"); //可以在构造参数中传入buffer大小 OutputStream os = new BufferedOutputStream(new FileOutputStream(file),2*1024); os.write(byteArray); //执行后,观察E盘是否新建了一个Test.txt的文本文件,文件内容为"hello China!" os.close(); }
备注:关于如何设置buffer的大小,我们应根据我们的硬件状况来确定。对于磁盘IO来说,如果硬盘每次读取4KB大小的文件块,那么我们最好设置成这个大小的整数倍。因为磁盘对于顺序读的效率是特别高的,所以如果buffer再设置的大写可能会带来更好的效率,比如设置成44KB或84KB。
还需要注意一点的就是磁盘本身就会有缓存,在这种情况下,BufferedInputStream会一次读取磁盘缓存大小的数据,而不是分多次的去读。所以要想得到一个最优的buffer值,我们必须得知道磁盘每次读的块大小和其缓存大小,然后根据多次试验的结果来得到最佳的buffer大小。
Reader是用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。
主要的子类:
例:用字符流去读文件
public static void main(String[] args) throws Exception{ //在E盘中新建一个Test.txt文件,内容填入 “hello China!” File file = new File("E:\\Test.txt"); //因为媒介对象是文件,所以用到子类是FileReader Reader reader= new FileReader(file); char [] byteArray= new char[(int) file.length()]; int size= reader.read( byteArray); System. out.println("大小:"+size +";内容:" +new String(byteArray)); //输出为:大小:14;内容:hello China! reader.close(); }
写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。
主要的子类:
例:用字符流去写文件
public static void main(String[] args) throws Exception{ String hello= new String("hello China!"); File file= new File("E:\\Test.txt"); //因为是用字符流来读媒介,所以对应的是Writer,又因为媒介对象是文件,所以用到子类是FileWriter Writer os= new FileWriter(file); os.write(hello); //执行后,观察E盘是否新建了一个Test.txt的文本文件,文件内容为"hello China!" os.close(); }
BufferedReader、BufferedWriter 的作用基本和BufferedInputStream、BufferedOutputStream一致,具体用法和原理都差不多 ,只不过一个是面向字符流一个是面向字节流。同样,我们将改造字符流中的例4,给其加上buffer功能,例:
public static void main(String[] args) throws Exception{ String hello= new String( "hello China!"); File file= new File( "E:\\Test.txt"); //因为是用字符流来读媒介,所以对应的是Writer,又因为媒介对象是文件,所以用到子类是FileWriter Writer os= new BufferedWriter(new FileWriter(file)); os.write( hello); //执行后,观察E盘是否新建了一个Test.txt的文本文件,文件内容为"hello China!" os.close(); }
想要选择用哪种IO流,首先,肯定是要先区分字节流与字符流之间的差异,以下是我总结几点:
输入:InputStream、Reader
输出:OutputStream、Writer
纯文本:Reader,Writer
非纯文本:InputStream,OutputStream
当我们新建一个java流对象之后,不仅在内存中创建了一个相应类的实例对象,而且还占用了相应的系统资源,比如:文件句柄、端口、网络连接等。在内存中的实例对象,当没有引用指向的时候,java垃圾收集器会按照相应的策略自动回收,但是却无法对系统资源进行释放。所以,我们需要主动调用close()方法释放java流对象。在java7之后,可以使用try-with-resources语句来释放java流对象,从而避免了try-catch-finally语句的繁琐,尤其是在finally子句中,close()方法也会抛出异常。
关闭流通用写法:
OutputStream out = null;try {out = new FileOutputStream("");// ...操作流代码} catch (Exception e) {e.printStackTrace();} finally {try {if (out != null) {out.close();}} catch (Exception e) {e.printStackTrace();}}
有些stream是不需要关闭的,比如ByteArrayOutputStream、ByteArrayIntputStream, StringWriter,点进ByteArrayOutputStream的close()方法发现,里面实现代码是空的,如图:
为什么会这样呢?因为ByteArrayOutputStream内部实现是一个byte[]数组,也就是基于内存的字节数据访问,并没有占有文件句柄、端口、网络连接,就算不关闭,用完之后垃圾回收器也会回收。即然是操作内存,就要考虑内存大小,如果字节流太大就要考虑内存溢出。
但是,我这边还是建议,只要是流,我们就给他关闭以下,反正不吃亏,万一那天记混了,线上环境报错吃亏的就是咱们了!
参考:
https://guisu.blog.csdn.net/article/details/7418161
Https://blog.csdn.net/suifeng3051/article/details/48344587
来源地址:https://blog.csdn.net/weixin_44273248/article/details/128374908
--结束END--
本文标题: 【JAVA IO 详细介绍】
本文链接: https://www.lsjlt.com/news/459497.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-04-03
2024-04-03
2024-04-01
2024-01-21
2024-01-21
2024-01-21
2024-01-21
2023-12-23
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0