美文网首页
Java中的IO流

Java中的IO流

作者: 我要离开浪浪山 | 来源:发表于2021-08-28 12:16 被阅读0次

1、IO简介

数据流是一组有序,有起点和终点的字节的数据序列。包括输入流和输出流。

流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:

    1. 字节流:数据流中最小的数据单元是字节
    1. 字符流:数据流中最小的数据单元是字符,

Java中的字符是Unicode编码,一个字符占用两个字节。
Java.io包中最重要的就是5个类和一个接口。
5个类指的是File、OutputStream、InputStream、Writer、Reader;
一个接口指的是Serializable。掌握了这些就掌握了Java I/O的精髓了。

2、Java I/O主要包括如下3层次:

    1. 流式部分——最主要的部分。如:OutputStream、InputStream、Writer、Reader等
    1. 非流式部分——如:File类、RandomAccessFile类和FileDescriptor等类
    1. 其他——文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。
image.png

3、字节流的学习

在具体的学习流之前,我们必须要学的一个设计模式是装饰模式。因为从流的整个发展历史,出现的各种类之间的关
系看,都是沿用了修饰模式,都是一个类的功能可以用来修饰其他类,然后组合成为一个比较复杂的流。比如说:

DataOutputStream out = new DataOutputStream( 
    new BufferedOutputStream( 
    new FileOutputStream( 
    new File(file)));

从上面的代码块中大家不难看出这些类的关系:
为了向文件中写入数据,首先需要创建一个FileOutputStream,然后为了提升访问的效率,所以将它发送给具备缓存功能的BufferedOutput-Stream,而为了实现与机器类型无关的java基本类型数据的输出,所以,我们将缓存的流传递给了DataOutputStream。从上面的关系,我们可以看到,其根本目的都是为outputSteam添加额外的功能。而这种额外功能的添加就是采用了装饰模式来构建的代码。因此,学习流,必须要学好装饰模式。

4、字节流

image.png

字节流的学习过程

为什么要按照一个学习路线来呢?原因是他们的功能决定的。
OutputStream -> FileOutputStream/FilterOutputStream ->DataOutputStream->bufferedOutputStream
相应的学习InputStream方法就好了。

FilterOutputStream

从学习的角度来,我们应该先掌握FilterOutputStream, 以及FileOutputStream,这两个类是基本的类,从继承关系可以不难发现他们都是对 abstract 类 OutputStream的拓展,是它的子类。然而,伴随着 对 Stream流的功能的拓展,所以就出现了 DataOutputStream,(将java中的基础数据类型写入数据字节输出流中、保存在存储介质中、然后可以用DataOutputStream从存储介质中读取到程序中还原成java基础类型)。这里多提一句、DataOutputStream、FilterOutputStream三个类的关系的这种设计既使用了装饰器模式 避免了类的爆炸式增长。

BufferedOutputStream

为了提升Stream的执行效率,所以出现了bufferedOutputStream。bufferedOutputStream就是将本地添加了一个缓存的数组。在使用bufferedOutputStream之前每次从磁盘读入数据的时候都是需要访问多少byte数据就向磁盘中读多少个byte的数据,而出现bufferedOutputSteam之后,策略就改了,会先读取整个缓存空间相应大小的数据,这样就是从磁盘读取了一块比较大的数据,然后缓存起来,从而减少了对磁盘的访问的次数以达到提升性能的目的。

另外一方面,我们知道了outputStream(输出流)的发展历史后,我们便可以知道如何使用outpuSteam了,同样
的方法,我们可以运用到inputStream中来,这样对称的解释就出现到了inputStream相关的中来了,于是,我们对
整个字节流就有了全方位的理解,所以这样子我们就不会感觉到流的复杂了。这个时候对于其他的一些字节流的使用
(byteArrayOutputStream/PipeOutputStream/ObjectOutputStream)的学习就自需要在使用的时候看看API即可。

5、字符流

image.png image.png

1:如果只用FileOutputStream fileOutputStream = new FileOutputStream("d:/text.txt"); 不是也能输出到"d:/text.txt"吗?为什么要用其它两个呢?能起到什么作用呢?

答案: FileOutputStream :是字节流,它一个字节一个字节的向外边送数据 OutputStreamWriter:是字符流,它一个字符一个字符的向外边送数据

2:它们有什么区别么?

答案: 英文字符占一个字节,中文是一个字符,至少占俩字节。 如果用stream,你读出来的英语再倒也罢了,读出来的中文可就是乱码或者一个个“????”。 如果你用WRITER,就不会有乱码了

3:BufferedWriter Buffer是一个缓冲区,为什么要用BUFFER呢?

答案: 如果你直接用stream或者writer,你的硬盘可能就是读一个字符或者一个字节 就去读写 硬盘一次,IO负担巨大。可是你用了Buffer,你的硬盘就是读了一堆数据之后,读写一下硬 盘。这样对你硬盘有好处。

6、字节流与字符流的关系

那么字节输入流和字符输入流之间的关系是怎样的呢?请看下图

image.png

7、字节流与字符流的区别

字节流和字符流使用是非常相似的,那么除了操作代码的不同之外,还有哪些不同呢?
字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使 用到缓冲区的字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方 法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在 不close的情况下输出内容

8、那开发中究竟用字节流好还是用字符流好呢?

在所有的硬盘上保存文件或进行传输的时候都是以字节的方法进行的,包括图片也是按字节完成,而字符是只有在内存中才会形成的,所以使用字节的操作是最多的。
如果要java程序实现一个拷贝功能,应该选用字节流进行操作(可能拷贝的是图片),并且采用边读边写的方式(节省内存)

9、RandomAccessFile

image.png image.png

10、NIO——FileChannel

Channel是对I/O操作的封装。
FileChannel配合着ByteBuffer,将读写的数据缓存到内存中,然后以批量/缓 存的方式read/write,省去了非批量操作时的重复中间操作,操纵大文件时可 以显著提高效率(和Stream以byte数组方式有什么区别?经过测试,效率上几 乎无区别)。

11、字节流与字符流的转换

虽然Java支持字节流和字符流,但有时需要在字节流和字符流两者之间转换。
InputStreamReader和OutputStreamWriter,这两个为类是字节流和字符流之间相互转换的类。

1、InputSreamReader用于将一个字节流中的字节解码成字符:

有两个构造方法
//功能:用默认字符集创建一个InputStreamReader对象
InputStreamReader(InputStream in);
//功能:接收已指定字符集名的字符串,并用该字符创建对象
InputStreamReader(InputStream in,String CharsetName);
//字节流转化为字符流
 var input = FileInputStream("aa/aa.txt")
 val inputStreamReader = InputStreamReader(input)

2、OutputStream用于将写入的字符编码成字节后写入一个字节流。

同样有两个构造方法:
//功能:用默认字符集创建一个OutputStreamWriter对象;
OutputStreamWriter(OutputStream out);
功能:接收已指定字符集名的字符串,并用该字符集创建OutputStreamWrite对象
OutputStreamWriter(OutputStream out,String CharSetName);
var out = FileOutputStream ("aa/aa.txt")
val outputStreamWriter = OutputStreamWriter(out)

3、为了避免频繁的转换字节流和字符流,对以上两个类进行了封装。
BufferedWriter类封装了OutputStreamWriter类;
BufferedReader类封装了InputStreamReader类;

//封装格式:
BufferedWriter out=new BufferedWriter(new OutputStreamWriter(System.out)); BufferedReader in= new BufferedReader(new InputStreamReader(System.in);

利用下面的语句,可以从控制台读取一行字符串:

BufferedReader in=new BufferedReader(new InputStreamReader(System.in)); String line=in.readLine();

相关文章

  • 28、说说Java 中 IO 流

    说说Java 中 IO 流 Java 中 IO 流分为几种? 1、按照流的流向分,可以分为输入流和输出...

  • 05-Java中的IO与NIO面试题(15题)

    1、Java 中 IO 流? Java 中 IO 流分为几种?按照流的流向分,可以分为输入流和输出流;按照操作单元...

  • Java之IO流详解

    title: Java之IO流详解tags: Java IO流categories: Java IO流 大多数应用...

  • Java中的IO流

    Java中的IO流分类 输入IO流输入字节流(InputStream)处理流缓冲流(BufferedInputSt...

  • IO

    一 IO中各个流的基本用法 参考: java中的IO整理 二 IO体系 参考:看完这个,Java IO从此不在难 ...

  • Java IO 笔记

    学习Java中的IO,首先要理解Java中IO的流模型。所谓流,可以假想成河流,流的数据源,就是河流的发源地,流是...

  • Java新特性之Java8的那些事儿-Stream

    什么是流? ​ Java Se中对于流的操作有输入输出IO流,而Java8中引入的Stream 属于Java ...

  • java笔记--IO流(字符流和字节流)

    IO流: 用来处理设备之间的数据传书。Java对数据的操作是通过流的方式。Java用于操作流的对象都在IO包中。流...

  • javaIO

    吃透Java IO:字节流、字符流、缓冲流 IO流是Java中的一个重要构成部分,也是我们经常打交道的。 下面几个...

  • Java IO与NIO技术体系分析

    java.io包中最为核心的一个概念是流(Stream),面向流的编程。流分为两种输入流和输出流,Java中的io...

网友评论

      本文标题:Java中的IO流

      本文链接:https://www.haomeiwen.com/subject/sirbiltx.html