Java IO —— 战斗的号角已经吹响

Java IO —— 战斗的号角已经吹响


目录

1. Java IO概述

2. File

3. InputStream

4. OutputStream 

5. Filter模式

6. ZipInputStream

 7. 资源文件和序列化&反序列化

8. Reader 

9. Writer 


1. Java IO概述

同步和异步(这里只介绍java.io

  • JDK 提供的java.io是同步IO
  • JDK提供的java.nio是异步IO

Java.io的结构图

Java IO —— 战斗的号角已经吹响_第1张图片

总结

  • IO流是一种流式的数据输入 / 输出模型
  • 二进制数据以byte为最小单位在InputStream / OutputStream中单向流动
  • 字符数据以char为最小单位在Reader / Writer中单向流动
  • JDK的java.io包提供了同步IO宫嗯
  • Java的IO流的接口和实现是分离的:

字节流接口:InputStream / OutputStream

字符流接口:Reader / Writer


2. File

java.io.File表示文件以通的一个文件或目录:

  • 构造方法:File(String pathname)

绝对路径、相对路径:

Java IO —— 战斗的号角已经吹响_第2张图片

  • String getPath() / getAbsolutePath() / getCanonicalPath() —— 规范目录

  • boolean isFile():是否是文件
  • boolean isDirectory():是否是目录

当File对象表示一个文件时(isFile()==true):

  • boolean canRead():是否允许读取该文件
  • boolean canWrite():是否允许写入该文件
  • boolean canExecute():是否允许运行该文件

  • long length():获取文件大小
  • boolean createNewFile():创建一个新文件
  • static boolean createTempFile(String prefix,String suffix):创建一个临时文件
  • boolean delete():删除该文件
  • void deleteOnExit():在JVM退出时删除该文件

  • String[ ] list():列出目录下的文件和子目录名
  • File[ ] listFiles():列出目录下所有的子目录名和文件
  • File[ ] listFile(FileFilter filter)
  • File[ ] listFiles(FilenameFilter filter)

Java IO —— 战斗的号角已经吹响_第3张图片

  • boolean mkdir():创建该目录
  • boolean mkdirs():创建该目录,并在必要时将不存在的父目录也创建出来
  • boolean delete():删除该目录

  • 测试代码:

Java IO —— 战斗的号角已经吹响_第4张图片

总结(File对象表示一个文件或者目录)

  • 创建File对象本身不涉及IO操作
  • 获取路径 / 绝对路径 / 规范路径:getPath() / getAbsolutePath() / getCanonicalPath()
  • 可以获取目录的文件和子目录
  • 通过File对象可以创建或删除文件和目录

3. InputStream

java.io.InputStream是所有输入流的超类:

  • abstract int read():读取下一个字节并返回字节(0~255);如果已读到末尾返回-1
  • int read(byte[ ] b):读取若干字节并填充到byte[ ]数组,返回读取的字节数
  • int read(byte[ ] b,int off,int len)
  • void close():关闭输入流

完整的读取一个InputStream所有字节:

Java IO —— 战斗的号角已经吹响_第5张图片

利用缓冲区一次读取多个字节:(推荐

Java IO —— 战斗的号角已经吹响_第6张图片

read()方法是阻塞(blocking)的:

FileInputStream可以从文件获取输入流:

ByteArrayInputStream可以在内存中模拟一个InputStream:——测试中经常使用

Java IO —— 战斗的号角已经吹响_第7张图片

总结

  • InputStream定义了所有输入流的超类
  • FileInputStream实现了文件流输入
  • ByteArrayInputStream在内存中模拟一个字节流输入
  • 使用try(reasourse)保证InputStream正确关闭

4. OutputStream 

java.io.OutputStream是所有输出流的超类:

  • abstract write(int b):写入一个字节
  • void write(byte[ ] b)
  • void write(byte[ ] b,int off,int len)
  • void close()
  • void flush():将缓冲区的内容输出

write()方法是阻塞(blocking)的:

FileOutputStream可以输出到文件:

ByteArrayOutputStream可以在内存中模拟一个OutputStream:

Java IO —— 战斗的号角已经吹响_第8张图片

总结

  • OutputStream定义了所有输出流的超类
  • FileOutputStream实现了文件流输出
  • ByteArrayOutputStream在内存中模拟一个字节流输出
  • 使用try(resource)保证OutputStream正确关闭

5. Filter模式

 JDK把InputStream分为两类:

  • 直接提供数据的InputStream:FileInputStream、 ByteArrayInputStream、 ServletInputStream...
  • 提供额外附加功能的InputStream:BufferedInputStream、 DigestInputStream、 CipherInputStream...
  • 使用InputStream时,根据情况组合:

Java IO —— 战斗的号角已经吹响_第9张图片

  • 组合功能而非继承的设计模式称为Filter模式或者Dectorator模式
  • 通过少量的类实现了各种功能的组合

Java IO —— 战斗的号角已经吹响_第10张图片Java IO —— 战斗的号角已经吹响_第11张图片

  • 代码测试:—— 利用Filter自定义创建Stream

Java IO —— 战斗的号角已经吹响_第12张图片

Java IO —— 战斗的号角已经吹响_第13张图片

总结

  • Java IO使用Filter模式为InputStream / OutputStream增加功能
  • 可以把一个InputStream和任意FilterInputStream组合
  • 可以把一个OutputStream和任意FilterOutputStream组合
  • Filter模式可以在运行期动态增加功能(又称Dectorator模式)

6. ZipInputStream

ZipInputStream是一种FilterInputStream:

  • 可以直接读取Zip的内容

Java IO —— 战斗的号角已经吹响_第14张图片

  • ZipInputStream直接读取Zip

Java IO —— 战斗的号角已经吹响_第15张图片

  • ZipInputStream直接写入Zip的内容

Java IO —— 战斗的号角已经吹响_第16张图片

  • 代码实现:

Java IO —— 战斗的号角已经吹响_第17张图片

总结

  • ZipInputStream可以读取Zip格式的流
  • ZipOutputStream可以把数据写入Zip
  • ZipInputStream / ZipOutputStream都是FilterInputStream / FilterOutputStream
  • 配合FileInputStream和FileOutputStream就可以读写Zip文件

 7. 资源文件和序列化&反序列化

Java存放.class的目录或jar包也可以包含任意其他类型的文件:

  • .properties, .txt, .jpg, .mov, ...

从classpath读取文件可以避免不同环境下文件路径不一致的问题:

总结

  • 把资源存储在classpath中可以避免文件路径依赖
  • Class对象的getResourceAsStream()可以从classpath读取资源
  • 需要检查返回的InputStream是否为null

序列化

序列化是指把一个Java对象变成二进制内容( byte[ ] )

  • 序列化后可以把byte[ ]保存到文件中
  • 序列化后可以把byte[ ] 通过网络传输 

一个Java对象要能序列化要能序列化,必须实现Serializable接口:

  • Serializable接口没有定义任何方法
  • 空接口被称为“标记接口Marker Interface”

反序列化

反序列化是指把一个二进制内容(byte[ ])变成Java对象

  • 反序列化后可以从文件读取byte[ ] 并变为Java对象
  • 反序列化后可以从网络读取byte[ ] 并变为Java对象

注:反序列化由JVM直接构造Java对象,不调用构造方法

Java IO —— 战斗的号角已经吹响_第18张图片

反序列化是根据serialVersionUID来识别匹配的对象,如果更改serialVersionUID会报java.io.InvalidClassException异常。

ObjectOutputStream&ObjectIntputStream

ObjectOutputStream就是一个序列化类,负责把一个Java对象写入二进制流:

ObjectIntputStream负责从二进制流读取一个Java对象:

readObject()可能抛出的异常:

  • ClassNotFoundException:没有找到对应的Class
  • InvalidClassException:Class不匹配

总结

 

  • 可序列化的Java对象必须实现java.io.Serializable接口
  • 类似Serializable这样的空接口被称为“标记接口”
  • 反序列化时不调用构造方法
  • 可设置serialVersionUID作为版本号(非必需)
  • Java的序列化机制仅适用于Java,如果需要与其他语言交换数据必须使用通用的序列化方法,如JSON 

8. Reader 

java.io.Reader和java.io.InputStream的区别:

Java IO —— 战斗的号角已经吹响_第19张图片

java.io.Reader是所有字符输入流的超类:

  • int read()

读取下一个字符,并返回字符

如果已读到末尾,返回-1

  • int read(char[ ] c)
  • int read(char[ ] c,int off, int len):指定char[ ]数组的偏移量和最大填充数
  • void close()

利用缓冲区一次读取多个字符:

Java IO —— 战斗的号角已经吹响_第20张图片

FileReader可以从文件获取Reader:

CharArrayReader可以在内存中模拟一个Reader:

Java IO —— 战斗的号角已经吹响_第21张图片

总结

  • Reader定义了所有字符输入流的超类
  • FileReader实现了文件字符流输入
  • CharArrayReader在内存中模拟一个字符流输入
  • Reader是基于InputStream构造的:

FileReader使用系统默认编码,无法指定编码;可以通过InputStreamReader指定编码

  • 使用try(resource)保证Reader正确关闭

9. Writer 

java.io.Writer和java.io.OutputStream的区别:

Java IO —— 战斗的号角已经吹响_第22张图片

java.io.Writer是所有字符输入流的超类:

  • void write(int c)
  • void write(char[ ] c)
  • void write(char[ ] c,int off,int len)
  • void write(String s)
  • void flush()
  • void close()  

一次写入多个字符:

Java IO —— 战斗的号角已经吹响_第23张图片

write()方法是阻塞blocking的:

FileWriter可以从文件获取Writer:

CharArrayWriter可以在内存中模拟一个Writer:

Java IO —— 战斗的号角已经吹响_第24张图片

Writer实际上是基于OutputStream构造的:

  • FileWriter内部持有一个FileOutputStream
  • Writer可以通过OutputStream构造

总结

  • Writer定义了所有字符输出流的超类
  • FileWriter实现了文件字符流输出
  • CharArrayWriter在内存中模拟一个字符流输入
  • Writer是基于OutputStream构造的:

FileWriter使用系统默认编码,无法指定编码

可以通过OutputStreamWriter指定编码

  • 使用try(resource)保证Writer正确关闭


 java io流的拓展还是挺广的,实际应用深度想必会更深,多看看java API收获也是不少的,加油!也要注意身体哟,每天花30分钟健健身挺不错的。晚安~~~~

                                          谢谢阅读             ----知飞翀

你可能感兴趣的:(JavaSE学习笔记)