Java中IO流

Java中IO流分为3种:

  • 按照流的流向分,可以分为输入流和输出流;
  • 按照操作单元划分,可以分为字节流和字符流
  • 按照流的角色划分为节点流和处理流

字节流:处理字节数据的流设备。字节流可以处理设备上的所有数据,所以字节流可以处理字符数据。
字符流:由于字符每个国家都使用得不一样,所以涉及到了字符编码问题,为了方便文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。

InputStream/Reader:所有的输入流的基类,前者是字节输入流,后者是字符输入流。
OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流。

BIO:同步阻塞I/O模型,数据的读取写入必须阻塞在一个线程内等待其完成。

NIO:同步非阻塞的I/O模型,对应java.nio包,提供了Channel,Selector,Buffer等抽象。NIO提供了与传统BIO模型中的Socket和ServerSocket对应的SocketChannel和ServerSocketChannel两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。

AIO:进化版NIO,它是异步非阻塞的IO模型。异步IO是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会阻塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续操作。

IO中使用到的设计模式:装饰器模式
装饰器设计模式解决:对一组类进行功能的增强。
包装:写一个类(包装类)对被包装对象进行包装:
1. 包装类和被包装类要实现同样的接口;
2. 包装类要持有一个被包装类的引用;
3. 包装类在实现接口时,大部分方法是靠调用被包装对象来实现的。

new BufferedReader(new FileReader("")); 
new BufferedReader(new InputStreamReader(System.in));

一层嵌套一层,字节流转字符流等等,这样方式的使用就是装饰器模式的一种体现。

流的操作规律:

1. 明确源和目的:

  • 数据源:需要读取,可以使用两个体系:InputStream、Reader;
  • 目的:需要写入,可以使用两个体系:OutputStream、Writer;

2. 操作的数据是否属于纯文本数据:
如果是:

  • 数据源:Reader
  • 目的:Writer

如果不是:

  • 数据源:InputStream
  • 目的:OutputStream

3.体系中的对象

  • 源:硬盘(File)、内存(byte[])、键盘(System.in)
  • 目的:硬盘(File)、内存(byte[])、键盘(System.out)

缓存区(Buffer):是一个特殊的数组,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态。Channel提供从文件、网络读取数据的渠道,但是读取或写入的数据都必须经由Buffer,如下图所示:

该图模拟了从一个客服端向服务端发送数据,然后服务端接收数据的过程。客户端发送数据时,必须先将数据存入Buffer中,然后将Buffer中的内容写入通道。服务端这边接收数据必须通过Channel将数据读入到Buffer中,然后再从Buffer中取出数据来处理。

通道(Channel):Channel和IO中的Stream(流)是类似的,例如FileInputStream对象,用来建立到目标(文件、网络套接字、硬件设备等)的一个链接,但是:BIO中的stream是单向的,例如FileInputStream对象只能进行读取数据操作,而NIO中的通道(Channel)是双向的,既可以用来进行读操作,也可以用来进行写操作。

Selector:Selector能够检测多个注册的通道上是否有事件发生,如果有事件发生,便获取事件然后针对每个事件进行相应的响应处理。

import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

// 往本地文件中写数据
public class TestFileChannel {
    public static void main(String[] args) throws Exception{
        String str = "hello, nio, 我是哈哈";
        // 通过输出流中获取到Channel
        FileOutputStream fos = new FileOutputStream("basic.txt");
        FileChannel fc = fos.getChannel();
        // 设置缓存区的初始容量
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        // 在往channel中写入数据时,必须通过put方法存到ByteBuffer
        byteBuffer.put(str.getBytes());
        // 反转缓存区,重置位置到初始位置(将指针重置到head)
        byteBuffer.flip();
        fc.write(byteBuffer);
        fos.close();
    }
}
import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class TestFileChannel2 {
    public static void main(String[] args) throws Exception{
        // 得到文件描述符
        File file = new File("basic.txt");

        // 得到流对象
        FileInputStream fileInputStream = new FileInputStream(file);

        // 打开通道
        FileChannel fc = fileInputStream.getChannel();

        // 开辟缓存
        ByteBuffer byteBuffer = ByteBuffer.allocate((int)file.length());

        // 读取到缓存中
        fc.read(byteBuffer);

        // 读到
        System.out.println(new String(byteBuffer.array()));
        fileInputStream.close();
    }
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值