流的概念

按流的方向分类:

  1. 输入流:数据流向是数据源到程序(以InputStream、Reader结尾的流)。

  2. 输出流:数据流向是程序到目的地(以OutPutStream、Writer结尾的流)。


按处理的数据单元分类:

  • 字节流:以字节为单位获取数据,命名上以 Stream 结尾的流一般是字节流,如FileInputStream、FileOutputStream
  • 字符流:以字符为单位获取数据,命名上以 Reader/Writer 结尾的流一般是字符流,如FileReader、FileWriter

按处理对象不同分类:

  • 节点流:可以直接从数据源或目的地读写数据,如 FileInputStream、FileReader、DataInputStream等。
  • 处理流:不直接连接到数据源或目的地,是”处理流的流”。通过对其他流的处理提高程序的性能,如 BufferedInputStream、BufferedReader 等。处理流也叫包装流。

  • 节点流处于IO操作的第一线,所有操作必须通过它们进行
  • 处理流可以对节点流进行包装,提高性能或提高程序的灵活性

IO 流类体系

InputStream / OutputStream

表示字节输入输出流的所有类的父类。
子类:

  • FileInputStream / FileOutputStream: 节点流,以字节为单位 【直接】操作『文件』
  • ByteArrayInputStream / ByteArrayOutputStream:节点流,…操作『字节数组对象』
  • ObjectInputStream / ObjectOutputStream:处理流,…『对象』
  • DataInputStream / DataOutputStream:处理流,…『基本数据类型与字符串类型』

Reader / Writer

