Java的IO流
1.I/O流概述
InputStream
和OutPutStream
是字节流,而Reader
和Writer
是字符流InputStream
和Reader
是输入流,而OutPutStream
和Writer
是输出流- 图中的4个顶级类都是抽象类,并且是所有流类型的父类
2.字节流
2.1.字节流概述
InputStream
方法声明 | 功能描述 |
---|---|
int read() | 从输入流读取一个8位的字节,把它转换为0~255之间的整数,并返回这一整数。当没有可用字节时,将返回-1 |
int read(byte[] b) | 从输入流读取若干字节,把它们保存到参数b指定的字节数组中,返回的整数表示读取字节的数目 |
int read(byte[] b,int off,int len) | 从输入流读取若干字节,把它们保存到参数b指定的字节数组中,off指定字节数组开始保存数据的起始下标,len表示读取的字节数目 |
void close() | 关闭此输入流并释放与该流关联的所有系统资源 |
OutputStream
方法声明 | 功能描述 |
---|---|
void write(int b) | 向输出流写入一个字节 |
void write(byte[] b) | 把参数b指定的字节数组的所有字节写到输出流 |
void write(byte[] b,int off,int len) | 将指定byte数组中从偏移量off开始的len个字节写入输出流 |
void flush() | 刷新此输出流并强制写出所有缓冲的输出字节 |
2.2.字节流读写文件
2.2.1.读取文件FileInputStream
1 | FileInputStream in = new FileInputStream("test.txt"); |
2.2.2.写入文件FileOutputStream
1 | FileOutputStream out = new FileOutputStream("test.txt"); |
- 注意:使用字节流向文件追加写入数据,需要调用重载的构造方法
1 | FileOutputStream out = new FileOutputStream("test.txt", true); |
2.2.2.关闭流
- I/O流在进行数据读写操作时会出现异常,为了保证I/O流的
close()
方法一定执行来释放占用的系统资源,通常会将关闭流的操作写在finally
代码块中
1 | finally { |
2.3.文件的拷贝
1 | FileInputStream in = new FileInputStream("source/origin.txt"); |
2.4.字节流的缓冲区
1 | FileInputStream in = new FileInputStream("source/origin.txt"); |
2.5.字节缓冲流
BufferedInputStream
BufferedOutputStream
1 | BufferedInputStream bis = new BufferedInputStream(new FileInputStream("source/origin.tex")); |
3.字符流
3.1.字符流概述
3.2.字符流读写文件
3.2.1.读取文件FileReader
1 | FileReader fr = new FileReader("test.txt"); |
3.2.2.写入文件FileWriter
1 | FileWriter fw = new FileWriter("test.txt"); |
- 注意:使用字符流向文件追加写入数据,需要调用重载的构造方法
1 | FileWriter fw = new FileWriter("test.txt", true); |
3.3.字符流的缓冲区
1 | FileReader fr = new FileReader("reader.txt"); |
3.4.字符缓冲流
1 | BufferedReader br = new BufferedReader(new FileReader("reader.txt")); |
3.5.转换流
InputStreamReader
是Reader
的子类,它可以将一个字节输入流转换成字符输入流,方便直接读取字符OutputStreamWriter
是Writer
的子类,它可以将一个字节输出流转换成字符输出流,方便直接写入字符
1 | FileInputStream in = new FileInputStream("reader.txt"); |
4.File类
4.1.构造方法
方法声明 | 功能描述 |
---|---|
File(String pathname) | 通过指定的一个字符串类型的文件路径来创建一个新的File对象 |
File(String parent,String child) | 根据指定的一个字符串类型的父路径和一个字符串类型的子路径(包括文件名称)创建一个File对象 |
File(File parent,String child) | 根据指定的File类的父路径和字符串类型的子路径(包括文件名称)创建一个File对象 |
4.2.常用方法
方法声明 | 功能描述 |
---|---|
boolean exists() | 判断File对象对应的文件或目录是否存在,若存在则返回ture,否则返回false |
boolean delete() | 删除File对象对应的文件或目录,若成功删除则返回true,否则返回false |
boolean createNewFile() | 当File对象对应的文件不存在时,该方法将新建一个此File对象所指定的新文件,若创建成功则返回true,否则返回false |
String getName() | 返回File对象表示的文件或文件夹的名称 |
String getPath() | 返回File对象对应的路径 |
String getAbsolutePath() | 返回File对象对应的绝对路径(在Unix/Linux等系统上,如果路径是以正斜线/开始,则这个路径是绝对路径;在Windows等系统上,如果路径是从盘符开始,则这个路径是绝对路径) |
String getParent() | 返回File对象对应目录的父目录(即返回的目录不包含最后一级子目录) |
boolean canRead() | 判断File对象对应的文件或目录是否可读,若可读则返回true,反之返回false |
boolean canWrite() | 判断File对象对应的文件或目录是否可写,若可写则返回true,反之返回false |
boolean isFile() | 判断File对象对应的是否是文件(不是目录),若是文件则返回true,反之返回false |
boolean isFile() | 判断File对象对应的是否是文件(不是目录),若是文件则返回true,反之返回false |
boolean isDirectory() | 判断File对象对应的是否是目录(不是文件),若是目录则返回true,反之返回false |
boolean isAbsolute() | 判断File对象对应的文件或目录是否是绝对路径 |
long lastModified() | 返回1970年1月1日0时0分0秒到文件最后修改时间的毫秒值 |
long length() | 返回文件内容的长度 |
String[] list() | 列出指定目录的全部内容,只是列出名称 |
String[] list(FilenameFilter filter) | 接收一个FilenameFilter参数,通过该参数可以只列出符合条件的文件 |
File[] listFiles() | 返回一个包含了File对象所有子文件和子目录的File数组 |
1 | File file = new File("test.txt"); |
4.3.遍历目录下的文件
String[] list()
: 遍历某个指定目录下的所有文件的名称
1 | File file = new File("F:\\Java\\workspace\\chapter07"); |
String[] list(FilenameFilter filter)
: 该方法接收一个FilenameFilter
接口类型的参数,其中定义了一个抽象方法accept(File dir,String name)
用于依次对指定File
的所有子目录或文件进行迭代
1 | File file = new File("F:\\Java\\workspace\\chapter07"); |
File[] listFiles()
递归遍历目录文件
1 | class Main { |
4.4.删除文件及目录
1 | class Main { |
5.RandomAccessFile
5.1.构造方法
- 不属于流类,但具有读写文件数据的功能,可以随机从文件的任何位置开始并以指定的操作权限
方法声明 | 功能描述 |
---|---|
RandomAccessFile(File file,String mode) | 使用参数file指定被访问的文件,并使用mode来指定访问模式 |
RandomAccessFile(String name,String mode) | 使用参数name指定被访问文件的路径,并使用mode来指定访问模式 |
- 参数
mode
取值r
:以只读的方式打开文件。如果执行写操作,会报IOException
异常rw
:以“读写”的方式打开文件。如果文件不存在,会自动创建该文件rws
:以“读写”方式打开文件。与“rw
”相比,它要求对文件的内容或元数据的每个更新都同步写入到底层的存储设备rwd
:以“读写”方式打开文件。与“rw
”相比,它要求对文件的内容的每个更新都同步写入到底层的存储设备
- 原理:
RandomAccessFile
对象包含了一个记录指针来标识当前读写处的位置- 当新建
RandomAccessFile
对象时,该对象的文件记录指针会在文件开始处(即标识为0的位置) - 当读写了n个字节后,文件记录指针会向后移动n个字节
- 除了按顺序读写外,
RandomAccessFile
对象还可以自由的移动记录指针,既可以向前移动,也可以向后移动
- 当新建
5.2.常用方法
方法声明 | 功能描述 |
---|---|
long getFilePointer() | 返回当前读写指针所处的位置 |
void seek(long pos) | 设定读写指针的位置,与文件开头相隔pos个字节数 |
int skipBytes(int n) | 使读写指针从当前位置开始,跳过n个字节 |
void write(byte[] b) | 将指定的字节数组写入到这个文件,并从当前文件指针开始 |
void setLength(long newLength) | 设置此文件的长度 |
final String readLine() | 从指定文件当前指针读取下一行内容 |
5.3.示例
1 | /** |
6.对象序列化
- 对象的序列化(
Serializable
)将一个Java对象转换成一个I/O
流中字节序列的过程 - 目的: 为了将对象保存到磁盘中,或允许在网络中直接传输对象
- 将I/O流中的字节序列恢复为Java对象的过程被称之为反序列化(
Deserialize
)
实现Serializable接口 | 实现Externalizable接口 |
---|---|
系统自动存储必要信息 | 由程序员决定存储的信息 |
Java内部支持,易实现,只需实现该接口即可,不需要其他代码支持 | 接口中提供了两个空方法,实现该接口必须为两个方法提供实现 |
性能较差 | 性能较好 |
容易实现,实际开发使用较多 | 编程复杂度大 |
1 | public class Person implements Serializable { |
7.NIO
7.1.NIO概述
- 从
JDK 1.4
开始,Java提供了一系列改进的用于处理输入/输出的新功能,这些新功能被称之为NIO(New I/O)
- 三大核心
- **
Buffer
**本质是一个数组缓冲区,读入或写出到Channel
中的所有对象都会先放在Buffer中 - **
Channel
**是对传统的输入/输出的模拟,在NIO
中,所有的数据都需要通过通道流的形式传输 - **
Selecter
**用于监听多个通道的事件(例如:连接打开、数据到达等),主要用于多线程处理
- **
7.2.Buffer缓冲器
7.2.1.作用
Java NIO
中的Buffer
用于和NIO
中的Channel
进行交互,交互时数据会从Channel
读取到Buffer
中,或从Buffer
写入到Channel
中
7.2.2.使用
- 通过子类中的
static XxxBuffer allocate(int capacity)
方法来实现(其中Xxx
表示不同的数据类型,而capacity
表示容量) Buffer
类似于一个数组,它可以保存多个类型相同的数据Buffer
是一个抽象类,其子类有ByteBuffer
、CharBuffer
、DoubleBuffer
、FloatBuffer
、IntBuffer
、LongBuffer
和ShortBuffer
Buffer
子类中最常用的是ByteBuffer
和CharBuffer
1 | charBuffer buffer = CharBuffer.allocate(6); |
7.2.3.三个重要概念
capacity
(容量): 缓冲器的容量表示该Buffer的最大数据容量,即最多可以存储多少数据。缓冲器的容量值不能为负数,也不能够改变limit
(界限): 表示Buffer
容器中不可被读取的区域的第一个索引,即位于Buffer
容器中索引为0
到limit
之间的区域都可以进行读取操作。缓冲器的limit
值从不为负,也从不大于其容量position
(位置): 用于指定下一个可以被读写的缓冲器位置索引。新创建的Buffer
对象,position
的默认值为0
,每进行一次读取或写入操作,position
的值都会自动向后移动一步
7.2.4.常用方法
方法声明 | 功能描述 |
---|---|
int capacity() | 获取缓冲区的大小 |
Buffer clear() | 清除缓冲区,将position设置为0,limit设置为capacity |
Buffer flip() | 反转缓冲区,先将limit设置为当前position位置,然后再将position设置为0 |
boolean hasRemaining() | 判断当前位置(position)和界限(limit)之间是否还有元素 |
int limit | 获取Buffer的limit位置 |
Buffer limit(int newLimit) | 设置limit的值,并返回一个新的limit缓冲区对象 |
Buffer mark() | 设置Buffer的标记(mark),只能在0与position之间做标记 |
int position() | 获取Buffer中position的值 |
Buffer position(int newPosition) | 设置Buffer的position,并返回位置被修改之后的Buffer对象 |
int remaining() | 获取当前位置和界限之间的元素个数 |
Buffer reset() | 将此缓冲区的位置重置为先前标记的位置 |
Buffer rewind() | 倒带缓冲区,将position设置为0,并取消设置的标记 |
7.3.Channel通道
7.3.1.概论
Channel
可以异步的执行I/O
读写操作Channel
的读写操作是双向的,既可以从Channel
中读取数据,又可以写数据到Channel
,而流的读写操作通常都是单向的Channel
可以直接将指定文件的部分或者全部直接映射成Buffer
Channel
只能与Buffer
进行交互,程序不能直接读写Channel中的数据
7.3.2.实现类
DatagramChannel
用于支持UDP
网络通信FileChannel
用于从文件中读写数据Pipe.SinkChannel
和Pipe.SourceChannel
用于支持线程之间的通信ServerSocketChannel
和SocketChannel
用于支持TCP
网络通信
7.3.3.使用
Channel
对象并不是通过构造方法来创建的,而是通过传统I/O
的getChannel()
方法来获取对应的Channel
- 不同的流所获取的
Channel
是不同的,例如FileInputStream
和FileOutputStream
获取的是FileChannel
,同时还可以使用RandomAccessFile
获取该对象 PipedInputStream
和PipedOutputStream
所获得的是Pipe.SinkChannel
和Pipe.SourceChanne
7.3.4.FileChannel常用方法
方法声明 | 功能描述 |
---|---|
MappedByteBuffer map(MapMode mode, long position, long size) | 将该通道文件的区域直接映射到内存中。其中第1个参数用于执行映射时的模式,包含只读、读写等模式;第2个参数表示映射区域开始的文件中的位置;第3个参数表示要映射区域的大小 |
long position() | 返回该通道的文件位置 |
Int read(ByteBuffer dst) | 从这个通道读取一个字节序列到给定的缓冲区 |
Int read(ByteBuffer dst, long position) | 从给定的文件位置开始,从这个通道读取一个字节序列到给定的缓冲区 |
long read(ByteBuffer[] dsts, int offset, int length) | 从这个通道读取一个字节序列到给定缓冲区的子序列 |
long size() | 返回该通道文件的当前大小 |
long transferTo(long position, long count, WritableByteChannel target) | 读取该通道文件中给定位置的字节数,并将它们写入目标通道 |
Int write(ByteBuffer src) | 从给定的缓冲区写入这个通道的字节序列 |
long write(ByteBuffer[] srcs, int offset, int length) | 从给定缓冲区的子序列中写入该通道的字节序列 |
Int write(ByteBuffer src, long position) | 从给定的缓冲区开始,从给定的文件位置开始向该通道写入一个字节序列 |
7.3.5.示例
1 | RandomAccessFile infile = new RandomAccessFile("source/src.jpg", "rw"); |
8.NIO.2
8.1.概述
NIO.2
最大的改进是提供了全面的文件输入/输出以及文件系统的访问与支持- 并且新增了j
ava.nio.file
包及其子包 - 而且还提供基于异步Channel的输入/输出。
8.2.Path接口
方法声明 | 功能描述 |
---|---|
boolean endsWith(String other) | 判断当前路径是否以指定的字符串结尾 |
Path getName(int index) | 返回此路径的名称元素作为路径对象 |
int getNameCount() | 返回路径中名称元素的数量 |
Path getParent() | 返回父路径,如果此路径没有父路径,则返回null |
Path getRoot() | 返回该路径的根组件作为路径对象,如果此路径没有根组件,则返回null |
Path toAbsolutePath() | 返回表示此路径的绝对路径的路径对象 |
URI toUri() | 返回表示此路径的URI地址 |
1 | Path path = Paths.get("D:\\test\\文件夹\\test.txt"); |
1 | /** |
8.3.Files类
方法声明 | 功能描述 |
---|---|
static Path createDirectories(Path dir, FileAttribute<?>… attrs) | 创建多级文件目录 |
static Path createFile(Path path, FileAttribute<?>… attrs) | 创建一个新的空文件,如果文件已经存在,则创建失败 |
static Path copy(Path source, Path target,CopyOption… options) | 该方法将一个文件复制到目标文件,并使用选项参数指定如何执行复制 |
static List | 从文件中读取所有行 |
static long size(Path path) | 返回文件的大小(以字节为单位) |
static Stream | 将指定路径转换为Stream流对象 |
static Path write(Path path, Iterable<? extends CharSequence> lines, OpenOption… options) | 将文本行写入文件,并传入指定的写入模式 |
1 | Path directoryPath = Paths.get("D:/test/sample"); |
1 | /** |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 修远的小屋!