I/O流概述

在 Java 中,把不同类型的输入、输出源抽象为流(Stream),而其中输入或输出的数据则称为数据流(Data Stream),用统一的接口表示,从而使程序设计简单明了。流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

字节流基类

字节流主要操作byte类型数据,以byte数组为准,java 中每一种字节流的基本功能依赖于基本类 InputStream 和 Outputstream,他们是抽象类,不能直接使用。字节流能处理所有类型的数据(如图片、avi等)

  • InputStream

此抽象类是表示字节输入流的所有类的超类。InputStream 是从装置来源地读取数据的抽象表示,例如 System 中的标准输入流 in 对象就是一个InputStream 类型的实例。

只有默认的无参构造器,类中定义的其它方法如下:

  1. | 方法 | 描述 |
  2. |------|------|
  3. | int available() | 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。 |
  4. | void close() | 关闭此输入流并释放与该流关联的所有系统资源。 |
  5. | void mark(int readlimit) | 在此输入流中标记当前的位置。 |
  6. | boolean markSupported() | 测试此输入流是否支持 mark reset 方法。 |
  7. | **abstract** int read() | 从输入流中读取数据的下一个字节。 |
  8. | int read(byte[] b) | 从输入流中读取一定数量的字节,并将其存储在**缓冲区数组** b 中。 |
  9. | int read(byte[] b, int off, int len) | 将输入流中最多 len 个数据字节读入 byte[off] byte[off + len -1]。 |
  10. | void reset() | 将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。 |
  11. | long skip(long n) | 跳过和丢弃此输入流中数据的 n 个字节。 |
  12. >
  13. >对于三个read()方法,若返回-1,表明流结束,否则,返回**实际读取的字符数**。
  • OutputStream

此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。例如 System 中的标准输出流对象 out 其类型是java.io.PrintStream,这个类是 OutputStream 的子类。

只有默认的无参构造器,类中定义的其它方法如下:

  1. | 方法 | 描述 |
  2. |------|------|
  3. | void close() | 关闭此输出流并释放与此流有关的所有系统资源。|
  4. | void flush() | **刷新**此输出流并**强制写出**所有缓冲的输出字节。|
  5. | void write(byte[] b) | b.length 个字节从指定的 byte 数组写入此输出流。|
  6. | void write(byte[] b, int off, int len) | 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。|
  7. | **abstract** void write(int b) | 将指定的字节写入此输出流。|

一般来说,很少直接实现 InputStream 或 OutputStream 上的方法,因为这些方法比较低级,通常会实现它们的子类。

文件流

  • File 类

首先来了解一下File类。Java文件类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。

构造方法:

  1. //根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
  2. File(File parent, String child);
  3. //通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
  4. File(String pathname);
  5. // 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
  6. File(String parent, String child);
  7. // 通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。
  8. File(URI uri);

