Java I/O学习(一)
写作目的
自学Java,Java中流的概念比较复杂,故专门作一整理。期望开始学习的童鞋,看完本文后对Java流有一个大致的认识。主要分三个小篇:
一、概述、输入/输出字节流
二、输入/输出字符流、装饰者模式与处理流
三、其他
本文首先大致介绍以下流的概念和分类,然后介绍字节流的接口,最后介绍一些三种常用的字节流,并举例说明它们的用法。
一、什么是流

首先,给一个图,给大家一个感性的认识。大家至少接触过面向对象语言,在面向对象语言中讲到输入输出(I/O)时,一般都是流。那什么是流呢?你能准确描述一下吗?其实我也不能准确描述描述,下面是我的理解。首先说说IO,IO就是将数据从一个地方搬运到另一个地方,如从一个文件运到内存中,从一台机器运到另一台机器。再来说说流,流就是隐藏这一搬运细节的一个对象(或者说将搬运细节封装起来了)。如上图所示,流对象就像桥一样,连接源数据和目标存放位置,我们程序员呢,什么都不用管,只要将源数据按照流对象规定的格式存到流对象中或从流对象读出来。
二、Java中的流
每学一门编程语言,I/O总是很头疼的一块,虽然我一直用C++写代码,但对C++的流我也没有搞懂。像控制结构、基本数据类型、运算类型等等一般都是相同的,但是流在不同的语言中会有很大差别。因为是自学,所以就把它弄清楚一些。JDK本身提供了丰富的流类型。我们首先用思维导图的方式来将这些类整理一下:
是不是很壮观,先大体上说下Java流的分类:
按流向分,可分为输入流和输出流(输入/输出是针对CPU而言的);
按处理数据的类型,可字节流和字符流(一般字节流就够用了,涉及到文本编码,尤其是非ASCII编码的会用到字符流)。在此,要强调的一点:磁盘上存储的所有数据都是面向字节的,字符只存在程序(或者说内存)中。
- 按功能分,可分为节点流和处理流。节点流提供基本功能,处理流提供扩展功能,增加性能。
所有这些类中,最重要的就是InputStream和OutputStream,接着是Reader和Writer。首先来详细介绍以下InputStream的接口。
2.1 InputStream类提供的接口
接口一、从流中读入一个字节的数据

上面这个方法是InputStream唯一的抽象方法,子类必须实现这一方法,其功能是读入一个字节的数据。不同的输入流(有不同的数据源),读入的方式当然是不一样的,接下来要介绍的几个接口都依赖于这一接口。此接口返回值有两种可能:(1) 读到字节的值; (2) -1表示已经读到流的结束。
接口二、从流中读入若干个字节

这个函数是从流中读入若干字节到缓存数组b[]中,返回值也有两种情况:
(1) 实际读到字节数组b中的字节数(可能<b.length);
(2) -1,已经到流的结尾啦,没有字节可读了!
一般而言,上述两个函数是我们在使用输入流时,最常用的两个函数。另外,JDK还给我们提供了另一个更为灵活的读入若干字节的接口:

这个接口与上一个接口的功能是类似的,只是增加了off和len两个参数,使用户可以指定读入字节的起始位置和长度。如果len + off > b.length,会抛出一个IndexOutofBoundsException异常。
2.2 OutputStream类提供的接口
接下来,介绍输出流的接口。OutputStream的接口与InputStream的接口是一一对应的。你有read一个字节,那我就有write一个字节;你有read若干个字节,那我就有write若干个字节。接口如下(不做详细介绍了):
public abstract void write(int b) throws IOException;
public void write(byte b[]) throws IOException;
public void write(byte b[], int off, int len) throws IOException;
2.3 字节流的派生类及作用

