广告
返回顶部
首页 > 资讯 > 后端开发 > JAVA >【JAVA IO 详细介绍】
  • 665
分享到

【JAVA IO 详细介绍】

java 2023-10-26 11:10:50 665人浏览 八月长安
摘要

JAVA io 详细介绍 目录一、什么是IO?1.1 IO的介绍1.2 流的介绍1.2.1 流的特征1.2.2 数据流的特征1.2.3 输入流的特征1.2.4 输出流的特征 二、

JAVA io 详细介绍

目录

一、什么是IO?

1.1 IO的介绍

           IO是指对数据流的输入和输出,也称为IO流。Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。

1.2 流的介绍

1.2.1 流的特征

           IO流的好处是简单易用,缺点是效率较低。

1.2.2 数据流的特征

           数据流是一组有序,有起点和终点的字节的数据序列(如图),它包括输入流和输出流。
在这里插入图片描述

1.2.3 输入流的特征

           输入流是程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道。比较通俗的来讲就是外部的文件通过输入流,传入到咱们的程序当中,程序去读取输入流内容(如图)。
在这里插入图片描述

1.2.4 输出流的特征

           输出流是程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道。比较通俗的来讲就是程序中的内容通过输出流,输出给外部(如图)。
在这里插入图片描述

二、Java IO类库的框架

2.1 Java IO的类型

           通过第一点描述得知,其实Java的IO类库总体来说其实并不复杂。从是读写的的维度看,Java IO可以分为

  1. 输入流:InputStream和Reader
  2. 输出流:OutputStream和Writer

从其处理流的类型的维度上看,Java IO又可以分为:

  1. 字节流:InputStream和OutputStream
  2. 字符流:Reader和Writer

下面这幅图就清晰的描述了JavaiO的分类:

字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

2.2 Java IO的类库

           上面我们介绍了Java IO中的四各类:InputStream、OutputStream、Reader、Writer,其实在我们的实际应用中,我们用到的一般是它们的子类,之所以设计这么多子类,目的就是让每一个类都负责不同的功能,以方便我们开发各种应用。各类用途汇总如下:

  • 文件访问
  • 网络访问
  • 内存缓存访问
  • 线程内部通信(管道)
  • 缓冲
  • 过滤
  • 解析
  • 读写文本 (Readers / Writers)
  • 读写基本类型数据 (long, int etc.)
  • 读写对象

下面按I/O类型来总体分类:

  1. Memory
    (1)从/向内存数组读写数据: CharArrayReader、 CharArrayWriter、ByteArrayInputStream、ByteArrayOutputStream
    (2)从/向内存字符串读写数据 StringReader、StringWriter、StringBufferInputStream
  2. Pipe管道:实现管道的输入和输出(进程间通信): PipedReader、PipedWriter、PipedInputStream、PipedOutputStream
  3. File 文件流:对文件进行读、写操作 :FileReader、FileWriter、FileInputStream、FileOutputStream
  4. ObjectSerialization 对象输入、输出:ObjectInputStream、ObjectOutputStream
  5. DataConversion数据流:按基本数据类型读、写(处理的数据是Java的基本类型(如布尔型,字节,整数和浮点数)):DataInputStream、DataOutputStream
  6. Printing:包含方便的打印方法 :PrintWriter、PrintStream
  7. Buffering缓冲:在读入或写出时,对数据进行缓存,以减少I/O的次数:BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream
  8. Filtering 滤流:在数据进行读或写时进行过滤:FilterReader、FilterWriter、FilterInputStream、FilterOutputStream
  9. Concatenation合并输入:把多个输入流连接成一个输入流 :SequenceInputStream
  10. Counting计数 :在读入数据时对行记数 :LineNumberReader、LineNumberInputStream
  11. Peeking Ahead:通过缓存机制,进行预读 :PushbackReader、PushbackInputStream
  12. Converting between Bytes and Characters:按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换(Stream到Reader,Writer的转换类):InputStreamReader、OutputStreamWriter

下面就以这张图来大体了解一下这些类的继承关系
在这里插入图片描述

三、Java IO的基本用法

3.1 字节流InputStream/OutputStream

