I/O
基本概念
IO:Input和Output,即输入与输出。
输入是从外界到程序中的方向,是我们程序用于获取外界信息的过程,是“读”的过程。
输出是从程序到外界的方向,是我们程序向外界发送信息的过程,是“写”的过程。
输入流与输出流:是程序与外界的一根管道,用于传输数据,数据以字节的形式传输。
超类
InputStream和OutputStream是两个超类,抽象类,Java中用于实际读写数据的流都继承自它们。
java.io.FileInputStream和FileOutputStream,这两个流都继承自InputStream和OutputStream,用于读写文件数据
java.io.InputStream是所有字节输入流的超类,里面定义了所有字节输入流都必须具备的读取字节的方法
- int read()
读取一个字节,以int形式返回,该int值的”低八位”有效,若返回值为-1则表示EOF - int read(byte[] data)
尝试最多读取给定数组的length个字节并存入该数组,返回值为实际读取到的字节量。
java.io.OutputStream是所有字节输出流的超类,里面定义了所有字节输出流都必须具备的写出字节的方法
- void write(int d)
写出一个字节,写的是给定的int的”低八位” - void write(byte[] data)
将给定的字节数组中的所有字节全部写出 - void write(byte[] data,int offset,int len)
将给定的字节数组中从offset处开始的连续len个字节写出
文件流
概念
文件流是用来链接我们的程序与文件之间的"管道",用来读写文件数据的流。
文件流分为
- 文件输入流java.io.FileInputStream:读取文件数据的流
- 文件输出流java.io.FileOutputStream:写入文件数据的流
- 文件流是继承自InputStream和OutputStream
文件输出流
java.io.FileOutputStream使用文件输出流向文件中写入数据
构造器
FileOutputStream(String path)
创建文件输出流对指定的path路径表示的文件进行写操作,如果该文件不存在则将其创建出来
FileOutputStream(File file)
创建文件输出流对指定的file对象表示的文件进行写操作,如果该文件不存在则将其创建出来
文件输入流
java.io.FileInputStream使用文件输入流向从文件中读取数据
构造器
FileInputStream(String path)
基于给定的路径对应的文件创建文件输入流
FileInputStream(File file)
基于给定的File对象所表示的文件创建文件输入流
文件复制
复制文件的原理就是使用文件输入流从原文件中陆续读取出每一个字节,然后再使用文件输出流将字节陆续写入到另一个文件中完成的。
效率问题
上述案例在复制文件时的读写效率是很低的。因为硬盘的特性,决定着硬盘的读写效率差,而单字节读写就是在频繁调用硬盘的读写,从而产生了"木桶效应"。
为了解决这个问题,我们可以采取使用块读写的方式来复制文件,减少硬盘的实际读写的次数,从而提高效率。
块读写
-
块读:一次性读取一组字节的方式
InputStream中定义了块读的方法 -
int read(byte[] data)
一次性读取给定字节数组总长度的字节量并存入到该数组中。
返回值为实际读取到的字节数。如果返回值为-1表示本次没有读取到任何字节已经是流的末尾了 -
块写:一次性写出一组字节的方式
OutputStream中定义了块写的方法
-
void write(byte[] data)
一次性将给定数组中所有字节写出
void write(byte[] data,int offset,int len)
一次性将data数组中从下标offset处开始的连续len个字节一次性写出
问题
速度问题解决了,但是复制后的文件比原文件大一些。这是文件不一定是10240的倍数,这会导致最后一次读取时是读不够10240的字节数的,那么data数组中就不是所有数据都是新数据了。此时如果在写出时将data数组所有内容写出就会出现文件最后多出很多旧的数据。
解决办法
使用OutputStream的另一个块写操作
void write(byte[] data,int offset,int len)
将给定数组data从offset处开始的连续len个字节一次性写出
写出文本数据
文件中只能保存2进制信息,因此我们要想写出文本数据,需要先将字符串转换为2进制。
文件流
概念
文件流是用来链接我们的程序与文件之间的"管道",用来读写文件数据的流。
文件流分为
- 文件输入流java.io.FileInputStream:读取文件数据的流
- 文件输出流java.io.FileOutputStream:写入文件数据的流
- 文件流是继承自InputStream和OutputStream
文件输出流
java.io.FileOutputStream使用文件输出流向文件中写入数据
构造器
FileOutputStream(String path)
创建文件输出流对指定的path路径表示的文件进行写操作,如果该文件不存在则将其创建出来
FileOutputStream(File file)
创建文件输出流对指定的file对象表示的文件进行写操作,如果该文件不存在则将其创建出来
文件输入流
java.io.FileInputStream使用文件输入流向从文件中读取数据
构造器
FileInputStream(String path)
基于给定的路径对应的文件创建文件输入流
FileInputStream(File file)
基于给定的File对象所表示的文件创建文件输入流
文件复制
复制文件的原理就是使用文件输入流从原文件中陆续读取出每一个字节,然后再使用文件输出流将字节陆续写入到另一个文件中完成的。
效率问题
上述案例在复制文件时的读写效率是很低的。因为硬盘的特性,决定着硬盘的读写效率差,而单字节读写就是在频繁调用硬盘的读写,从而产生了"木桶效应"。
为了解决这个问题,我们可以采取使用块读写的方式来复制文件,减少硬盘的实际读写的次数,从而提高效率。
块读写
-
块读:一次性读取一组字节的方式
InputStream中定义了块读的方法 -
int read(byte[] data)
一次性读取给定字节数组总长度的字节量并存入到该数组中。
返回值为实际读取到的字节数。如果返回值为-1表示本次没有读取到任何字节已经是流的末尾了 -
块写:一次性写出一组字节的方式
OutputStream中定义了块写的方法
-
void write(byte[] data)
一次性将给定数组中所有字节写出
void write(byte[] data,int offset,int len)
一次性将data数组中从下标offset处开始的连续len个字节一次性写出
问题
速度问题解决了,但是复制后的文件比原文件大一些。这是文件不一定是10240的倍数,这会导致最后一次读取时是读不够10240的字节数的,那么data数组中就不是所有数据都是新数据了。此时如果在写出时将data数组所有内容写出就会出现文件最后多出很多旧的数据。
解决办法
使用OutputStream的另一个块写操作
void write(byte[] data,int offset,int len)
将给定数组data从offset处开始的连续len个字节一次性写出
写出文本数据
文件中只能保存2进制信息,因此我们要想写出文本数据,需要先将字符串转换为2进制。