Java 输入输出流
Java 中的输入/输出流一共有2种4个类。分别为字节类型的输入——InputStream、输出——OutputStream,字符类型的输入——Reader、输出——Writer。
四种输入输出流都是抽象类,在读取不同的内容时,分别使用对应的实现类去读取即可。
以读写文件为例,使用这四种类如下。
字节方式读写
读取文件
使用到的实现类为FileInputStream。
- 代码如下:
File file = new File("E:\\Documents\\demo.txt");
InputStream is = new FileInputStream(file);
int readLengthATime = 128;
byte[] bytes = new byte[readLengthATime];
int length;
while((length = is.read(bytes,0,readLengthATime))!=-1) {
System.out.println(length);
System.out.println(new String(bytes));
System.out.println("----------------------");
}
is.close();
- 运行结果:
128
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
111 222 333 444 555 666 777 888 999
苟利国家生死以,岂因祸�
----------------------
15
�避趋之。
pqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
111 222 333 444 555 666 777 888 999
苟利国家生死以,岂因祸�
----------------------
- 结果解析:
- inputStream的read()方法有三个参数,第一个参数指定将读取到的数据存入byte[],第二个参数指定从这个byte[]的开始存储位置距数组开头的偏移量offset,第三个参数指定读取多少个字节的requiredLength。返回值为实际读取到了多少个字符actualLength,当返回-1时,表示已经读取结束。
- 当读到行末时,不会停止,将换行视为一个\n继续读取。
- 如果读取的是中文字符,由于中文字符为2个byte,此时有可能会被掐断,导致转String时内容出错。可以选择一个大一点的offset或者使用其他读取方法。
- 由于IO流会阻塞线程,如果byte[]和单次读取的字节数过大,会单次读取的慢且占内存。
- 在数组不越界的前提下,read()方法只会读取Math.max(requiredLength,actualLength)个字符,并从下标offset开始存入byte[],byte[]中未涉及到的部分不会被存入。因此,例子中可见,当循环到第二次时,实际读取到15个字节的数据,只覆盖了byte[0~14]的数据,后面的内容还在,所以在转换为String时,后面还有一些内容。因此,最好在转换成String后,将byte[]清空一下或new一个新的。
- 最后不要忘了关闭输入流。
写入文件
使用到的实现类为FileOutputStream。
- 代码如下:
File file = new File("E:\\Documents\\demoO.txt");
OutputStream os = new FileOutputStream(file);
String toWrite = "abcdefghijklmnopqrstuvwxyz\n" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" +
"111 222 333 444 555 666 777 888 999\n" +
"苟利国家生死以,岂因祸福避趋之。\n";
os.write(toWrite.getBytes());
os.close();
- 运行结果:
无 - 结果解析:
- write()方法与read()方法类似,写入字节数组。使用String.getBytes()方法得到字节后直接输出即可。源码中可以看到它是调用了另一个重载函数write(byte)来一次写一个字节直到写完。
- 最后不要忘了关闭输出流。
字符方式读写
读取文件
使用到的实现类为FileReader。FileReader与InputStreamReader差不多,其实内部只是封装了一步由File到InputStream再到InputStreamReader的过程。
- 代码如下:
File file = new File("E:\\Documents\\demo.txt");
Reader r = new FileReader(file);
int readLengthATime = 32;
char[] chars = new char[readLengthATime];
int length;
while((length = r.read(chars,0,readLengthATime))!=-1) {
System.out.println(length);
System.out.println(new String(chars));
System.out.println("----------------------");
}
r.close();
- 运行结果:
32
abcdefghijklmnopqrstuvwxyz
ABCDE
----------------------
32
FGHIJKLMNOPQRSTUVWXYZ
111 222 33
----------------------
32
3 444 555 666 777 888 999
苟利国家生死
----------------------
11
以,岂因祸福避趋之。
66 777 888 999
苟利国家生死
----------------------
- 结果解析:
- read()方法与InputStream的read()十分类似,只是把byte换成了char。因而也不会出现切断中文字符的情形。
- 最后不要忘了关闭输入流。
写入文件
使用到的实现类为FileWriter。FileWriter与InputStreamWriter差不多,其实内部只是封装了一步由File到OutputStream再到OutputStreamWriter的过程。
- 代码如下:
File file = new File("E:\\Documents\\demoO.txt");
Writer w = new FileWriter(file);
String toWrite = "abcdefghijklmnopqrstuvwxyz\n" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" +
"111 222 333 444 555 666 777 888 999\n" +
"苟利国家生死以,岂因祸福避趋之。\n";
w.write(toWrite);
w.close();
- 运行结果:
无 - 结果解析:
- 不需要转换为char[]数组,可以直接传入String进行输出。
- 最后不要忘了关闭输出流。