经常使用File类的下列方法获取文件本身的一些信息:

  1. | 方法 | 描述 |
  2. |-----|-----|
  3. | public String getName() | 获取文件的名字。 |
  4. | public boolean canRead() | 判断文件是否是可读的。 |
  5. | public boolean canWrite() | 判断文件是否是可被写入的。|
  6. | public boolean exits() | 判断文件是否存在。 |
  7. | public long length() | 获取文件的长度(单位是字节)。 |
  8. | public String getAbsolutePath() | 获取文件的绝对路径。 |
  9. | public String getParent() | 获取文件的父目录。 |
  10. | public boolean isFile() | 判断文件是否是一个正常文件,而不是目录。 |
  11. | public boolean isDirectory() | 判断文件是否是有个目录。 |
  12. | public boolean isHidden() | 判断文件是否是隐藏文件。 |
  13. | public long lastModified() | 获取文件最后修改的时间(返回距1970.01.01的毫秒数)。
  14. >
  15. >关于目录、文件创建与删除等内容不做展开,可以去[JDK 1.6 在线中文手册](http://www.runoob.com/manual/jdk1.6/)中查看File类的方法。

java.io 包中所提供的文件操作包括:

  1. 用于读写本地文件系统中的文件:FileInputStream 和 FileOutputStream
  2. 描述本地文件系统中的文件或目录:File、FileDescriptor 和 FilenameFilter
  3. 提供对本地文件系统中文件的随机访问支持:RandomAccessFile
  • FileInputStream

FileInputStream 类用于打开一个输入文件,若要打开的文件不存在,则会产生异常 FileNotFoundException,这是一个非运行时异常,必须捕获或声明抛弃。

构造方法:

  1. //打开一个以 f 描述的文件作为输入
  2. FileInputStream(File f);
  3. //打开一个文件路径名为 name 的文件作为输入
  4. FileInputStream(String name);

从输入流中读取字节,可以用上面介绍的 InputStream 类中三个 read 方法。

  • FileOutputStream

FileOutputStream 类用来打开一个输出文件,若要打开的文件不存在,则会创建一个新的文件,否则原文件的内容会被新写入的内容所覆盖。

构造方法:

  1. //创建一个以 f 描述的文件作为输出
  2. //如果文件存在,则其内容被清空
  3. FileOutputStream(File f);
  4. //创建一个文件路径名为 name 的文件作为输出
  5. //文件如果已经存在,则其内容被清空
  6. FileOutputStream(String name);
  7. //创建一个文件路径名为 name 的文件作为输出
  8. //文件如果已经存在,则在该输出上输出的内容被接到原有内容之后
  9. FileOutputStream(String name, boolean append);

使用上面 OutputStream 类中介绍的 write() 方法把字节写入到输出流到达目的地,只要不关闭流,就可以一直调用顺序写入。

注:虽然 Java 在程序结束时自动关闭所有打开的流,但是当我们使用完流之后,显式地关闭任何打开的流仍是一个良好的习惯(调用 close() 方法)。原因是一个打开的流会占用一定的系统资源,关闭输出流还可以把该流缓冲区的内容冲洗掉,即写到它的目的地。

缓冲流

BufferedInputStream 和 BufferedOutputStream 实现了带缓冲的过滤流,它提供了缓冲机制,把任意的 I/O 流“捆绑”到缓冲流上,可以提高 I/O 流的读取效率。在初始化时,除了要指定所连接的 I/O 流之外,还可以指定缓冲区的大小。

  • BufferedInputStream

BufferedInputStream 的数据成员 buf 是一个位数组,默认为2048字节。当读取数据来源时例如文件,BufferedInputStream 会尽量将 buf 填满。当使用 read ()方法时,实际上是先读取 buf 中的数据,而不是直接对数据来源作读取。当 buf 中的数据不足时,BufferedInputStream 才会再实现给定的 InputStream 对象的 read() 方法,从指定的装置中提取数据。不过也可以使用 flush() 方法人为地将尚未填满的缓冲区中的数据送出。

构造方法:

  1. BufferedInputStream(InputStream in);
  2. BufferedInputStream(InputStream in, int size);
  • BufferedOutputStream

BufferedOutputStream 的数据成员 buf 是一个位数组,默认为512字节。当使用 write() 方法写入数据时,实际上会先将数据写至 buf 中,当 buf 已时才会实现给定的 OutputStream 对象的 write() 方法,将 buf 数据写至目的地,而不是每次都对目的地作写入的动作。

构造方法:

  1. BufferedOutputStream(OutputStream out);
  2. BufferedOutputStream(OutputStream out, int size);

数据流

接口 DataInput 和 DataOutput,设计了一种较为高级的数据输入输出方式:除了可处理字节和字节数组外,还可以处理 int、float、boolean等基本数据类型,这些数据在文件中的表示方式和它们在内存中的一样,无须转换,如 read(), readInt(), readByte()...; write(), writeChar(), writeBoolean()...此外,还可以用 readLine()方法读取一行信息。

数据流类 DateInputStream 和 DataOutputStream 的处理对象除了是字节或字节数组外,还可以实现对文件的不同数据类型的读写:

  1. 分别实现了 DataInput 和 DataOutput 接口
  2. 在提供字节流的读写手段同时,以统一的形式向输入流中写入 boolean,int,long,double 等基本数据类型,并可以再次把基本数据类型的值读取回来。
  3. 提供了字符串读写的手段

相关知识

  • 标准流

语言包 java.lang 中的 System 类管理标准输入/输出流和错误流。

  1. System.in从 InputStream 中继承而来,用于从标准输入设备中获取输入数据(通常是键盘)
  2. System.out从 PrintStream 中继承而来,把输入送到缺省的显示设备(通常是显示器)
  3. System.err也是从 PrintStream 中继承而来,把错误信息送到缺省的显示设备(通常是显示器)

每当 main 方法被执行时,就会自动生产上述三个对象。

  • 内存读写流

为了支持在内存上的 I/O,java.io 中提供了类:ByteArrayInputStream、ByteArrayOutputStream 和 StringBufferInputStream

  1. ByteArrayInputStream 可以从指定的字节数组中读取数据
  2. ByteArrayOutputStream 中提供了缓冲区可以存放数据(缓冲区大小可以在构造方法中设定,缺省为32),可以用 write() 方法向其中写入数据,然后用 toByteArray() 方法将缓冲区中的有效字节写到字节数组中去。size() 方法可以知道写入的字节数;reset() 可以丢弃所有内容。
  3. StringBufferInputStream 与 ByteArrayInputStream 相类似,不同点在于它是从字符缓冲区 StringBuffer 中读取16位的 Unicode 数据,而不是8位的字节数据(已被 StringReader 取代)
  • 顺序输入流

java.io 中提供了类 SequenceInputStream,使应用程序可以将几个输入流顺序连接起来。顺序输入流提供了将多个不同的输入流统一为一个输入流的功能,这使得程序可能变得更加简洁。

参考资料

  • 实验楼:JDK 核心 API
  • Java2实用教程 (第三版)_ 耿祥义,张跃平

Java.io 包(字节流)的更多相关文章

  1. java.io包中的字节流—— FilterInputStream和FilterOutputStream

    接着上篇文章,本篇继续说java.io包中的字节流.按照前篇文章所说,java.io包中的字节流中的类关系有用到GoF<设计模式>中的装饰者模式,而这正体现在FilterInputStre ...

  2. java.io包详细解说

    转自:http://hzxdark.iteye.com/blog/40133 hzxdark的博客 我不知道各位是师弟师妹们学java时是怎样的,就我的刚学java时的感觉,java.io包是最让我感 ...

  3. 1.java.io包中定义了多个流类型来实现输入和输出功能,

    1.java.io包中定义了多个流类型来实现输入和输出功能,可以从不同的角度对其进行分 类,按功能分为:(C),如果为读取的内容进行处理后再输出,需要使用下列哪种流?(G)   A.输入流和输出流 B ...

  4. Java:输入输出流 java.io包的层次结构

    1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读 ...

  5. Java源码解析——Java IO包

    一.基础知识: 1. Java IO一般包含两个部分:1)java.io包中阻塞型IO:2)java.nio包中的非阻塞型IO,通常称为New IO.这里只考虑到java.io包中堵塞型IO: 2. ...

  6. java IO的字节流和字符流及其区别

    1. 字节流和字符流的概念    1.1 字节流继承于InputStream    OutputStream,    1.2 字符流继承于InputStreamReader    OutputStre ...

  7. java.io 包下的类有哪些 + 面试题

    java.io 包下的类有哪些 + 面试题 IO 介绍 IO 是 Input/Output 的缩写,它是基于流模型实现的,比如操作文件时使用输入流和输出流来写入和读取文件等. IO 分类 传统的 IO ...

  8. java.io包下适配和装饰模式的使用

    如java.io.LineNumberInputStream(deprecated),是装饰模式(decorate)的实现: 如java.io.OutputStreamWriter,是适配器模式(ad ...

  9. 装饰者模式在JDK和Mybatis中是怎么应用的? java io包

    https://mp.weixin.qq.com/s/-bj71dBylRHRqiPorOpVyg 原创: 李立敏 Java识堂 3月10日 有一个卖煎饼的店铺找上了你,希望你能给她们的店铺开发一个收 ...

随机推荐

  1. 前端自动化Gulp工具常用插件

    npm init命令初始化当前文件夹后,在当前文件夹新建gulpfile.js文件.当前目录下的所有操作流都在gulpfile.js文件中定义. gulp自动化 gulp-uglify (JS压缩) ...

  2. Django models python3搭载mysql

    1    django默认支持sqlite,mysql, oracle,postgresql数据库.  <1> sqlite django默认使用sqlite的数据库,默认自带sqlite ...

  3. 推荐网站 explainshell.com

    ls 显示指定目录下的文件和目录,默认为当前目录. -a 显示所有文件及目录 (ls内定将文件名或目录名称开头为"."的视为隐藏档,不会列出) -l 除文件名称外,亦将文件型态.权 ...

  4. js文件加载太慢,JavaScript文件加载加速

    原文出自:https://blog.csdn.net/seesun2012 js脚本加载太慢,JavaScript脚本加载加速(亲测有效) 测试背景: JS文件大小:6.1kB 传统形式加载js文件: ...

  5. [javaSE] GUI(图形用户界面)

    java为gui提供的对象都在java.Awt和javax.Swing包中 Awt:抽象窗口工具包,依赖平台,调用系统的本地方法 Swing:完全由java实现的轻量级工具库 eclipse官方封装了 ...

  6. 【原】Java跨域以及实现原理

     前言:最近研究了一下跨域,主要是jsonp的实现,经过测试后总结如下: 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨 ...

  7. centos 6无法上外网

    1.先配置/etc/sysconfig/network-scripts/ifcfg-eth0 配置完成后能ping通内网.网关,但是上不了外网 DEVICE=eth0 HWADDR=:0C::FF:: ...

  8. unity3d之使用技巧

    知乎 project.hierarchy折叠打开全部文件夹——alt +方向键

  9. C#学习笔记-继承基本知识

    namespace Inheritance { class Program { static void Main(string[] args) { Dog dog = new Dog(); dog.A ...

  10. 原生canvas写的飞机游戏

    一个原生canvas写的飞机游戏,实用性不大,主要用于熟悉canvas的一些熟悉用法. 项目地址:https://github.com/BothEyes1993/canvas_game