3.1.1 InputStream抽象类

           InputStream 为字节输入流,它本身为一个抽象类,必须依靠其子类实现各种功能。继承自InputStream 的流都是向程序中输入数据的,且数据单位为字节(8bit),InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法.以下是Inputstream类中的常用方法:

  1. public abstract int read( ):读取一个byte的数据,返回值是高位补0的int类型值。若返回值=-1说明没有读取到任何字节读取工作结束。
  2. public int read(byte b[ ]):读取b.length个字节的数据放到b数组中。返回值是读取的字节数。该方法实际上是调用下一个方法实现的 。
  3. public int read(byte b[ ], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。
  4. public int available( ):返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用。
  5. public long skip(long n):忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取 。
  6. public int close( ) :我们在使用完后,必须对我们打开的流进行关闭。

主要的子类:在这里插入图片描述

3.1.2 OutputStream抽象类

           OutputStream提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。

  1. public void write(byte b[ ]):将参数b中的字节写到输出流。
  2. public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流。
  3. public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。
  4. public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。
  5. public void close( ) : 关闭输出流并释放与流相关的系统资源。

主要的子类:
在这里插入图片描述

3.1.3 文件输入流:FileInputStream类

           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();    }
3.1.4 文件输出流:FileOutputStream类

           用来处理以文件作为数据输出目的数据流;或者说是从内存区读数据入文件

例:用字节流去写文件

    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();    }
3.1.5 缓冲输入输出流 BufferedInputStream/ BufferedOutputStream

           在第一大点有提到就是流它的读取效率是比较低的,原始的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大小。

3.2 字符流Writer/Reader

3.2.1 Reader抽象类

           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();    }
3.2.2 Writer抽象类

           写入字符流的抽象类。子类必须实现的方法仅有 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();    }
3.2.3 BufferedReader和BufferedWriter

           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流?

4.1 字节流与字符流的区别?

想要选择用哪种IO流,首先,肯定是要先区分字节流与字符流之间的差异,以下是我总结几点:

  1. 字节流和字符流的用法几乎完成全一样,区别在于字节流和字符流所操作的数据单元不同,字节流操作的单元是数据单元是8位的字节,字符流操作的是数据单元为16位的字符。
  2. 字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。
  3. 字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。

4.2 确定是数据源和数据目的(输入还是输出)

           输入:InputStream、Reader
           输出:OutputStream、Writer

4.3 明确操作的数据对象是否是纯文本

           纯文本:Reader,Writer
           非纯文本:InputStream,OutputStream

五、如何关闭流?

5.1 必须关闭的流

          当我们新建一个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();}}

