字节流和字符流操作的方式基本相同,区别在于操作的数据单元不同,字节流操作的数据单元是字节,字符流操作的数据单元是字符。
输入流操作的抽象基类:InputStream(输入字节流的抽象基类)/Reader(输入字符流的抽象基类)
操作字节流InputStream的3个方法:
- int read()-从输入流中读取单个字节,返回读取到的字节数据(直接转换为int类型)。
- int read(byte[] b)-从输入流中读取b.length长度的数组,并将其存到bbff的字节数组中,方法返回值为读取字节数。
- int read(byte[] b,int off,int len)-从输入流中开始读取len长度的 数据,然后放入b数组中,放入数组中不是从开始位置,而是从off位置开始,返回值是读取的字节数。
操作字符流Reader的3个方法:
- int read()-从输入流中读取单个字符,返回读取到的字符数据(直接转换为int类型)。
- int read(char[] c)-从输入流中读取c.length长度的数组,并将其存到c的字符数组中,方法返回值为读取字符数。
- int read(char[] c,int off,int len)-从输入流中开始读取len长度的 数据,然后放入c数组中,放入数组中不是从开始位置,而是从off位置开始,返回值是读取的字符数。
对比InputStream和Reader发现两个基类无比类似。但是InputStream/Reader为抽象基类,不能直接创建实例。可用它们的继承类FileInputStream和FileReader创建实例对象。还有如何判断数据读取到了最后,相关代码为:
FileInputStream fis = new FileInputStream (/*"E:/workspace/Test/src/test/TestIO.java"*/"./TestIO.java");
/*为何创建bbff.length为1024长的数组,而不适合较小长度的数组:因为字节输入到内存中,
GBK方式中文占2个字节,如果使用read()有可能只读了中文的半个字节而导致中文乱码,*/
byte[] bbff = new byte[1024];
int retuenRead = 0;
while((retuenRead = fis.read(bbff))>0){
System.out.println(new String(bbff,0,retuenRead));
}
fis.close();
try {
// 创建字符流
FileReader fr = new FileReader(
"E:/workspace/Test/src/test/TestIO.java");
// 创建一个32位的字符数组
char[] dqzf = new char[32];
int returnRead = 0;
while ((returnRead = fr.read(dqzf)) > 0) {
System.out.println(new String(dqzf, 0, returnRead));
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
输出流操作的抽象基类:OutputStream(输出字节流的抽象基类)/Writer(输出字符流的抽象基类)
两个流输出的3个方法:
write(int c)-将指定字节/字符输出到输出流中,c代表字节,也可代表字符 。
write(byte[] b/char[] c/String s)-将字节数组/字符数组(字符串)输出到指定的输出流中。
write(byte[] b/char[] c/String s,int off,int len)-将字节/字符数组(字符串)从off位置开始,输出长度为len的字符输出到输出流中。