2.4 流的使用
下面通过几个实例来看看第3节介绍的三种流的用法。
1. 文件输入流
public static void main(String args[]) throws IOException {
// 定义文件输入流
FileInputStream fis = new FileInputStream("test.txt");
// 定义读入缓存字节
byte buf[] = new byte[1024];
// 使用read接口读入
fis.read(buf);
// 输出读入的字节
System.out.println(new String(buf));
}
【注】这里读入的buf字节数组,将其按系统默认字符集编码转为String字符串,然后输出。若文件的字符集编码与系统默认字符集编码不一致,则需要在构造String指定编码,否则可能出现乱码。
2. 字节数组输入流
前面已经指出,该流主要用于接收并解析网络数据,在单机上没啥意思。另外,需要配合处理流(如:DataInputStream)一起使用,在这里我们通过一个简单的例子来演示一下。
public static void main(String args[]) throws IOException {
// 定义输入缓冲区,这部分内容通常由网络传输过来的。
String sBuf = new String("ByteArrayInputStream Test.");
byte buf[] = sBuf.getBytes();
// 定义输入字节数组流
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
// 读入其中的8个字节并输出
byte[] obuf = new byte[8];
bais.read(obuf);
System.out.println(new String(obuf));
// 再次强调:上述三行代码仅仅演示,一般字节数组流不单独使用。
}
3. 管道流
配合使用,最好在线程中使用,便于线程的通信。为了演示,首先派生两个线程类,如下:
//实现两个线程类
class ThreadRead extends Thread { private PipedInputStream mPis = null; public ThreadRead(PipedInputStream pis) {
mPis = pis;
} // 读取管道流内容并输出
public void run() {
byte[] buf = new byte[100];
try {
mPis.read(buf);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(new String(buf));
}
} class ThreadWrite extends Thread { PipedOutputStream mPos = null; public ThreadWrite(PipedOutputStream pos) {
mPos = pos;
} public void run() {
String s = new String("你好!PipedOutputStream.");
try { mPos.write(s.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
主函数如下:
public class PipedStreamDemo01 {
public static void main(String args[]) {
PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis = null;
try {
pis = new PipedInputStream(pos);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} Thread th1 = new ThreadRead(pis);
Thread th2 = new ThreadWrite(pos); th2.start();
th1.start();
}
三、小结
到此,字节流大致介绍完毕。
Java I/O学习(一)的更多相关文章
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- 一位资深程序员大牛给予Java初学者的学习路线建议
java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是我你是如何学习Java的,能不能给点建议?今天我是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈 ...
- java并发编程学习: ThreadLocal使用及原理
多线程应用中,如果希望一个变量隔离在某个线程内,即:该变量只能由某个线程本身可见,其它线程无法访问,那么ThreadLocal可以很方便的帮你做到这一点. 先来看一下示例: package yjmyz ...
- 回答阿里社招面试如何准备,顺便谈谈对于Java程序猿学习当中各个阶段的建议
引言 其实本来真的没打算写这篇文章,主要是LZ得记忆力不是很好,不像一些记忆力强的人,面试完以后,几乎能把自己和面试官的对话都给记下来.LZ自己当初面试完以后,除了记住一些聊过的知识点以外,具体的内容 ...
- Java程序员学习之路
1. Java语言基础 谈到Java语 言基础学习的书籍,大家肯定会推荐Bruce Eckel的<Thinking in Java>.它是一本写的相当深刻的技术书籍,Java语言基础部分基 ...
- 老鸟谈谈JAVA EE的学习
老鸟谈谈JAVA EE的学习 因为出差和项目的原因,有将近一个月的时间没有更新博客了,今天终于得闲,和兄弟们分享一下JAVA EE的学习心得.书中带过,直入主题,下面我们首先看看什么是JAVA EE. ...
- Java虚拟机JVM学习07 类的卸载机制
Java虚拟机JVM学习07 类的卸载机制 类的生命周期 当Sample类被加载.连接和初始化后,它的生命周期就开始了. 当代表Sample类的Class对象不再被引用,即不可触及时,Class对象就 ...
- Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论
Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...
- Java虚拟机JVM学习05 类加载器的父委托机制
Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...
- Java虚拟机JVM学习04 类的初始化
Java虚拟机JVM学习04 类的初始化 类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始 ...
随机推荐
- webstorm 快捷键
Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/*-*/ ) Shift+F6 重构-重命名 Ctrl+X 删除行 Ctrl+D 复制行 Ctrl+G 查找行 Ctrl+Shift+Up ...
- windows server 2008镜像重启后密码变为默认密码的问题的解决方案
1. cmd中执行regedit,打开注册表: 修改HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Cloudbase Solusions\Cloudbase-Init ...
- 菜鸟的MySQL学习笔记(五)
7.自定义函数 用户自定义函数(user-defined function,UDF)是一种对MySQL扩展的途径,其用法与内置函数相同.包含了两个必要条件,参数与返回值.没有必然内在联系. 函数可以返 ...
- maven一些问题
maven一些问题 - ljhzzyx的日志 - 网易博客 1. The container 'Maven Dependencies' references non existing library ...
- vi或vim快捷键
1.dG:这是删除光标所在行到最后一行的内容(包括光标所在行的内容) 2.ggVG全选
- Java 单链表的倒置
在面试,笔试的过程中经常会遇到面试官问这种问题,实现单链表的倒置方法.现在对单链表的倒置犯法做个记录,方便自己以后查看. 单链表的定义: public class Node { int v; Node ...
- copy,retain,assign,strong,weak的区别
引用地址:http://www.aichengxu.com/view/32930 一.assign,copy,retain 1.copy是内容复制,新建一个相同内容的不同指针,retain为指针复制, ...
- 10g和11g,优化器对外连接的处理对比
我反省,今天面试有个问题没有说清楚.我给出的结论(而且这个结论我验证过)是:不要使用不必要的外连接,举了下面这个例子却没有说清楚.虽然最近感冒,状态不是很好,但最擅长的东西都没有表达清楚,泪流满面啊: ...
- 树莓派上搭建基于Python+web.py+fastcgi+lighttpd的网站
最近在网上淘了一个树莓派,什么是树莓派?这里是他的官方网站你可以去看看. 简单的说就是一块使用了ARM11的CPU,具有256MB或512MB内存的具有两个USB接口,一个RJ45接口,HDMI输出和 ...
- Java NIO回炉
重回东软了,据说可能要做一个跟文件相关的项目,于是决定把Java NIO的内容再捡起来,看看. 为什么要使用NIO,其实在低连接数的情况下,NIO的性能是要低于IO的:但是在高并发的情况下,确实NIO ...