前言

  《Java I/O 从0到1》系列上一章节,介绍了File 类,这一章节介绍的是IO的核心 输入输出。I/O类库常使用流这个抽象概念。代表任何有能力产出数据的数据源对象或者是有能力接受数据的接收端对象。

  流 屏蔽了实际的I/0设备中处理数据的细节。Java类库中的I/O类库分为输入输出两部分。InputStram或Reader 派生而来的类都含有 read() 基本方法,用于 读 取单个字节或者字节数组。同样,任何自OutputStream或Writer 派生而来的类都含有名为write()基本方法,用于 写 单个字节或者字节数组。但是,我们通常不会用到这些方法,他们之所以存在是因为别的类可以使用它们,以便提供更有用的接口。因此,很少使用单一的类来创建流对象,而是通过叠合多个对象来提供所期望的功能。摘自《Java 编程思想第四版》

下面呢,提供一个整理的IO思维导图(查看图片,点击图片右键 选择 新标签页中打开):

Xmind下载链接:http://pan.baidu.com/s/1gfrLcf5


InputStream:用来表示从不同数据源产生输入的类。数据源包括:字节数组,String对象,文件,“管道”等 。引用《Java 编程思想第四版》中图片。

OutputStream:决定了输出所要去往的目标。

字节流

  字节流对应的类是InputStream和OutputStream,而在实际开发过程中,需要根据不同的类型选用相应的子类来处理。

  a. 先根据需求进行判定,读 则使用 InputStream 类型;  写 则使用 OutputStream 类型

  b. 在判定媒介对象什么类型,然后使用对应的实现类。  eg: 媒介对象是 文件  则使用FileInputStream FileOutputStream 进行操作。

  方法

  1.    int  read(byte[] b) 从此输入流中读取一个数据字节。

  2.  int read(byte[] b, int off, int len)  从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。

  3.   void   write(byte[] b)  将 b.length 个字节写入此输出流。

  4.    void   write(byte[] b, int off, int len)  将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

 /**
*
* Title: writeByteToFile
* Description: 字节流写文件
* @author yacong_liu Email:2682505646@qq.com
* @date 2017年9月20日下午5:34:41
*/
private static void writeByteToFile() {
String str = new String("Hello Everyone!,My name is IO");
byte[] bytes = str.getBytes();
File file = new File("D:" + File.separator + "tmp" + File.separator + "hello.txt");
OutputStream os = null;
try {
os = new FileOutputStream(file);
os.write(bytes);
System.out.println("write success");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

字节流 写 文件

     /**
*
* Title: readByByteFromFile Description: 字节流读文件
*
* @author yacong_liu Email:2682505646@qq.com
* @date 2017年9月20日下午5:47:35
*/
public static void readByByteFromFile() {
File file = new File("D:" + File.separator + "tmp" + File.separator + "hello.txt");
byte[] byteArr = new byte[(int) file.length()];
try {
InputStream is = new FileInputStream(file);
is.read(byteArr); System.out.println(new String(byteArr) + "\n"); is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} /**
* Console:
* Hello Everyone!,My name is IO
*/
}

字节流 读 文件

字符流

  字符流对应的类似 Reader 和 Writer。

 public static void writeCharToFile() {
String str = new String("Hello Everyone!,My name is IOs");
File file = new File("D:" + File.separator + "tmp" + File.separator + "helloChar.java");
try {
Writer os = new FileWriter(file); os.write(str); os.close();
} catch (IOException e) {
e.printStackTrace();
}
}

字符流 写 文件

     public static void readCharFromFile() {
File file = new File("D:" + File.separator + "tmp" + File.separator + "helloChar.java");
try {
Reader reader = new FileReader(file);
char[] byteArr = new char[(int) file.length()];
reader.read(byteArr); System.out.println("文件内容: " + new String(byteArr));
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} /**
* Console:
* 文件内容: Hello Everyone!,My name is IOs
*/
}

字符流 读 文件

字节字符流组合

  IO流之间可以组合,但不是所有的流都能组合。组合(或者称为嵌套)的好处就是把多种类型的特性融合到一起以实现更多的功能。

 public static void composeByteAndChar() {
File file = new File("D:" + File.separator + "tmp" + File.separator + "helloChar.java");
InputStream is; try {
is = new FileInputStream(file);
Reader reader = new InputStreamReader(is);
char[] byteArr = new char[(int) file.length()];
reader.read(byteArr); System.out.println("文件内容: " + new String(byteArr)); is.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}

字节流 组合 字符流

缓冲流

  缓冲就是对流进行读写操作时提供一个缓冲管道buffer来提高IO效率。(且由我说成为管道吧,其实原理都一样的嘛,前面是小管道,后面套一个大管道,然后就可以大批量的往后输送了嘛)。

  原始的字节流对数据的读取都是一个字节一个字节的操作,而Buffer缓冲流在内部提供了一个buffer,读取数据时可以一次读取一大块数据到buffer中,效率要提高很多。对于磁盘IO以及大量数据来讲,使用缓冲最合适不过。

  使用方面,其实很简单,只要在字节流的外面组合一层缓冲流即可。

 public static void readBufferFromByte(){
File file = new File("D:" + File.separator + "tmp" + File.separator + "helloChar.java");
byte[] byteArr = new byte[(int) file.length()];
try {
// 制定缓冲流 buffer 大小
InputStream is = new BufferedInputStream(new FileInputStream(file),2*1024); is.read(byteArr); System.out.println("文件内容: " + new String(byteArr)); is.close(); } catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

组合 缓冲流

  上面的示例中,我们制定了buffer 的大小,那么这个大小范围如何确定呢?这可不是瞎编的哦。buffer的大小应该是硬件状况来确定。对于磁盘IO来说,如果硬盘每次读取4KB大小的文件块,那么我们最好设置成这个大小的整数倍。因为磁盘对于顺序读的效率是特别高的,所以如果buffer再设置的大写可能会带来更好的效率,比如设置成4*4KB或8*4KB。

  还需要注意的就是磁盘本身就会有缓存,在这种情况下,BufferedInputStream会一次读取磁盘缓存大小的数据,而不是分多次的去读。所以要想得到一个最优的buffer值,我们必须得知道磁盘每次读的块大小和其缓存大小,然后根据多次试验的结果来得到最佳的buffer大小。(引用自Heaven-Wang 博客 java io 概述)。

那么,至此呢,本章节 “流”的内容就已经基本介绍完毕了,更多的内容还是需要常查看API。

    

 

《Java I/O 从0到1》 - 第Ⅱ滴血 “流”的更多相关文章

  1. Java I/O 从0到1 - 第Ⅰ滴血 File

    前言 File 类的介绍主要会依据<Java 编程思想>以及官网API .相信大家在日常工作中,肯定会遇到文件流的读取等操作,但是在搜索过程中,并没有找到一个介绍的很简洁明了的文章.因此, ...

  2. 20145208 《Java程序设计》第0周学习总结

    20145208 <Java程序设计>第0周学习总结 阅读心得 读了老师推荐的几个文章,虽然第四个文章"为什么一定要自学"报告资源不存在而无法阅读,其他的三篇文章都言之 ...

  3. Windows Intellij环境下Gradle的 “Could not determine Java version from ‘9.0.1’”的解决方式

    当我导入Gradle项目初试Java spring的时候,遇到下面报错: Gradle complete project refresh failed Error:Could not determin ...

  4. hadoop 遇到java.net.ConnectException: to 0.0.0.0:10020 failed on connection

      hadoop 遇到java.net.ConnectException: to 0.0.0.0:10020 failed on connection   这个问题一般是在hadoop2.x版本里会出 ...

  5. 20145328 《Java程序设计》第0周学习总结

    20145328 <Java程序设计>第0周学习总结 阅读心得 从总体上来说,这几篇文章都是围绕着软件工程专业的一些现象来进行描述的,但深入了解之后就可以发现,无论是软件工程专业还是我们现 ...

  6. 《Java I/O 从0到1》 - 第Ⅰ滴血 File

    前言 File 类的介绍主要会依据<Java 编程思想>以及官网API .相信大家在日常工作中,肯定会遇到文件流的读取等操作,但是在搜索过程中,并没有找到一个介绍的很简洁明了的文章.因此, ...

  7. Java升级替换java version "1.5.0"

    首先进行java安装 http://www.cnblogs.com/someone9/p/8670585.html 2. 然后查看版本信息,仍然是1.5.0 [root@OKC java]# java ...

  8. java在线聊天项目0.5版 解决客户端向服务器端发送信息时只能发送一次问题 OutputStreamWriter DataOutputStream socket.getOutputStream()

    没有解决问题之前客户端代码: package com.swift; import java.awt.BorderLayout; import java.awt.Color; import java.a ...

  9. Java SPI、servlet3.0与@HandlesTypes源码分析

    关于Java SPI与servlet3.0的应用,这里说的很精炼,链接地址如下. https://blog.csdn.net/pingnanlee/article/details/80940993 以 ...

随机推荐

  1. 编译安装 Python3.6.1

    操作系统 centos7.2 系统自带python版本 2.7.5 说明:编译python3的过程是简单的但比较慢,可以用连字符 && ,这样可以先去(忙其他的|喝茶|听音乐|聊妹), ...

  2. Hadoop2 和 Hadoop1 区别

    Hadoop2 和 Hadoop1 区别 Namenode NameNode其实是Hadoop的一个目录服务,它包含着整个集群存储的文件的元数据. 早期发行的Hadoop1版本将所有HDFS目录和文件 ...

  3. WeQuant交易策略—5日均线

    简单的价格突破策略.当前价格超过最近5个收盘价的均价,则全仓买入:低于均价,则全仓卖出 代码 # 简单的价格突破策略.当前价格超过最近5个收盘价的均价,则全仓买入:低于均价,则全仓卖出 # PARAM ...

  4. Google研究人员宣布完成全球首例SHA-1哈希碰撞!

    2004年的国际密码讨论年会(CRYPTO)尾声,我国密码学家王小云及其研究同事展示了MD5.SHA-0及其他相关杂凑函数的杂凑碰撞并给出了实例.时隔13年之后,来自Google的研究人员宣布完成第一 ...

  5. 利用Xtrabackup在不停机的情况下备用数据库迁移

    什么是Xtrabackup?答:Xtrabackup是一个对InnoDB做数据备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具InnoDB Hotbackup的一个很好的替代品. 下 ...

  6. .NET Core多平台开发体验[1]: Windows

    微软在千禧年推出 .NET战略,并在两年后推出第一个版本的.NET Framework和IDE(Visual Studio.NET 2002,后来改名为Visual Studio),如果你是一个资深的 ...

  7. HTML (Hyper Text Markup Language) 常用标签

    HTML是什么?  英文全称:Hyper Text Markup Language  中文全称:超文本标记语言  网页主要由 机构  表现 行为  组成 什么是标签?    < > 里的叫 ...

  8. C++语法细节笔记

    1.数据类型转换 当赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数. 把负数转换成无符号数类似于直接给无符号数赋一个负值,结果等于这个负数加上无符号数后的模. ...

  9. 单表ORM框架

    基本描述 1.首先是一个单表的ORM框架,多表连接查询请使用视图或者使用SqlHelper查询,然后转换成实体集合. 2.目前仅完成基本结构和MySQL部分. 3.目前欠缺Lambda表达式解析,所以 ...

  10. Spring《错误集合,总结更新》

    1.这几天配置springmvc 使用注解,并且自动扫描注解,当我单个配置,不用自动扫描,出现下面错误,找了很多人跟我看,配置也没问题,但是就是显示不出东西,所说的类也去看了,没有问题 這是我的模拟数 ...