Java IO —— 战斗的号角已经吹响
目录
1. Java IO概述
同步和异步(这里只介绍java.io)
- JDK 提供的java.io是同步IO
- JDK提供的java.nio是异步IO
Java.io的结构图
总结
- 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)
绝对路径、相对路径:
- 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)
- boolean mkdir():创建该目录
- boolean mkdirs():创建该目录,并在必要时将不存在的父目录也创建出来
- boolean delete():删除该目录
- 测试代码:
总结(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所有字节:
利用缓冲区一次读取多个字节:(推荐)
read()方法是阻塞(blocking)的:
FileInputStream可以从文件获取输入流:
ByteArrayInputStream可以在内存中模拟一个InputStream:——测试中经常使用
总结
- 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:
总结
- OutputStream定义了所有输出流的超类
- FileOutputStream实现了文件流输出
- ByteArrayOutputStream在内存中模拟一个字节流输出
- 使用try(resource)保证OutputStream正确关闭
5. Filter模式
JDK把InputStream分为两类:
- 直接提供数据的InputStream:FileInputStream、 ByteArrayInputStream、 ServletInputStream...
- 提供额外附加功能的InputStream:BufferedInputStream、 DigestInputStream、 CipherInputStream...
- 使用InputStream时,根据情况组合:
- 组合功能而非继承的设计模式称为Filter模式或者Dectorator模式
- 通过少量的类实现了各种功能的组合
- 代码测试:—— 利用Filter自定义创建Stream
总结
- Java IO使用Filter模式为InputStream / OutputStream增加功能
- 可以把一个InputStream和任意FilterInputStream组合
- 可以把一个OutputStream和任意FilterOutputStream组合
- Filter模式可以在运行期动态增加功能(又称Dectorator模式)
6. ZipInputStream
ZipInputStream是一种FilterInputStream:
- 可以直接读取Zip的内容
- ZipInputStream直接读取Zip
- ZipInputStream直接写入Zip的内容
- 代码实现:
总结
- 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对象,不调用构造方法
反序列化是根据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.Reader是所有字符输入流的超类:
- int read()
读取下一个字符,并返回字符
如果已读到末尾,返回-1
- int read(char[ ] c)
- int read(char[ ] c,int off, int len):指定char[ ]数组的偏移量和最大填充数
- void close()
利用缓冲区一次读取多个字符:
FileReader可以从文件获取Reader:
CharArrayReader可以在内存中模拟一个Reader:
总结
- Reader定义了所有字符输入流的超类
- FileReader实现了文件字符流输入
- CharArrayReader在内存中模拟一个字符流输入
- Reader是基于InputStream构造的:
FileReader使用系统默认编码,无法指定编码;可以通过InputStreamReader指定编码
- 使用try(resource)保证Reader正确关闭
9. Writer
java.io.Writer和java.io.OutputStream的区别:
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()
一次写入多个字符:
write()方法是阻塞blocking的:
FileWriter可以从文件获取Writer:
CharArrayWriter可以在内存中模拟一个Writer:
Writer实际上是基于OutputStream构造的:
- FileWriter内部持有一个FileOutputStream
- Writer可以通过OutputStream构造
总结
- Writer定义了所有字符输出流的超类
- FileWriter实现了文件字符流输出
- CharArrayWriter在内存中模拟一个字符流输入
- Writer是基于OutputStream构造的:
FileWriter使用系统默认编码,无法指定编码
可以通过OutputStreamWriter指定编码
使用try(resource)保证Writer正确关闭
java io流的拓展还是挺广的,实际应用深度想必会更深,多看看java API收获也是不少的,加油!也要注意身体哟,每天花30分钟健健身挺不错的。晚安~~~~
谢谢阅读 ----知飞翀