java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java流Stream

Java基础:流Stream详解

作者:CodingALife

Stream流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。这篇文章主要介绍了Java8新特性Stream流的相关资料,需要的朋友参考下吧

写在前面

从Java 1.0开始,引入java.io包;到Java 1.4再扩展了java.nio包;再到java 1.7又添加了新的流类,使得Java的流机制变得十分强大。

一、"流"概念

James Gosling所著《Java程序设计》中描述Java I/O流模式图如下。Program是中间环节,用于对Source进行处理,然后输出到Dest处。

b654b83fa3312585d665d043388b518d.png

Java中的"流"就是指把数据从一个对象移动到另一个对象的流动模式的抽象。其实Java的流模式用水流或者电流模型来解释是很容易理解的。

363cc7573ed96e3ea734d47025759159.png

James Gosling的Java流模式图与水流模式图概念映射。数据源(data source)即水库,数据目的地(data destination)就是脸盆,数据(data)就是水,流(stream)实例化就是在管子中流动的水流。

输入流(input stream)就是用水泵从水库中抽出来要到水管中的水,输出流(output stream)经过水龙头将要达到脸盆中的水,计算机内存(memory)就是上图中的水流管道,关闭输入流(close input stream)就是关闭水泵开关,关闭输出流(close output stream)就是关闭关闭水龙头开关。

更进一步说,具体的水库和脸盆分别对应于Java中输入流对象和输出流对象。水流可以分成一粒一粒的水分子,这些水分子映射成计算机二进制位(bit)0/1,其组成的水滴映射成计算机字节流(字节是计算机储存信息的基本单位)。字节流和字符流在物理层面的实现都是比特流,二进制数据流可以认为是字节流,而字符流是遵循unicode编码规则的字节流。因此计算机中的"流"概念实际上就是指字节数据(bytes data)从源对象对按顺序流向目标对象的一种流动形式。

e31533f5a5cfd51c65279543be6e302a.png

二、流的分类

1、按流的方向分为:输入流、输出流

判断当前流是输入流还是输出流的依据是二进制数据相对于计算机内存的位置,输入流是输入计算机内存是二进制数据,输出流是从计算机内存输出的二进制数据。而计算机程序在运行期间会储存在到计算机内存中,因此总的来说就是数据的来源、取向是相对程序而言的。比如键盘键入数据属于输入流,内存数据持久化到磁盘中属于输出流。

cd73d9ac40fe5f303e72def8f682ddf4.png

说明:本图片取自互联网,纠正补充为流的来源有网络连接、内存块、磁盘(文件)、键盘等;流的去向也基本是这些。

2、按流处理数据的单位分为:字节流、字符流

从物理层面来看,流中数据都是二进制比特流。而计算机中储存信息的基本单位是字节(Byte)。因此,可以认为计算机中信息传输在底层是靠字节流来实现的。字符流只是通过不同的字符编码方式,对字节流的封装,即字符流的实现还是得依靠字节流。

3、按流的功能分为:节点流(又称低级流)、过滤流(又称高级流、处理流、包装流)

节点流(Node Stream)是流管道两端直接连接data source和data destination上的,即为取放数据的真实载体,在流通道本身不对数据做任何加工,因而也被称为低级流。

节点流从一个特定的数据源读写数据。即节点流是直接操作文件,网络等的流,例如FileInputStream和FileOutputStream,他们直接从文件中读取或往文件中写入字节流。

2374f1b0340903f7b84a7a89c3f94422.png

“连接”在已存在的流(节点流或处理流)之上通过对数据的处理为程序提供更为强大的读写功能。过滤流是使用一个已经存在的输入流或输出流连接创建的,过滤流就是对节点流进行一系列的包装。例如BufferedInputStream和BufferedOutputStream,使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率,以及DataInputStream和DataOutputStream,使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。他们都属于过滤流。

f71da4ab9fa8bc1a96224fc34c9d1ad0.png

