第十一章:IO流

1.流的概念
流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以"流"的方式进行。设备可以是文件,网络,内存等

流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的流向是程序至设备,我们成为输出流,如果数据的流向是设备至程序称为输入流。

数据以二进制的形式在程序与设备之间流动传输,就想水在管道里流动一样,所以就把这种数据传输的方式称之为输入流输出流

思考:代码程序中要读取文件中的内容,需要使用什么流?代码程序中要向文件中写内容,又需要使用什么流?

2.流的分类
1)按照流的方向分为输入流和输出流
2)按照处理数据的单位不同分为字节流和字符流
字节流读取的最小单位是一个字节(1byte=8bit),而字符流一次可以读取一个字符(1char = 2byte = 16bit)
3)按照功能的不同分为节点流和处理流
节点流是可以"直接"从一个数据源中读写数据的流。
处理流也可以称为功能流或者包装流,它是可以对节点流进行封装的一种流,封装后可以增加节点流的功能。
例如:FileInputStream是一个节点流,可以直接从文件读取数据,而BufferedInputStream可以包装 FileInputStream,使得其有缓冲数据的功能。

4)除了以上三种分类外,还有其他的一些类型的:对象流、缓冲流、压缩流、文件流等等,其实这些都是节点流或者处理流的子分类。当然还可以分出来其他的流类型,如果有这样需要的话。

5)不管流的分类是多么的丰富和复杂,其根源来自于四个基本的父类
字节输入流:InputStream
字节输出流:OutputStream
字符输入流:Reader
字符输出流:Writer

注:这四个父类都是抽象类

3.字节流中的常用节点流
注:java中常用的io流都在java.io包中
1)InputStream
//从输入流中读取数据的下一个字节
//如果到达流的末尾则返回 -1
public abstract int read();
//把读到的字节存到字节数组b中,并返回本次读到了多少个字节
public int read(byte[] b){..}
//把读到的字节存到字节数组b中,同时指定开始存的位置以及最大字节数,并返回本次读到了多少个字节
public int read(byte[] b,int off,int len){..}

//返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数
public int available(){..}

//跳过此输入流中数据的 n 个字节
public long skip(long n){..}

//关闭此输入流并释放与该流关联的所有系统资源
public void close(){..}

//测试此输入流是否支持 mark 和 reset 方法
public boolean markSupported(){..}
//在此输入流中标记当前的位置
public void mark(int readlimit){..}
//将此流重新定位到最后一次对此输入流调用mark方法时的位置
public void reset(){..}

2)OutputStream
//将指定的字节写入此输出流
public abstract void write(int b);
//将字节数组b中的所有字节写入此输出流
public void write(byte[] b){..}
//将字节数组b中的字节写入此输出流,指定开始位置及最大字节数
public void write(byte[] b,int off,int len){..}

//刷新此输出流并强制写出所有缓冲的输出字节
public void flush(){..}

//关闭此输出流并释放与此流有关的所有系统资源
public void close(){..}

3)InputStream的子类和OutputStream的子类几乎都是成对出现的,一个负责读数据的工作,一个负责写数据的工作

4)System.out和System.in
System类的部分源码:
public final class System{
//标准输入流
public final static InputStream in = null;
//标准输出流。
public final static PrintStream out = null;
//标准错误输出流
public final static PrintStream err = null;

public static void setIn(InputStream in){..}
public static void setOut(PrintStream out){..}
public static void setErr(PrintStream err){..}
}

标准输入流会默认从控制台读取数据
标准输出流会默认把数据输出到控制台

System.out.println(System.in.getClass());
System.out.println(System.out.getClass());
输出结果为:
class java.io.BufferedInputStream
class java.io.PrintStream

5)ByteArrayInputStream和ByteArrayOutputStream
ByteArrayInputStream可以从数组中读取字节
ByteArrayOutputStream可以把字节写到对象中的缓冲区里面,其实就是一个字节数组

6)FileInputStream和FileOutputStream
FileInputStream可以读取文件中的字节
FileOutputStream可以向文件中写进去字节

7)PipedInputStream和PipedOutputStream
PipedInputStream管道字节输入流
PipedOutputStream管道字节输出流