5.2 内存流可以不用关闭

          有些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文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 【JAVA IO 详细介绍】
    JAVA IO 详细介绍 目录一、什么是IO?1.1 IO的介绍1.2 流的介绍1.2.1 流的特征1.2.2 数据流的特征1.2.3 输入流的特征1.2.4 输出流的特征 二、...
    99+
    2023-10-26
    java
  • Java中IO流的详细介绍
    这篇文章主要介绍“Java中IO流的详细介绍”,在日常操作中,相信很多人在Java中IO流的详细介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中IO流的详细介绍”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-20
  • 详细介绍Linux IO
    1.IO概述 分析一下写操作: char *buf = malloc(MAX_BUF_SIZE); strncpy(buf, src, , MAX_BUF_SIZE); fwrite(buf, MAX_BUF_SIZ...
    99+
    2022-06-03
    Linux IO
  • Java非阻塞IO和异步IO的详细介绍
    这篇文章主要讲解了“Java非阻塞IO和异步IO的详细介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java非阻塞IO和异步IO的详细介绍”吧!阻塞模式 IO我们已经介绍过使用 Java...
    99+
    2023-06-02
  • Java IO流 - 打印流详细使用介绍
    文章目录 打印流打印流基本使用输出语句重定向 打印流 打印流基本使用 打印流: 作用:打印流可以实现更方便、更高效的打印数据到文件中去。打印流一般是指:PrintStrea...
    99+
    2023-09-05
    java 算法 开发语言
  • Java IO流 - 缓冲流的详细使用介绍
    文章目录 缓冲流缓冲流概述字节缓冲流字符缓存流 缓冲流 缓冲流概述 缓冲流介绍: 缓冲流也称为高效流、或者高级流。之前学习的字节流和字符流可以称为原始流。 作用:缓冲流自带...
    99+
    2023-09-11
    java jvm 算法
  • Java IO流 - 字节流的使用详细介绍
    文章目录 IO流的基本介绍字节流的使用文件字节输入流创建字节输入流每次读取一个字节每次读取一个数组一次读取全部字节 文件字节输出流创建字节输出流写入文件输出流 文件拷贝练习 ...
    99+
    2023-09-16
    java jvm 前端
  • Java maven详细介绍
    目录maven什么是maven仓库的种类仓库的配置本地仓库配置私服配置中央仓库配置maven标准目录结构常用命令maven项目的生命周期pom.xml依赖适用域总结maven 什么是...
    99+
    2022-11-12
  • Java 方法(详细介绍)
    那么什么是方法呢?Java方法是语句的集合,它们在一起执行一个功能。 (推荐学习:java课程)方法是解决一类问题的步骤的有序组合方法包含于类或对象中方法在程序中被创建,在其他地方被引用方法的优点 使程序变得更...
    99+
    2017-06-19
    java教程 Java
  • java泛型详细介绍
    一. 泛型概念的提出(为什么需要泛型)?(推荐:java视频教程)首先,我们看下下面这段简短的代码:public class GenericTest { public static void main(String[] args)...
    99+
    2019-06-24
    java基础 java
  • Java NIO的详细介绍
    这篇文章主要讲解了“Java NIO的详细介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java NIO的详细介绍”吧!首先,我们需要弄清楚几个概念:同步和异步,阻塞和非阻塞。同步和异步...
    99+
    2023-06-16
  • 详细介绍java UDP通信
    介绍:UDP为用户数据报协议,在java中操纵UDP使用JDK中java.net包下的DatagramSocket和DatagramPacket类,可以方便的控制用户数据报文。DatagramPacket类将数据字节填充到UDP包中,这称为...
    99+
    2016-02-03
    java教程 java UDP通信
  • 浅析Java getResource详细介绍
    在 Java 中访问资源我们一般使用 getResource() 方法,亦或者直接new File()然后传入一个文件路径获取资源文件。但是这两者究竟有什么区别呢?由于平常在使用的时...
    99+
    2022-11-12
  • Java操作Redis详细介绍
    1. 简介Redis 是一个开源(BSD许可)的,内存中的key-value存储系统,它可以用作数据库、缓存和消息中间件。2. 对key的操作首先要建立连接Jedis jedis = new Jedis("127.0.0.1", 6379)...
    99+
    2023-05-30
    java redis使用
  • Java中CompletableFuture 的详细介绍
    目录1.概述1.0 创建 CompletableFuture 的对象的工厂方法1.1 non-async 和 async 区别1.1.1 non-async 示例:注册 action...
    99+
    2022-11-13
  • java反射机制详细介绍
    一、什么是JAVA的反射机制(推荐:java视频教程)Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifie...
    99+
    2015-08-04
    java
  • Java 函数编程详细介绍
    目录一、函数编程Lambda1、接口二、Java函数接口1、Predicate2、Consumer3、Function4、Supplier三、类型检查1、Capturing Lamb...
    99+
    2022-11-12
  • OAuth2 详细介绍!
    目录 一、文章介绍 二、OAth2 2.1 简介 2.2 OAuth2  授权总体流程 2.3 四种授权模式 1.授权码模式 2.简化模式 3.密码模式 4. 客户端模式 2.4 OAuth2 标准接口 2.5 GitHub 授权登录 1...
    99+
    2023-09-15
    github java
  • springMVC详细介绍
    目录springMVC简介SpringMVC框架的优点第一个SpringMVC程序第一步:创建maven-web项目第二步:在pom.xml中添加依赖和插件第三步注册中央调度器第四步...
    99+
    2022-11-12
  • DockerCompose详细介绍
    目录一、Docker Compose的安装二、Docker Compose的基本使用三、Docker Compose的高级功能四、总结一、Docker Compose的安装 Dock...
    99+
    2023-05-16
    Docker Compose详解 Docker Compose
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作