I / O 流
IO 流体系结构
节点流和处理流:
抽象基类 | 节点流(或文件流) | 缓冲流(处理流的一种) | 数据流 |
---|---|---|---|
InputStream | FileInputStream | BufferedInputStream | DataInputStream |
OutputStream | FileOutputStream | BufferedOutputStream | DataInputStream |
Reader | FileReader | BufferedReader | - |
Writer | FileWriter | BufferedWriter | - |
-
抽象基类:可以分为两大类字节流(InputStream / OutputStream)和字符流(Reader / Writer),这两大类别中都有输入流(InputStream / Reader)和输出流(OutputStream / Writer)的类。输入流只能读取数据,输出流只能写入数据。
-
**文件流:**可以读写硬盘中的文件,前面有关键字 FileXXXXXXX 的都是文件流。
-
**缓冲流:**处理流的一种,可以提升节点流的效率。不能单独使用,需要创建对应的节点流,带有关键字 BufferedXXXXXXX 的都为缓冲流。
转换流(属于处理流):
抽象基类 | 转换流 |
---|---|
Reader | InputStreamReader |
Writer | OutputStreamWriter |
- **转换流:**可以将一个字节流转换为字符流,方便直接读取字符。
**注1:**使用 IO 流的方法和对象时,可能会抛出 IOException 异常,建议在try / catch
中声明和使用(不推荐在 main 或方法中直接 throws IOException
)
**注2:**使用完流时一定要调用 void close( )
方法来关闭流操作,释放系统资源。
字节流(InputStream / OutputStream)
InputStream 常用方法:
方法声明 | 功能描述 |
---|---|
int read( ) | 读取文件的一个 8 位字节,转换为 0 ~ 255 之间的整数,并返回。没有字节时返回 -1 |
int read( byte[] b ) | 同上,此方法会把获取的字节存放于参数的 byte 型数组中,并返回读取到的字节数目 |
int read( byte[] b, int off, int len ) | 同上, off 为从指定下标开始保存字节, len 表示读取字节数目 |
void close( ) | 关闭输入流,释放与此流相关的所有系统资源】 |
文件字节流(FileInputStream / FileOutputStream)
使用文件字节流读取(FileInputStream)文件中的内容(下面实例中,为了可读性,直接在 main 方法中抛出了异常)
例1:
public class Example1 {
public static void main(String[] args) throws IOException {
// 1.创建输入流,来读取 Example1.txt 这个文件(需先创建好)
FileInputStream in = new FileInputStream("Example1.txt");
// 2.创建变量 b 来接收文件中的字节
int b;
/*
* 3.while 中的条件为:
* (1)每次获取到的字节赋值给 b
* (2)再判断 b 的值是否为 -1 如果为 -1 证明文件的字节读取完毕,则结束循环
*/
while ((b = in.read()) != -1) {
// 4.将获取到的字节转换为 char 类型
System.out.print((char)b);
}
// 5.关闭输入流
in.close();
}
}
以上方法不能读取文件内有中文的文件,若要读取中文推荐使用字符流(FileReader)或者以下方法(不推荐)
例2:
public class Example2 {
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("Example2.txt");
byte[] bytes = new byte[1024];
int len;
while ((len = in.read(bytes)) != -1) {
/*
* 调用 String 的有参构造,会把数组转换成字符串。
* 0 为开始下标,len 为返回的字节数的个数
*/
String str = new String(bytes, 0, len);
System.out.print(str);
}
in.close();
}
}
OutputStream 常用方法:
方法声明 | 功能描述 |
---|---|
void write( int b ) | 向输出流中写入一个字节 |
viod write( byte[] b ) | 同上,会把 byte 型数组 b 的所有字节写入到输出流 |
void write( byte[] b, int off, int len ) | 同上,将指定 byte 数组中从偏移量 off 开始的 len个字节写入到输出流 |
void flush( ) | 刷新此输出流并强制写出所有缓冲的输出字节 |
void close( ) | 关闭输出流,释放与此流相关的所有系统资源 |
使用文件字节流输出(FileOutputStream)文件中的内容
字符流(Reader / Writer)
字符输入流 ( Reader ) 常用方法:
方法声明 | 功能描述 |
---|---|
int read( ) | 读取一个字符,返回该字符的一个整数,达到末尾时返回 -1 |
int rear( char[] cbuf ) | 同上,此方法会将读取到的字符依次存入 char 类型数组,并返回读取到的字符数量,结尾返回 -1 |
int read( char[] cbuf, int off, int len ) | 同上,参数 off 为开始的位置下标,len 为要读取到的最大字符数量 |
void close( ) | 关闭输入流,释放与该流相关的任何系统资源 |
当读取到的字符被阻塞或到结尾是会返回 false 否则就为 true | |
标记流中的当前位置,对reset( )的后续调用将尝试将流重新定位到此位置。并非所有字符输入流都支持mark( ) | |
告诉这个流是否支持mark( )操作,默认实现始终返回false,子类应该覆盖此方法 | |
跳过字符,该方法将阻塞,直到某些字符可用,n 为要跳过的字符数,返回实际跳过的字符数 | |
重置流,如果流被标记 ( mark() ) 则尝试在标记处重新定位。未被标记,尝试以某种方式对特定的流重置 |
注:删除线 是还未学习的方法
**字符输出流(Writer)常用方法: **
方法声明 | 功能描述 |
---|---|
void write( char c ) | 向输出流中写入一个字符 |
void write( String str ) | 将一个字符串写入到流 |
void write( String str, int off, int len ) | 将一个字符串按 off 的开始下标,到 len 的结束下标写入到流 |
void write( char[] cbuf ) | 将一个 char 型数组写入到流 |
void wrtie( char[] cbuf, int off, int len ) | 将一个 char 型数组按照 off 开始的下标,到 len 的结束下标写入到流 |
void close( ) | 会先刷新流,再关闭输出流,释放与该流相关的任何系统资源 |
将指定的字符附加到此作者 | |
将指定的字符序列附加到此作者 | |
将指定字符序列的子序列附加到此作者 | |
刷新流 |
注:删除线 是还未学习的方法
使用 try / catch 抛出 IOException 异常
以字节输入流(InputStream)为例
例3:
public class Example3 {
public static void main(String[] args) {
FileInputStream in = null;
try {
in = new FileInputStream("Example3.txt");
int len;
while ((len = in.read()) != -1) {
System.out.print((char) len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
/**
* 关闭流操作因为必须执行,所以得放进finally 里。
* 因为会抛出 IOException 异常,所以需要加上 try / catch
* 判断输入流 in 是否是 null 的,为 null 的不需要关闭
*/
try {
if (in != null) {
in.close(); //关闭输入流
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}