注:使用时需要把俩个管道进行对接

8)ObjectInputStream和ObjectOutputStream
在序列化中要使用的对象输入流和对象输出流,之后再来使用测试

9)java.io.File类
File类型对象可以表示一个文件也可以表示一个目录.

4.字节流中的常用处理流
也可以称为功能流或者包装流,因为它是对节点流进行包装的一种流,包装后可以增加节点流的功能。但是处理流本身并不能直接读写数据

1)BufferedInputStream和BufferedOutputStream
可以给字节流中的节点流提供代码缓冲区的输入/输出流
2)DataInputStream和DataOutputStream
可以给字节流中的节点流提供输入/输出java中不同类型的数据
3)PrintStream
PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式

5.字符流
1)Reader
public int read(){..}
public int read(char[] cbuf){..}
public abstract int read(char[] cbuf, int off,int len){..}
//指定缓冲区
//@since 1.5
public int read(CharBuffer target){..}

abstract public void close();
public long skip(long n){..}

public boolean markSupported(){..}
public void mark(int readAheadLimit){..}
public void reset(){..}

//Tells whether this stream is ready to be read
public boolean ready(){..}

2)Writer
public void write(int c){..}
public void write(char cbuf[]){..}
abstract public void write(char cbuf[], int off, int len);
public void write(String str){..}
public void write(String str, int off, int len){..}

abstract public void flush();
abstract public void close();

//@since 1.5
//和out.write(c)的效果一样
public Writer append(char c){..}
public Writer append(CharSequence csq){..}
public Writer append(CharSequence csq, int start, int end){..}

3)CharArrayReader和CharArrayWriter
CharArrayReader可以读取字符数组中的内容
CharArrayWriter可以向字符数组中写内容

4)FileReader和FileWriter
FileReader读取文件内容的便捷类,InputStreamReader的子类
FileWriter写入文件内容的便捷类,OutputStreamWriter的子类

5)PipedReader和PipedReader
PipedReader管道字符输入流
PipedReader管道字符输出流

6)BufferedReader和BufferedWriter
这个俩个流属于处理流,它们本身并不能读取数据,它们的作用是包装在其他节点流上面,为其提供额外的功能

7)PrintWriter
一般会把BufferedReader和PrintWriter配合在一起使用,因为BufferedReader可以一次读一行字符串,而PrintWriter可以一次写一行字符串(自动换行)。

6.转换流
InputStreamReader和OutputStreamWriter是一对名字中既有Stream,又有Reader或Writer的流,因为它们是转换流,负责把一个字节流转换为字符流。所以它们是字节流和字符串之间的桥梁.
注:在把字节流转换为字符流的过程中,还可以指定字符编码,避免乱码的出现。

8.对象流
1)序列化和反序列化
Java中的序列化是指把Java对象转换为字节序列的过程
对象---序列化--->01010101
Java中的反序列化是指把字节序列恢复为Java对象的过程
01010101---反序列化--->对象

思考:为什么需要序列化和反序列化?

2)如何实现序列化和反序列化
使用对象流即可实现对象的序列化和反序列化
ObjectOutputStream类中的方法可以完成对象的序列化:
public final void writeObject(Object obj){..}

ObjectInputStream类中的方法可以完成对象的反序列化:
public final Object readObject(){..}

注:这俩个对象流都属于字节流

3)序列化的要求
只有实现了java.io.Serializable接口的类的对象才可以被序列化,否则序列化时会报错

思考:测试序列化版本号的作用是什么?

4)transient关键字
在对象序列化的时候,被transient修饰的属性的值,在序列化过程中是会被忽略掉的。

9.随机访问流
java.io.RandomAccessFile类
public class RandomAccessFile extends Object{..}
这是个特殊的流,它不属于之前那些流的体系。

这个流的既可以用来读文件,也可以用来给文件中写内容,并且该类中的方法可以用来定位文件中的位置:
public native void seek(long pos);

构造器中需要设置该流的操作模式:
//对文件只读
RandomAccessFile r = new RandomAccessFile(filePath,"r");
//对文件即可读又可写
//但是一旦确定了读或者写,那么就不能在变
RandomAccessFile rw = new RandomAccessFile(filePath,"rw");

