美文网首页
Java I/O系统

Java I/O系统

作者: DaemonXiao | 来源:发表于2019-03-22 17:55 被阅读0次

1 输入和输出

Java类库中的I/O类分成输入和输出两部分,通过叠合多个对象来提供所期望的功能(装饰者设计模式)。

1.1 InputStream类型

InputStream的作用是用来表示那些从不同数据源产生输入的类。这些数据源包括:字节数组、String对象、文件、管道、一个由其他种类的流组成的序列、其他数据源等。
常用的类:

  • FileInputStream:用于从文件中读取信息,构造器参数是字符串,表示文件名、文件或者FileDescriptor对象。
//可以使用字符串类型的文件名来创建一个输入流对象来读取文件
InputStream fin = new FileInputStream("C:\java\hello.class");
//也可以使用一个文件对象来创建一个输入流对象来读取文件
File f = new File("C:\java\hello.class");
InputStream fin2 = new FileInputStream(f);

1.2 OutputStream类型

该类别的类决定了输出所要去的目标:字节数组、文件或者管道。
常用的类:

  • FileOutoutStream:用于将信息写至文件,构造器参数是字符串,表示文件名、文件或者FileDescriptor对象。如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。
import java.io.*;
 
public class fileStreamTest {
    public static void main(String args[]) {
        try {
            byte bWrite[] = { 11, 21, 3, 40, 5 };
            OutputStream os = new FileOutputStream("test.txt");
            for (int x = 0; x < bWrite.length; x++) {
                os.write(bWrite[x]); // writes the bytes
            }
            os.close();
 
            InputStream is = new FileInputStream("test.txt");
            int size = is.available();
 
            for (int i = 0; i < size; i++) {
                System.out.print((char) is.read() + "  ");
            }
            is.close();
        } catch (IOException e) {
            System.out.print("Exception");
        }
    }
}

2 Reader和Writer

Java 1.1对基本的I/O流类库进行了重大的修改,Reader和Writer这两个类不是用来替代上述的InputStream和OutputStream的类。它们面向的对象不同,Stream在以面向字节形式的I/O中仍然可以提供极有价值的功能,Reader和Writer则提供兼容Unicode与面向字符I/O功能。
有时我们必须把来自于“字节”层次结构中的类和“字符”层次结构中的类结合起来使用,为了实现这个目的,要用到适配器(adapter)类:InputStreamWriter和OutputStreamWriter。
设计Reader和Writer继承层次结构主要是为了国际化。老的I/O流继承层次结构仅支持8位字节流,并且不能很好地处理16位的Unicode字符。由于Unicode用于字符国际化,所以添加Reader和Writer继承层次的结构就是为了在所有的I/O操作中都支持Unicode。另外,新类库的设计使得它的操作比旧类库更快。

3 NIO

3.1 什么是NIO?