public static void main(String[] args) throws IOException {
        // 节点流FileOutputStream直接以A.txt作为数据源操作
        FileOutputStream fileOutputStream = new FileOutputStream("A.txt");
        // 过滤流BufferedOutputStream进一步装饰节点流,提供缓冲写
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                fileOutputStream);
        // 过滤流DataOutputStream进一步装饰过滤流,使其提供基本数据类型的写
        DataOutputStream out = new DataOutputStream(bufferedOutputStream);
        out.writeInt(3);
        out.writeBoolean(true);
        out.flush();
        out.close();
        // 此处输入节点流,过滤流正好跟上边输出对应,读者可举一反三
        DataInputStream in = new DataInputStream(new BufferedInputStream(
                new FileInputStream("A.txt")));
        System.out.println(in.readInt());
        System.out.println(in.readBoolean());
        in.close();
}

理解:

4、字节流与字符流区别

三、流的方法

1、字节流

字节输入流类:FileInputStream、BufferedInputStream和DataInputStream

FileInputStream:此类用于从本地文件系统中读取文件内容。

构造方法:

常用方法:

BufferedInputStream此类本身带有一个缓冲区,在读取数据时,先放到缓冲区中,可以减少对数据源的访问,提高运行的效率。

构造方法:

常用方法:

DataInputStream:该类提供一些基于多字节读取方法,从而可以读取基本数据类型的数据。

构造方法:

常用方法:

字节输出流类:FileOutputStream、BufferedOutputStream和DataOutputStream

FileOutputStream:此类用于从本地文件系统的文件中写入数据。

构造方法:

常用方法:

BufferedOutputStream:此类本身带有一个缓冲区,在写入数据时,先放到缓冲区中,实现缓冲的数据流。

构造方法:

常用方法:

DataOutputStream(OutputStream out):创建一个新的数据输出流,将数据写入指定基础输出流。

常用方法:

2、字符流

FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的

构造方法:

FileReader(File file):在给定从中读取数据的File的情况下创建一个新的FileReader。FileReader(String fileName):在给定从中读取数据的文件名的情况下创建一个新的FileReader。

BufferedReader类是Reader类的子类,为Reader对象添加字符缓冲器,为数据输入分配内存存储空间,存取数据更为有效。

构造方法:

操作方法:

FileWriter:用来写入字符文件的便捷类,可用于写入字符流。

构造方法:

FileWriter(File file):根据给定的File对象构造一个FileWriter对象。

FileWriter(String filename):根据给定的文件名构造一个FileWriter对象。

BufferedWriter: 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

缓冲流的目的:

操作流的时候,习惯定义一个byte/char数组。

int read(): 每次都从磁盘文件中读取一个字节。 直接操作磁盘文件性能极低。

解决方案:定义一个数组作为缓冲区。

byte[] buffer = new byte[1024];该数组其实就是一个缓冲区。

一次性从磁盘文件中读取1024个字节。如此以来,操作磁盘文件的次数少了,性能得以提升。提供的默认缓存区大小是8192(1024*8),我们一般不用修改大小

public class BufferStreamDemo {
    public static void main(String[] args) throws Exception {
        File file = new File("file/aaa.txt");
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
        out.write("中国".getBytes());
        out.close();
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
        byte[] buffer = new byte[1024];
        int len = -1;
        while((len = in.read(buffer)) != -1){
            System.out.println(new String(buffer, 0, len));
        }
        in.close();
    }
}
public class BufferCharacterDemo {
    public static void main(String[] args) throws Exception {
        File file = new File("file/aaa.txt");
        BufferedWriter in = new BufferedWriter(new FileWriter(file,true));
        in.newLine();//用来换行等同于‘\n'
        in.write("美国");
        in.newLine();
        in.write("马来西亚");
        in.close();
        BufferedReader out = new BufferedReader(new FileReader(file));
        String line = null;
        //按行读取
        while((line = out.readLine()) != null){
            System.out.println(line);
        }
        out.close();
    }
}

4、流相关设计模式

处理流/包装流(相对于节点流更高级) 装饰设计模式/包装模式:

参考:https://blog.csdn.net/dreamzuora/article/details/79691702

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

您可能感兴趣的文章:
阅读全文