文档章节

I/O工作机制

marjey
 marjey
发布于 2016/10/24 20:11
字数 1564
阅读 37
收藏 1

数据发生流动,都会涉及到IO问题。在当今这个数据大爆炸时代,I/O 问题尤其突出,很容易成为一个性能瓶颈。

JAVA中的I/O主要涉及到两个方向:磁盘I/O工作机制,网络I/O工作机制。

I/O基本框架

Java 的 I/O 操作类在包 java.io 下,大概有将近 80 个类,但是这些类大概可以分成四组,分别是:

  1. 基于字节操作的 I/O 接口:InputStream 和 OutputStream
  2. 基于字符操作的 I/O 接口:Writer 和 Reader
  3. 基于磁盘操作的 I/O 接口:File
  4. 基于网络操作的 I/O 接口:Socket

前两组主要是根据传输数据的数据格式,后两组主要是根据传输数据的方式,虽然 Socket 类并不在 java.io 包下,但是我仍然把它们划分在一起,因为我个人认为 I/O 的核心问题要么是数据格式影响 I/O 操作,要么是传输方式影响 I/O 操作,也就是将什么样的数据写到什么地方的问题,I/O 只是人与机器或者机器与机器交互的手段,除了在它们能够完成这个交互功能外,我们关注的就是如何提高它的运行效率了,而数据格式和传输方式是影响效率最关键的因素了。我们后面的分析也是基于这两个因素来展开的。

基于字节的 I/O 操作接口

基于字节的 I/O 操作接口输入和输出分别是:InputStream 和 OutputStream,InputStream 输入流的类继承层次如下图所示:

输入流根据数据类型和操作方式又被划分成若干个子类,每个子类分别处理不同操作类型,OutputStream 输出流的类层次结构也是类似,如下图所示:

图 2. OutputStream 相关类层次结构

java io的开始:文件

 

1. 我们主要讲的是流,流的本质也是对文件的处理,我们循序渐进一步一步从文件将到流去。

2. java 处理文件的类 File,java提供了十分详细的文件处理方法。

另外一个BLOG对文件File类有了进一步说明。

输入流:从磁盘或网络取得提供给程序(存放在内存)使用的数据。

输出流:数据已经在程序中存在(内存),现要写入到磁盘或者网络。

我理解的“流”是一个中介对象。通过它,磁盘和内存(buffer)实现交互。

字节输出流:OutputStream  (抽象类)

方法:

close() 关闭输出流

flush()  刷新缓冲区

write() ;向输出流中写入byte[]

write(int b) 向输出流中写入一个字节

FileOutputStream ;

 

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Created by li on 2016/10/24.
 * 1
 */
public class FileInputDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("D:/asd.txt");
        if (!file.exists()) {
            System.out.println(file.createNewFile());
        }

        OutputStream outputStream = new FileOutputStream(file, true);
        outputStream.write("Hello Word".getBytes("utf-8"));
outputStream.close();
      //outputStream.write("Hello Word".getBytes("utf-8"));
}
}

注意任何流对象都应该关闭,关闭后再往里面做读写错字可是不能了。

OutputStream outputStream = new FileOutputStream(file, true);

设置为true可在文件后追加,否则清空文件。

 

 

InputStream 

只有一个构造方法,仅仅用于创建对象。

方法

Methods 

Modifier and Type Method and Description
int

available()

返回输入流指向的数据能被读取或者跳过的字节大小。

 

void close()

关闭输入流,关闭之后输入流指向数据为空,再做操作会报错。

void mark(int readlimit)

标记属于流位置。

boolean markSupported()

测试输入流是否支持标记和重置方法。

abstract int read()

从输入流指向的数据仓库中读取数据到内存。

int read(byte[] b)

读取输入流指向的数据到内存b字节中。

int read(byte[] b, int off, int len)

读取指定长度字节

void reset()

重置标记。

long skip(long n)

跳读输入流指向数据。

 

import java.io.*;

/**
 * Created by li on 2016/10/24.
 * 1
 */
public class FileInputDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("D:/asd.txt");
        if (!file.exists()) {
            System.out.println(file.createNewFile());
        }
        OutputStream outputStream = new FileOutputStream(file);
        outputStream.write("输出输出".getBytes());
        InputStream inputStream = new FileInputStream(file);
//        System.out.println(inputStream.available());
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);


        String s = new String(bytes, 0, len);
        System.out.println(s);
        inputStream.close();

    }
}

字符流不做介绍,注意 OutputStreamWriter 和InputStreamReader 可在字节流和字符流中变换。

内存操作流

 

ByteoutputStream 用于将内存中的数据输出。 这个类的构造器好像是唯一不需要添加参数的IO类,其他类可以用它指定为构造器输入,做为中介将数据传输给它,然后该对象有一个方法toByteArray()用于把输入的东西转为字节数组。(搭配ObjectOutputStream使用)

ByteIntputStream 用于读取数据到内存。

 

内存操作流一般用于生成一些临时信息,假如不用内存操作流,临时信息需要存放在文件中,比较麻烦。

如将对象转为二进制需要用到。

import com.sun.org.apache.xpath.internal.SourceTree;

import java.io.Serializable;

public class Preson implements Serializable {
    String name;

    void tell() {
        System.out.println("name is " + name);
    }
}
import java.io.*;
import java.time.Period;

