IO
相关概念
一输入输出 |
数据源 Source 程序 Program 目标 Destination 原理: 常见数据源与目标媒介:文件、管道、网络连接、内存缓存、标准输入、标准输出、错误输出 |
二流 |
流Stream:连续的数据流 原理: 用途: 文件访问、 网络访问、 内存缓存访问 、线程内部通信(管道)、 缓冲、 过滤、 解析、 读写文本 (Readers / Writers) 、读写基本类型数据 (long, int etc.) 、读写对象 区别: 数组:有索引 流 :无索引 |
IO文件 —RandomAccessFile随即存取 — 基础流与组合流 —基础流InputStream —组合流BufferedInputStream IO管道 —当使用两个相关联的管道流时,务必将它们分配给不同的线程。read()方法和write()方法调用时会导致流阻塞,这意味着如果你尝试在一个线程中同时进行读和写,可能会导致线程死锁。 IO网络 —当两个进程之间建立了网络连接之后,他们通信的方式如同操作文件一样:利用InputStream读取数据,利用OutputStream写入数据。换句话来说,Java网络API用来在不同进程之间建立网络连接,而Java IO则用来在建立了连接之后的进程之间交换数据。 Buffered Filter FilterReader |
IO知识点
1.流的概念 |
概念:一组有顺序的,有起点和终点的字节集合。 (数据传输的总称或抽象) 表现:数据在两设备之间的传输。 本质:数据传输 (根据数据传输特性将流抽象为各种类,直观操作数据) |
2.分类 |
标准1:处理数据单位 【处理数据类型】 字符流:处理单元为2个字节的Unicode字符。 操作字符、字符数组、或字符串 处理字符类型数据 — 字符流处理类负责将外部的其他编码的字符流和 java 内 Unicode 字符流之间的转换 — [本质:基于字节流,查询码表] 字节流:处理单元为1个字节byte. 操作字节、字节数组 处理所有类型数据 —字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的; —而字符流在操作的时候下后是会用到缓冲区的,是通过缓冲区来操作文件 标准2:数据流向 (程序\设备 \文件\内存\网络 数据源—>目的地) 【方向性】 —输入流: 源数据输入内存 InputStream 对应Reader —输出流: 内存输出目的地 OutputStream 对应Writer 标准3:功能 节点流:从特定的数据源读写数据. 直接操作文件、网络等的流。FileInputStream和FileOutputStream。直接从文件中读取或往文件中写入字节流 处理流:"连接"在已存在的流(节点流或处理流),通过对数据的处理为程序提供更强大的读写。 过滤流:使用一个已经存在的输入流或输出流连接创建,对节点流进行一系列的包装。 |
3.结构 |
Java所有的流类位于java.io包,别继承字以下四种抽象流类型 |
public static void main(String[] args) throws IOException { // 节点流FileOutputStream直接以A.txt作为数据源操作 数据源 节点流FileOutputStream 输出内存 FileOutputStream fileOutputStream = new FileOutputStream("A.txt"); 过滤流BufferedOutputStream 输出缓存 // 过滤流BufferedOutputStream进一步装饰节点流,提供缓冲写 BufferedOutputStream bufferedOutputStream = new BufferedOutputStream( fileOutputStream); // 过滤流DataOutputStream进一步装饰过滤流,使其提供基本数据类型的写 处理流DataOutputStream提供基本数据类型 DataOutputStream out = new DataOutputStream(bufferedOutputStream); out.writeInt(3); out.writeBoolean(true); //输出—字符 out.flush(); //冲刷—缓存, out.close(); //关闭—处理输出流 // 此处输入节点流,过滤流正好跟上边输出对应,读者可举一反三 DataInputStream in = new DataInputStream(new BufferedInputStream( new FileInputStream("A.txt"))); System.out.println(in.readInt()); System.out.println(in.readBoolean()); in.close(); } |
一.结构:
数据单位 | 数据流向 [抽象类] |
数据处理能力 | 数据处理功能 | |
IO流 | 字符流 (byte=8bit) 数据单位是字节 |
Reader (输入) |
节点流 | FileReader |
处理流 | InputStreamReader转换\BufferedReader缓冲 |
|||
Writer (输出) |
节点流 | FileWriter | ||
处理流 | OutputStreamReader转换BufferedWriter缓冲 | |||
字节流 (2byte=16bit) 数据单位是字符 |
InputStream (输入) |
节点流 | FileInputStream | |
处理流 | ByteArrayInputStream字节数组缓冲区 | |||
OutputStream (输出) |
节点流 | FileOutputStream | ||
处理流 | ByteArrayOutputStream字节数组缓冲区 |
详解:
一.继承自InputStream/OutputStream的流都是用于向程序中输入/输出数据,且数据的单位都是字节(byte=8bit),如图,深色的为节点流,浅色的为处理流。 |
二.继承自Reader/Writer的流都是用于向程序中输入/输出数据,且数据的单位都是字符(2byte=16bit),如图,深色的为节点流,浅色的为处理流。 |
三.IO类介绍 |
节点流 |
— 字符流:FileReader/FileWriter — 字节流:FileInputStream/FileOutputStream |
处理流 使用已经存在的节点流来构造,提供缓冲:读写[基本数据类型、对象]、缓存、转换、 |
—缓冲流:缓冲—读写,提高读写效率 —字节缓冲流:BufferedInputStream/BufferedOutputStream —字符缓冲流:BufferedReader/BufferedWriter 【1.字符缓冲流:提供读取和写入一行的方法ReadLine和NewLine方法。】 【2.缓冲流输出:数据先写入内存,使用flush方法,再到硬盘。在使用字符缓冲流时,要先flush,然后再close】 —转换流: 转换—字节数据与字符数据 —适用条件:流操作的数据需要编码或解码、当字节和字符之间有转换动作时 —仅有字符流:InputStreamReader/OutputStreamWriter 【InputStreamReader需要与InputStream“套接”,OutputStreamWriter需要与OutputStream“套接”】 —数据流:读写—基本数据类型 —DataInputStream和DataOutputStream分别继承自InputStream和OutputStream 【DataInputStream需要与InputStream“套接”,DataOutputStream需要与OutputStream“套接”】 —对象流:读写—对象 —ObjectInputStream和ObjectOutputStream 【条件:要写出的对象必须实现Serializable接口,声明可以序列化。否则,不能用对象流读写。】 —关键字transient,由于修饰实现了Serializable接口的类内的属性,被该修饰符修饰的属性,以对象流的方式输出时,会被忽略。 |
二、应用
File file=new File("aaa.txt"); |
将字节输出流转化为字符输出流 Writer out=new OutputStreamWriter(new FileOutputStream(file)); out.write("hello"); out.close(); 将字节输入流变为字符输入流 Reader read=new InputStreamReader(new FileInputStream(file)); char[] b=new char[100]; int len=read.read(b); System.out.println(new String(b,0,len)); |
三、序列化
序列化serialization |
1\定义:把对象转换为字节序列的过程 —将对象的状态信息转换为可以存储或传输的形式的过程。 —在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。 —序列化使其他代码可以查看或修改,那些不序列化便无法访问的对象实例数据。即代码执行序列化需要特殊的权限 2\目的: 1、以某种存储形式使自定义对象持久化; 2、将对象从一个地方传递到另一个地方。 3、使程序更具维护性。 把对象保存到文件里--->对象的序列化 作用:永久保存数据(持久化) 可以在网络之间传输数据 如何实现?ObjectOutputStream:对象输出流 构造方法 new ObjectOutputStream(OuputStream out) 方法:writeObject():把对象写到文件里 注意:要序列化的对象--》类一定要实现Serializable接口
Serializable接口 仅仅只是一中标识,表示这个类的对象可以被序列化的 否则异常:java.io.NotSerializableException: 类里的属性必须要全部可序列化(包含其他类) 静态的属性也是不能被序列化的(内存存储只有一份) |
反序列化 |
1\定义:把字节序列恢复为对象的过程 2\目的: 1、以某种存储形式使自定义对象持久化; 2、将对象从一个地方传递到另一个地方。 3、使程序更具维护性。 把文件里的数据读取出来形成对象--->反序列化 ObjectInputStream:对象输入流 构造方法:new ObjectInputStream(InputStream in) 方法 readObject():读取对象 (强转) |
JDK API: java.io.ObjectOutputStream java.io.ObjectInputStream |
原理: 只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。 |