写作目的

自学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学习(一)的更多相关文章

  1. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  2. 一位资深程序员大牛给予Java初学者的学习路线建议

    java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是我你是如何学习Java的,能不能给点建议?今天我是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈 ...

  3. java并发编程学习: ThreadLocal使用及原理

    多线程应用中,如果希望一个变量隔离在某个线程内,即:该变量只能由某个线程本身可见,其它线程无法访问,那么ThreadLocal可以很方便的帮你做到这一点. 先来看一下示例: package yjmyz ...

  4. 回答阿里社招面试如何准备,顺便谈谈对于Java程序猿学习当中各个阶段的建议

    引言 其实本来真的没打算写这篇文章,主要是LZ得记忆力不是很好,不像一些记忆力强的人,面试完以后,几乎能把自己和面试官的对话都给记下来.LZ自己当初面试完以后,除了记住一些聊过的知识点以外,具体的内容 ...

  5. Java程序员学习之路

    1. Java语言基础 谈到Java语 言基础学习的书籍,大家肯定会推荐Bruce Eckel的<Thinking in Java>.它是一本写的相当深刻的技术书籍,Java语言基础部分基 ...

  6. 老鸟谈谈JAVA EE的学习

    老鸟谈谈JAVA EE的学习 因为出差和项目的原因,有将近一个月的时间没有更新博客了,今天终于得闲,和兄弟们分享一下JAVA EE的学习心得.书中带过,直入主题,下面我们首先看看什么是JAVA EE. ...

  7. Java虚拟机JVM学习07 类的卸载机制

    Java虚拟机JVM学习07 类的卸载机制 类的生命周期 当Sample类被加载.连接和初始化后,它的生命周期就开始了. 当代表Sample类的Class对象不再被引用,即不可触及时,Class对象就 ...

  8. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  9. Java虚拟机JVM学习05 类加载器的父委托机制

    Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...

  10. Java虚拟机JVM学习04 类的初始化

    Java虚拟机JVM学习04 类的初始化 类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始 ...

随机推荐

  1. Java_类和对象(完美总结)_转载_覆盖和隐藏的区别,覆盖就不能使用了,而隐藏提供全局方法名或者全局变量名还可以使用

    转载自海子:http://www.cnblogs.com/dolphin0520/p/3803432.html Java:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封 ...

  2. leetcode处女作

    闲来无事[真的吗?你确定→_→ 在leetcode上刷了一道题.费时一小时,也是醉了.谨以此文,纪念我的伟大成果.[呵呵 题目是找出非排序数组中缺少的最小正整数.要求时间复杂度O(n),空间复杂度为常 ...

  3. iOS谋职之OC面试题

    iOS谋职之OC面试题 iOS求职之OC面试题 IOS求职之OC面试题 1.Objective-C的类可以多重继承么?可以采用多个协议么? 答:不可以多重继承,可以采用多个协议. 2.#import和 ...

  4. 使用Idea编写javaweb以及maven的综合(一)

    今天总结的第一点是在windows下使用idea编写jsp并且使用tomcat部署:第二点是新建maven项目,之前一直是听说也没有自己实践过,今天就大概说一下. 0x01 IDEA 全称 Intel ...

  5. (poj) 1751 Highways

    Description The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has a very poor ...

  6. Scala - 处理时间(nscala-time - Joda Time的scala封装)

    GITHUB : https://github.com/nscala-time/nscala-time MAVEN : (注意选对scala版本) <dependency> <gro ...

  7. js生成随机字符串或者随机数

    //返回一个指定范围内的随机数 function createRandomNum(Min,Max){ let Range = Max - Min; let Rand = Math.random(); ...

  8. php验证复选框有效性的示例

    本文介绍一个简单的php通过代码验证复选框值的有效性,有需要的可以参考一下 验证复选框的php代码,如下: 复制代码代码如下: <?php   /**   * 在php中验证复选框的有效性  * ...

  9. #Leet Code# Sqrt

    描述:log(n) 代码: class Solution: # @param x, an integer # @return an integer def getVal(self, begin, en ...

  10. BZOJ 1052: [HAOI2007]覆盖问题

    BZOJ 1052: [HAOI2007]覆盖问题 题意:给定平面上横纵坐标在-1e9~1e9内的20000个整数点的坐标,用三个大小相同边平行于坐标轴的正方形覆盖(在边界上的也算),问正方形的边长最 ...