public class Obj {


    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Preson preson = new Preson();
        preson.name = "lisi";
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(preson);
        byte[] bytes = byteArrayOutputStream.toByteArray();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Preson object = (Preson) objectInputStream.readObject();
        object.tell();
        System.out.println(object.name);
    }
}

 

 

管道流:用于两个线程之间通信。 要进行输出,必须把输出流连在输入流上。

代码实例:

 

import java.io.IOException;
import java.io.PipedOutputStream;

public class pip extends Thread {

    private PipedOutputStream pipedOutputStream = null;

    public void send() {
        this.pipedOutputStream = new PipedOutputStream();
    }

    public PipedOutputStream getPipedOutputStream() {
        return pipedOutputStream;
    }

    @Override
    public void run() {
        String s = "Hello Word";
        try {
            this.pipedOutputStream.write(s.getBytes("utf-8"));
            this.pipedOutputStream.close();
            ;
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
import java.io.IOException;
import java.io.PipedInputStream;

public class Get extends Thread {

    private PipedInputStream pipedInputStream = null;

    public void get() {
        this.pipedInputStream = new PipedInputStream();
    }

    public PipedInputStream getPipedInputStream() {
        return pipedInputStream;
    }

    @Override
    public void run() {
        byte[] bytes = new byte[1024];
        int len = 0;
        try {
            len = this.pipedInputStream.read(bytes);
            this.pipedInputStream.close();
            System.out.println(new String(bytes));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class Demo {
    public static void main(String[] args) throws IOException {
        pip pip1 = new pip();
        pip1.send();
        Get get = new Get();
        get.get();
        PipedInputStream pipedInputStream = get.getPipedInputStream();
        PipedOutputStream pipedOutputStream = pip1.getPipedOutputStream();
        pipedOutputStream.connect(pipedInputStream);
        pip1.start();
        get.start();
    }
}

现对此不做细纠。以后写到多线程再说吧。

再列举一些类  

数据操作流:DataOutputStream  主要针对数据进行操作

合并流:SequenceInputStream  将两个文件合并为一个文件。

压缩流: ZipInpputStream 可将文件或文件夹压缩为ZIP,JAR,GZIP形式。

© 著作权归作者所有

marjey
粉丝 3
博文 173
码字总数 139219
作品 0
昆明
私信 提问
linux下的工作模型以及Nginx工作原理

web服务器主要任务就是处理来自客户端的请求,一般情况下Web服务器处理并发连接请求的工作模型有以下几种方式: 1、单线程web服务器(Single-threaded web servers) 此种架构方式中,web服务器...

魔都搬砖
2018/06/28
0
0
Nginx为什么比Apache Httpd高效:原理篇

Nginx才短短几年,就拿下了web服务器大笔江山,众所周知,Nginx在处理大并发静态请求方面,效率明显高于httpd,甚至能轻松解决C10K问题。下面我们就来聊聊Web服务器背后的一些原理。 一、进程...

小杨_Ivan
2017/02/09
0
0
深入分析 Java I/O 的工作机制(一)

简介: I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这个海量数据时代,数据在网络中随处流动。这个流动的过程中都涉及到 I/O 问题,可以说大部分 Web 应用系统的...

Mysoft
2015/09/24
59
0
一步步分析 Node.js 的异步I/O机制

它的优秀之处并非原创,它的原创之处并非优秀。 《深入浅出Node》 本文章节如下图所示,阅读时间大约为10分钟~15分钟,图少字多,建议仔细阅读。 背景 在计算机资源中,I/O和CPU计算在硬件支...

芒僧
06/03
0
0
Java NIO 学习:概述

Java 在 I/O 领域一直处于劣势,这种情况直到 J2SE SDK 发布了 1.4 版以后才有了改观。 Java 的劣势源于其最大的优势:一次编写,到处运行。 Java 需要运行于虚拟机(即 JVM)之上,为了保证...

HenrySun
2016/08/04
90
0

没有更多内容

加载失败,请刷新页面

加载更多

从零基础到拿到网易Java实习offer,我做对了哪些事

作为一个非科班小白,我在读研期间基本是自学Java,从一开始几乎零基础,只有一点点数据结构和Java方面的基础,到最终获得网易游戏的Java实习offer,我大概用了半年左右的时间。本文将会讲到...

Java技术江湖
昨天
4
0
程序性能checklist

程序性能checklist

Moks角木
昨天
6
0
VUE 计算属性

本文转载于:专业的前端网站▶VUE 计算属性 1、示例代码 <!DOCTYPE html><html lang="zh"> <head> <meta charset="UTF-8" /> <title>vue示例</title> </hea......

前端老手
昨天
5
0
快速搭建LNMT平台和环境部署 Tomcat详解

Tomcat部署的基本概念 1. CATALINA_HOME与CATALINA_BASE分别指什么?     CATALINA_HOME指的是Tomcat的安装目录     bin:\\Tomcat一些脚本存放目录,比如启动脚本startup.bat/start...

网络小虾米
昨天
6
0
float浮动

float浮动 float浮动概念及原理: 文档流:文档流是文档中可显示对象在排列时所占用的位置。 加浮动的元素,会脱离文档流,会沿父容器靠左或靠右排列,如果之前已经有浮动的元素,会挨着浮动...

studywin
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部