表示用于读取/写入的字符流抽象类,数据单位为字符.
子类:

  • FileReader / FileWriter:节点流,以字符为单位直接操作『文本文件』(只能读写文本文件
  • BufferedReader / BufferedWriter:处理流,将Reader/Writer对象进行包装,增加缓存功能,提升读写效率
  • BufferedInputStream / BufferedOutputStream:处理流,将InputStream/OutputStream对象包装,…
  • InputStreamReader / OutputStreamWriter:处理流,将字节流对象转化为字符流对象
  • PrintStream:处理流,将OutputStream进行包装,可以方便地输出字符

文件字节流

fis = new FileInputStream("a.txt");
while ((tmp = fis.read()) != -1)
sb.append((char) tmp);
... FileOutputStream fos = null;
String string = "i am writing.";
try {
fos = new FileOutputStream("a.txt", true); // true表示追加文件末尾
byte[] bytes = string.getBytes();
fos.write(bytes); // 直接将字符数组写入文件

文件字符流

字节流不能很好的处理Unicode字符,经常会出现“乱码”现象,一般使用字符流处理文本文件。

FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("a.txt");
fw = new FileWriter("./c.txt");
char[] buffer = new char[1024]; // 缓存数组
int len = 0;
while ((len = fr.read(buffer)) != -1)
fw.write(buffer, 0, len); } catch (Exception e) {...

缓冲字节流

Java缓冲流本身并不具有IO流的读取与写入功能,只是在别的流(节点流或其他处理流)上加上缓冲功能提高效率,就像是把别的流包装起来一样,因此缓冲流是一种处理流(包装流)。

因为缓冲流是先将数据缓存起来,然后当缓存区存满后或者手动刷新时再一次性的读取到程序或写入目的地。

// 使用缓冲流实现文件的高效率复制
FileInputStream fis = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
String srcPath = "/home/cenjw/Downloads/ideaIU-2019.3.5.tar.gz";
String destPath = "/home/cenjw/idea-package.tar.gz";
try {
fis = new FileInputStream(srcPath);
fos = new FileOutputStream(destPath);
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
int t = 0;
long start = System.currentTimeMillis();
while ((t = bis.read()) != -1)
bos.write(t);
long end = System.currentTimeMillis();
System.out.println(end - start);

缓冲字符流

FileReader fr = null;
BufferedReader br = null;
FileWriter fw = null;
BufferedWriter bw = null; try {
fr = new FileReader("a.txt");
fw = new FileWriter("./d.txt");
br = new BufferedReader(fr);
bw = new BufferedWriter(fw);
String tmpStr = "";
while ((tmpStr = br.readLine()) != null) {
bw.write(tmpStr);
bw.newLine();
}
  1. readLine()方法是BufferedReader特有的方法,可以对文本文件进行更加方便的读取操作。

  2. 写入一行后要记得使用newLine()方法换行。

字节数组流

ByteArrayInputStream和ByteArrayOutputStream经常用在需要流和数组之间转化的情况!
即,FileInputStream是把文件当做数据源。ByteArrayInputStream则是把内存中的”某个字节数组对象”当做数据源。

// 字符串转变为字节数组
byte[] bytes = "hello world".getBytes();
ByteArrayInputStream bais = null;
StringBuilder sb = new StringBuilder();
try {
int tmp = 0;
int cnt = 0;
bais = new ByteArrayInputStream(bytes);
while ((tmp = bais.read()) != -1) {
sb.append((char) tmp);
cnt++;
}

数据流

数据流将**“基本数据类型与字符串类型”作为数据源,从而允许程序以与机器无关的方式从底层输入输出流中操作Java基本数据类型与字符串类型。

DataInputStreamDataOutputStream 是处理流,可以对其他节点流或处理流进行包装,增加一些更灵活、更高效的功能。

转换流

InputStreamReader/OutputStreamWriter 用来实现将字节流转化成字符流

System.in字节流对象,代表键盘的输入,按行接收用户的输入时,必须用到缓冲字符流 BufferedReader 特有的方法readLine(),但在创建BufferedReader的构造方法的参数必须是一个Reader对象,因此需要用到转换流InputStreamReader

System.out 也是字节流对象,代表输出到显示器,按行读取用户的输入后,并且要将读取的一行字符串直接显示到控制台,就需要用到字符流的 write(String str) 方法,所以我们要使用OutputStreamWriter将字节流转化为字符流。

// 创建字符输入输出流
BufferedReader br = null;
BufferedWriter bw = null;
try {
// 使用转换流将 字节流转为字符流
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out)); String str = br.readLine();
while (! "exit".equals(str)) {
bw.write(str);
bw.newLine();
bw.flush();
str = br.readLine();
}
...

序列化与反序列化

把Java对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为Java对象的过程称为对象的反序列化。

对象序列化的作用:

  • 持久化: 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中,比如:休眠的实现。以后服务器session管理,hibernate将对象持久化实现。
  • 网络通信:在网络上传送对象的字节序列。比如:服务器之间的数据通信、对象传递。

序列化涉及的类和接口

ObjectOutputStream 代表对象输出流,它的 writeObject(Object obj) 方法可对参数指定的 obj 对象进行序列化,把得到的字节序列写到一个目标输出流中。
ObjectInputStream 代表对象输入流,它的readObject() 方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

只有实现了Serializable接口的类的对象才能被序列化。 Serializable接口是一个空接口,只起到标记作用。

FileOutputStream fos = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
FileInputStream fis = null;
try {
Person person = new Person(22, true, "jayvee");
// 通过ObjectOutputStream将Person对象的数据写入到文件,即序列化
fos = new FileOutputStream("a.txt");
oos = new ObjectOutputStream(fos);
oos.writeObject(person);
oos.flush();
// 反序列化
fis = new FileInputStream("a.txt");
ois = new ObjectInputStream(fis);
Person p = (Person) ois.readObject();
System.out.println(p);
...
// 实现Serializable接口后,Person对象才能被序列化
class Person implements Serializable {
// 添加序列化ID,它决定着是否能够成功反序列化!
private static final long serialVersionUID = 1L;

装饰器模式

笔记参考:https://www.sxt.cn/Java_jQuery_in_action/ten-javaio-streamclass.html
IO流体系图:https://blog.csdn.net/u010145219/article/details/89792877

Java IO 技术的更多相关文章

  1. Java IO 技术之基本流类

    流式IO 流(Stream)是字节的源或目的.         两种基本的流是:输入流(Input Stream)和输出流(Output Stream).可从中读出一系列字节的对象称为输入流.而能向其 ...

  2. 深入分析Java Web技术(2) IO

    IO是当今Web面临的主要问题之一,可以说,大部分web应用的瓶颈都是IO的瓶颈. Java的IO类是java.io.它包含有80多个类,分为4大部分: 基于字节操作: InputStream,Out ...

  3. [19/03/29-星期五] IO技术_File(文件)类(可操作文件,不能操作其里边内容,位于Java.io 包中)&递归遍历

    一.概念 java.io.File类:代表文件和目录. 在开发中,读取文件.生成文件.删除文件.修改文件的属性时经常会用到本类. 以pathname为路径创建File对象,如果pathname是相对路 ...

  4. Java基础之IO技术(一)

    ---恢复内容开始--- Java基础中的IO技术可谓是非常重要,俗话说的好,万丈高楼起于垒土之间.所以学习Java一定要把基础学好,今天我们来学习IO技术的基础. IO无非就是输入与输出,而其中处理 ...

  5. 【Java】IO技术的使用——用IO实现大文件的复制

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827481.html 用IO进行文件复制,实质就是用FileInputStream链接要复制的文件,按一定规模 ...

  6. (转)java缓存技术,记录

    http://blog.csdn.net/madun/article/details/8569860 最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇 ...

  7. JAVA缓存技术

    介绍 JNotify:http://jnotify.sourceforge.net/,通过JNI技术,让Java代码可以实时的监控制定文件夹内文件的变动信息,支持Linux/Windows/MacOS ...

  8. Netty学习二:Java IO与序列化

    1 Java IO 1.1 Java IO 1.1.1 IO IO,即输入(Input)输出(Output)的简写,是描述计算机软硬件对二进制数据的传输.读写等操作的统称. 按照软硬件可分为: 磁盘I ...

  9. JAVA IO 序列化与设计模式

    ➠更多技术干货请戳:听云博客 序列化 什么是序列化 序列化:保存对象的状态 反序列化:读取保存对象的状态 序列化和序列化是Java提供的一种保存恢复对象状态的机制 序列化有什么用 将数据保存到文件或数 ...

随机推荐

  1. 额外空间复杂度O(1) 的二叉树遍历 → Morris Traversal,你造吗?

    开心一刻 一天,有个粉丝遇到感情方面的问题,找我出出主意 粉丝:我女朋友吧,就是先天有点病,听不到人说话,也说不了话,现在我家里人又给我介绍了一个,我该怎么办 我:这个问题很难去解释,我觉得一个人活着 ...

  2. Sentry 开发者贡献指南 - 配置 PyCharm

    概述 如果您使用 PyCharm 进行开发,则需要配置一些内容才能运行和调试. 本文档描述了一些对 sentry 开发有用的配置 配置 Python 解释器:(确保它是 venv 解释器)例如 ~/v ...

  3. 《剑指offer》面试题37. 序列化二叉树

    问题描述 请实现两个函数,分别用来序列化和反序列化二叉树. 示例:  你可以将以下二叉树: 1 / \ 2 3 / \ 4 5 序列化为 "[1,2,3,null,null,4,5]&quo ...

  4. unity3d发布安卓出错plese set the package name

    发布时报错 参考https://forum.unity.com/threads/where-is-package-name-setting.318839/ 参考https://answers.unit ...

  5. 【自写信息搜集工具】ThunderSearch开发原理解析

    前段时间结合zoomeye的开发文档做了个简易的信息搜集工具ThunderSearch[项目地址 / 博客地址],这次来讲讲具体的实现原理和开发思路 首先要能看懂开发文档,https://www.zo ...

  6. X000001

    一些相互无关联的题目的集合 都是码量不大,略有思维难度的题 做起来还是很舒适的 P6312 [PA2018]Palindrom 空间限制很小,不足以存下整个字符串,故暴力判断不可行. 考虑使用字符串哈 ...

  7. bom-location

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. AFNetWorking 文件上传 By-H罗

    一.文件上传(图片,音频,视频,文本等)(不带进度) /** * 文件上传 导入 #import "AFNetworking.h" * @param filePath 上传文件本地 ...

  9. IOS tableView 滑动删除与排序功能

    // // ViewController.m // 0429 // // Created by apple on 15/4/29. // Copyright (c) 2015年 gense. All ...

  10. CheckStyle使用手册(一)

    介绍 CheckStyle是SourceForge下的一个项目,提供了一个帮助JAVA开发人员遵守某些编码规范的工具.它能够自动化代码规范检查过程,从 而使得开发人员从这项重要,但是枯燥的任务中解脱出 ...