《Java I/O 从0到1》 - 第Ⅱ滴血 “流”
前言
《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》 - 第Ⅱ滴血 “流”的更多相关文章
- Java I/O 从0到1 - 第Ⅰ滴血 File
前言 File 类的介绍主要会依据<Java 编程思想>以及官网API .相信大家在日常工作中,肯定会遇到文件流的读取等操作,但是在搜索过程中,并没有找到一个介绍的很简洁明了的文章.因此, ...
- 20145208 《Java程序设计》第0周学习总结
20145208 <Java程序设计>第0周学习总结 阅读心得 读了老师推荐的几个文章,虽然第四个文章"为什么一定要自学"报告资源不存在而无法阅读,其他的三篇文章都言之 ...
- Windows Intellij环境下Gradle的 “Could not determine Java version from ‘9.0.1’”的解决方式
当我导入Gradle项目初试Java spring的时候,遇到下面报错: Gradle complete project refresh failed Error:Could not determin ...
- 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版本里会出 ...
- 20145328 《Java程序设计》第0周学习总结
20145328 <Java程序设计>第0周学习总结 阅读心得 从总体上来说,这几篇文章都是围绕着软件工程专业的一些现象来进行描述的,但深入了解之后就可以发现,无论是软件工程专业还是我们现 ...
- 《Java I/O 从0到1》 - 第Ⅰ滴血 File
前言 File 类的介绍主要会依据<Java 编程思想>以及官网API .相信大家在日常工作中,肯定会遇到文件流的读取等操作,但是在搜索过程中,并没有找到一个介绍的很简洁明了的文章.因此, ...
- Java升级替换java version "1.5.0"
首先进行java安装 http://www.cnblogs.com/someone9/p/8670585.html 2. 然后查看版本信息,仍然是1.5.0 [root@OKC java]# java ...
- java在线聊天项目0.5版 解决客户端向服务器端发送信息时只能发送一次问题 OutputStreamWriter DataOutputStream socket.getOutputStream()
没有解决问题之前客户端代码: package com.swift; import java.awt.BorderLayout; import java.awt.Color; import java.a ...
- Java SPI、servlet3.0与@HandlesTypes源码分析
关于Java SPI与servlet3.0的应用,这里说的很精炼,链接地址如下. https://blog.csdn.net/pingnanlee/article/details/80940993 以 ...
随机推荐
- react+flux编程实践(一) 基础篇
1. React概览 最初听到React而还未深入了解它时,大多数人可能和我的想法一样:难道又是一个新的MVC/MVVM前端framework?深入了解后发现不是这么一回事,React关注的东西很单纯 ...
- 【Centos7】安装nginx
1.安装必要的rpm yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel 2.安装PCRE : 作用 ...
- 004-谈一谈lock和synchronized
这两个关键字都是用来对线程进行同步操作的. 参考疯狂java讲义16.5节 线程的同步. (完全答反了...)
- MongoDB Native Node.js Driver
写在前面 最近读<node.js学习指南>,对于mongodb没有介绍太多的工作原理,但是对于一个前端开发者,即使你还没有用过这种数据库也可以让你很好的理解和使用 一本非常好的 ...
- Sentry的安装搭建与使用
业务监控工具 Sentry 的搭建与使用 官方网址 Django Sentry 官网链接 Sentry 简介 Sentry 是一个开源的实时错误报告工具,支持 web 前后端.移动应用以及游戏,支持 ...
- Django 创建admin账户
Django版本 1.11.4 安装参考:http://blog.csdn.net/a_little_snail/article/details/76933868 问题:创建admin账户密码 解决: ...
- C#/VB.NET对EXCEL图片添加超链接
在日常工作中,在编辑文档时,为了方便自己或者Boss能够实时查看到需要的网页或者文档是,需要对在Excel中输入的相关文字进行超链接,那么对于一些在Excel中插入的图片我们该怎么实现超链接呢,下面给 ...
- C# 爬虫 Jumony html解析
前言 前几天写了个爬虫,然后认识到了自己的不足.感谢 "倚天照海- -" ,我通过你推荐的文章,意外的发现了html解析的类库——Jumony. 研究了2天,我发现这个东西简单粗暴 ...
- C#多线程的用法7-线程间的协作ManualResetEvent
ManualResetEvent:手动重置事件,它用于线程间同步时用法非常简单也易于理解. private static void MultiThreadSynergicWithManualReset ...
- 通过ssh协议实现用户key认证登录
author:JevonWei 版权声明:原创作品 用户实现key认证登录 主机A 192.168.198,134 主机B 192.168.198,131 主机C 192.168.198,136 创建 ...