java_day11_IO流的更多相关文章

  1. 使用C#处理基于比特流的数据

    使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型 ...

  2. HTML 事件(三) 事件流与事件委托

    本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...

  3. FILE文件流的中fopen、fread、fseek、fclose的使用

    FILE文件流用于对文件的快速操作,主要的操作函数有fopen.fseek.fread.fclose,在对文件结构比较清楚时使用这几个函数会比较快捷的得到文件中具体位置的数据,提取对我们有用的信息,满 ...

  4. java.IO输入输出流:过滤流:buffer流和data流

    java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...

  5. java 字节流与字符流的区别

    字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢?实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作 ...

  6. BZOJ 3504: [Cqoi2014]危桥 [最大流]

    3504: [Cqoi2014]危桥 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1407  Solved: 703[Submit][Status] ...

  7. java I/O流

    输入流(读取数据的流) BufferedInputStream---继承--->FileInputStream--继承--->InputStream------> (1)字节流操作中 ...

  8. Ford-Fulkerson 最大流算法

    流网络(Flow Networks)指的是一个有向图 G = (V, E),其中每条边 (u, v) ∈ E 均有一非负容量 c(u, v) ≥ 0.如果 (u, v) ∉ E 则可以规定 c(u, ...

  9. .NET基础拾遗(3)字符串、集合和流

    Index: (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基础 ...

随机推荐

  1. docker网络(3)

    docker网络介绍 大量的互联网应用服务需要多个服务组件,这往往需要多个容器之间通过网络通信进行相互配合. docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多个 host 的网络. ...

  2. B站动手学深度学习第十八课:seq2seq(编码器和解码器)和注意力机制

    from mxnet import nd h_forward = nd.array([1,2]) h_backward = nd.array([3,4]) h_bi = nd.concat(h_for ...

  3. JAVA 基础编程练习题15 【程序 15 排序】

    15 [程序 15 排序] 题目:输入三个整数 x,y,z,请把这三个数由小到大输出. 程序分析:我们想办法把最小的数放到 x 上,先将 x 与 y 进行比较,如果 x>y 则将 x 与 y 的 ...

  4. vue中如何编写可复用的组件?

    原文地址 Vue.js 是一套构建用户界面的渐进式框架.我们可以使用简单的 API 来实现响应式的数据绑定和组合的视图组件. 从维护视图到维护数据,Vue.js 让我们快速地开发应用.但随着业务代码日 ...

  5. docker部署jar、war包方法

    一.将war包放入容器 1.# docker imagesREPOSITORY                         TAG                 IMAGE ID         ...

  6. ImportError: libpython3.6m.so.1.0: cannot open shared object file: No such file or directory

    该错误原因是libpython3.6m.so.1.0不存在 解决方案 1.查看/usr/lib/x86_64-linux-gnu/目录下是否存在libpython3.m.so.1.0文件,或者直接全盘 ...

  7. APP安全测试要点

    APP面临的威胁 APP评估思路 APP自动化检测思路 安全测试要点 证书和签名 将apk文件更名为zip 使用unzip解压 META-INF中包含签名文件和真正的CERT.RSA文件(公钥证书自签 ...

  8. 数据结构与算法-stack

    栈的本质是一种线性表,特殊的一种线性表 基本概念 概念 栈是一种特殊的线性表 栈仅能在线性表的一端进行操作 栈顶(Top):允许操作的一端 栈底(Bottom):不允许操作的一端 stack是一种线性 ...

  9. 学习笔记:html学习之一:html基本标记

    1. 概论 一个完整的 HTML 文档必须包含 3 个部分: 一个由 元素定义的文档版本信息. 一个由 定义各项声明的文档头部, 作为各种声明信息的包含元素出现在文档的顶端,并且要先于 出现. 一个由 ...

  10. Django2.2 数据库的模块model学习笔记

    一.前言 为什么选用Django2.2,因为从2019年下半年起Django2.2逐渐成为长期支持版本,官网也有数据,所以当然选用维护时间长的版本 二.models的建立 Django的models也 ...