《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 以 ...
随机推荐
- c#Reverse字符串
class Program { static void Main(string[] args) { // 输出 ypoc si yek eht string str = "the key i ...
- Java中的i=i++
public class Demo_01 { public static void main(String[] args) { int a = 10; int b = 20; int i = 0; i ...
- RedHat 7 常用命令总结
Linux RedHat 7常用命令总结... ----------------------- 征服Linux从终端开始 ------------------------------------- 在 ...
- 获取当前页面URL信息
文章链接:http://www.cnblogs.com/hongmaju/p/5510988.html 查看信息可以在控制台输出(tab或者右移补全): 如:document.URL window. ...
- C++基础:二维数组动态的申请内存和释放内存
使用二维数组的时候,有时候事先并不知道数组的大小,因此就需要动态的申请内存.常见的申请内存的方法有两种:malloc/free 和 new/delete. 一.malloc/free (1)申请一维数 ...
- 通过css控制超链接不显示下划线
“页面属性”——“链接”——“下划线样式”——“始终无下划线” <style type="text/css"> a:link { text-decoration: no ...
- 迁移学习-Transfer Learning
迁移学习两种类型: ConvNet as fixed feature extractor:利用在大数据集(如ImageNet)上预训练过的ConvNet(如AlexNet,VGGNet),移除最后几层 ...
- 深入浅出数据结构C语言版(17)——有关排序算法的分析
这一篇博文我们将讨论一些与排序算法有关的定理,这些定理将解释插入排序博文中提出的疑问(为什么冒泡排序与插入排序总是执行同样数量的交换操作,而选择排序不一定),同时为讲述高级排序算法做铺垫(高级排序为什 ...
- [自制操作系统] 原子操作&核间中断&读写锁&PRWLock
本文主要为读论文Scalable Read-mostly Synchronization Using Passive Reader-Writer Locks的记录. 并将其在JOS上实现.其中包括la ...
- my new day in CNblog
感谢大家 今天正式在博客园平台开启我的第三个技术面博客 之前一直坚持在csdn平台撰文(http://blog.csdn.net/github_38885296)欢迎参观:) 因为觉得博客园知名度虽不 ...