JDK 1.4的java.nio.*包中引入了新的Java I/O类库,其目的在于提高速度。实际上,旧的I/O包已经用nio重新实现过,以便充分利用这种速度提高,因此,即使我们不显式地使用nio编程,也能从中受益。
速度的提高来自于所使用的结构更接近于操作系统执行I/O的方式:通道和缓冲器。
NIO主要有三大核心部分:Channel,Buffer,Selector。传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer进行。数据总是从通道读取到缓冲区,或者从缓冲区写入到通道中。Selector用于监听多个通道的事件,因此,单个线程可以监听多个数据通道。

    public void method(){
        RandomAccessFile aFile = null;
        try{
            aFile = new RandomAccessFile("F:\\发票与回单\\抬头与税务号.txt","rw");
            FileChannel fileChannel = aFile.getChannel();
            ByteBuffer buf = ByteBuffer.allocate(1024);
            int bytesRead = fileChannel.read(buf);
            System.out.println(bytesRead);
            while(bytesRead != -1)
            {
                buf.flip();
                while(buf.hasRemaining())
                {
                    System.out.print((char)buf.get());
                }
                buf.compact();
                bytesRead = fileChannel.read(buf);
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally{
            try{
                if(aFile != null){
                    aFile.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

3.2 主要区别

3.3 缓冲区

在java nio中负责数据存取。缓冲区是数组。根据数据类型的不同,提供了响应的缓冲区:ByteBuffer, CharBuffer, ShortBuffer, IntBuffer, LongBuffer, FloatBuffer, DoubleBuffer。通过allocate() 获取缓冲区,主要方法为put() 和get() 。
四个核心属性:

  • capacity:表示缓冲区中最大存储数据的容量,一旦声明不能改变,即数组大小。
  • limit:缓冲区中可以操作数据的大小。(limit后面的数据不能进行读写)
  • position:表示缓冲区正在操作的位置。
  • mark:标记,表示记录当前position位置,可以通过reset() 回到刚才记录位置
    position <= limit <= capacity
    public void bufferTest() {

        //1. 分配一个指定大小的缓冲区
        ByteBuffer buf = ByteBuffer.allocate(1024);

        //2. 调用put方法存入数据
        String ss = "7777";
        buf.put(ss.getBytes());

        //3. 切换取数据 flip()
        buf.flip();

        //4. 利用get方法读取
        byte[] dst = new byte[buf.limit()];
        buf.get(dst);
        System.out.println(new String(dst));

        //5. rewind方法可重复读数据
        buf.rewind();

        //6. 清空缓冲区,但是缓冲区的数据易燃存在,只是指针回到初始,数据处于“被遗忘”状态。
        buf.clear();

    }

非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM内存中
直接缓冲区:通过allocateDirect()方法分配直接内存,将缓冲区建立在物理内存中,可以提高效率。
通过isDirect() 方法判断是否是直接缓冲区。


直接缓冲区

3.4 通道

通道用于源节点与目标节点的链接,需要配合缓冲区进行传输。通道的主要实现类:FileChannel, SocketChannel, ServerSocketChannel, DatagramChannel。
获取方式:

  1. getChannel()。
  2. 在 JDK 1.7中NIO.2 针对各个通道提供了静态方法open()。
  3. 在 JDK 1.7中NIO.2的Files工具类的newByteChannel()。
public void channelTest() throws IOException {
        FileInputStream fis = new FileInputStream("1.jpg");
        FileOutputStream fos = new FileOutputStream("2.jpg");

        //1. 获取通道
        FileChannel inChannel = fis.getChannel();
        FileChannel outChannel = fos.getChannel();

        //2. 分配指定大小缓冲区
        ByteBuffer buf = ByteBuffer.allocate(1024);

        //3. 将通道数据存入缓冲区
        while (inChannel.read(buf) != -1) {
            buf.flip();
            outChannel.write(buf);
            buf.clear();
        }

        outChannel.close();
        inChannel.close();
        fos.close();
        fis.close();
 }

相关文章

  • Java I/O 系统

    所谓 I/O 指的是输入输出,输入输出的一端是内存(RAM),另一端可以是文件系统中的文件、网络中的数据或者标准输...

  • Java I/O系统

    1 输入和输出 Java类库中的I/O类分成输入和输出两部分,通过叠合多个对象来提供所期望的功能(装饰者设计模式)...

  • Java I/O系统

    存在各种不同的I/O来源端和目的端(文件、控制台、网络),不但希望让它们可以通信,而且还要以多种不同方式来和它们通...

  • Java I/O体系从原理到应用,这一篇全说清楚了

    本文介绍操作系统I/O工作原理,Java I/O设计,基本使用,开源项目中实现高性能I/O常见方法和实现,彻底搞懂...

  • NIO异步实现读写

    NIO 库是在 JDK 1.4 中引入的。在Java1.4之前的I/O系统中,提供的都是面向流的I/O系统,NIO...

  • Java-I/O系统

    对程序语言的设计者来说,创建一个好的输出/输入(I/O)系统是一项艰难的任务。——《Thinking in Jav...

  • java基础——IO

    I/O作为作为人机交互的核心问题,很多web应用系统的瓶颈都是I/O瓶颈。本文主要总结java的I/O类库基本架构...

  • 计算机组成原理(七)输入输出系统

    7.1 I/O系统基本概念 I/O系统由I/O软件和I/O硬件两部分构成。 I/O硬件包括外部设备、I/O接口、I...

  • 线上学习资料汇总_新

    1. Java I/O 这些年一直记不住的 Java I/O 深入分析 Java I/O 的工作机制 NIO 入门...

  • 《JAVA编程思想》学习笔记:第18章(Java的I/O系统)

    第十八章、Java的I/O系统 对程序语言的设计者来说,创建一个好的I/O系统是一个艰难的任务: 需要涵盖不同的I...

网友评论

      本文标题:Java I/O系统

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