流类
Java的流式输入/输出是建立在四个抽象类的基础上的:InputStream(字节输入流)、OutputStream(字节输出流)、Reader(字符输入流)、Writer(字符输出流)。它们用来创建具体的流式子类。尽管程序通过具体子类执行输入/输出操作,但顶层类定义了所有流类的基本通用功能。
InputStream和OutputStream为字节流设计,Reader和Writer为字符流设计,字节流和字符流形成分离的层次结构。一般来说,处理字符或字符串使用字符流类,处理字节或二进制对象使用字节流。
操作文件流时,不管是字符流还是字节流,都可以按照以下方式进行:
1、使用File类找到一个对象
2、通过File类的对象去实例化字节流或字符流的子类
3、进行字节(字符)的读、写操作
4、关闭文件流
OutputStream(字节输出流)
OutputStream是定义了Java流式字节输出模式的抽象类。该类的所有方法返回一个void值并且在出错的情况下引发一个IOException,OutputStream提供的抽象方法有:
方 法 | 作 用 |
void close() | 关闭输出流,关闭后的写操作会引发IOException |
flush() | 刷新此输出流并强制写出所有缓冲的输出字节 |
write(byte[] b) | 向一个输出流写一个完整的字节数组 |
write(byte[] b, int off, int len) | 以b[off]为起点,向文件写入字节数组b中len个字节 |
abstract void write(int b) | 向输入流写入单个字节,注意参数是一个int型,它允许设计者不必把参数转换成字节型就可以调用write()方法 |
FileOutputStream(文件字节输出流)
FileOutputStream应该是Java中最常见的字节输出流了,它创建一个可向文件写入字节的类OutputStream,它常用的构造方法如下:
1、FileOutputStream(String name)
2、FileOutputStream(File file)
3、FileOutputStream(File file, boolean append)
前两个构造方法类似,前者输入文件的绝对路径,后者输入File的实例对象,和RandomAccessFile一样(构造方法也是new一个File出来再调用第二种构造方法),推荐后者。第三个构造方法有一点不同,append如果设置为true,文件则是“追加数据”,为false则是”覆盖数据”。(写文件有两种方法,一种是从文件头写入(覆盖原有数据),另一种是从文件尾写入(增加数据))FileOutputStream的创建不依赖于文件是否存在,在创建对象时,FileOutputStream会在打开输出文件之前就创建它。这种情况下如果试图打开一个只读文件,会引发IOException。
FileOutputStream,写一个例子,现在我的D盘路径下并没有"stream.txt"这个文件:
public static void main(String[] args) throws Exception
{
File file = new File("D:/stream.txt");
OutputStream out = new FileOutputStream(file);;
byte b0[] = "hello world".getBytes(); //操作字节流,要转换成字节
out.write(b0);
out.close();
}
此时打开"stream.txt":
看到D盘下多了"stream.txt",且文件中的内容和我们写入的一致,同样这个例子也证明了FileOutputStream并不依赖指定路径下的文件是否存在。那如果指定路径下本来就有文件,那么写将会覆盖而不是追加,很好证明:
public static void main(String[] args) throws Exception
{
File file = new File("D:/stream.txt");
OutputStream out = new FileOutputStream(file);;
byte b0[] = "abcdefghijklmnopqrstuvwxyz".getBytes(); //操作字节流,要转换成字节
out.write(b0);
out.close();
}
此时再打开"stream.txt":
"stream.txt"中的内容变掉了,证明了结论。
InputStream(字节输入流)
InputStream是定义了Java流式字节输入模式的抽象类。该类所有方法在出错的时候都会引发一个IOException,InputStream提供的抽象方法有:
FileInputStream(文件字节输入流)
FileInputStream应该是Java中最常见的字节输入流了,它创建一个能从文件读取字节的InputStream类,它的两个常用构造方法如下:
1、FileInputStream(String name)
2、FileInputStream(File file)
和FileOutputStream差不多,推荐后者的用法。FileInputStream,同样写一个例子,操作的是上面D盘下生成的"stream.txt":
public static void main(String[] args) throws Exception
{
File file = new File("D:/stream.txt");
InputStream in = new FileInputStream(file);
byte b1[] = new byte[(int)file.length()];
int i = 0;
i = in.read(b1);
System.out.println(i);
System.out.println(new String(b1, 0, i));
}
运行结果为:
20
Hello World!!!
要区分清楚,OutputStream的作用是将内容由Java内存输出到文件中、InputStream是将内容由文件输入到Java内存中。read(byte b[])方法之前讲明了,表示"试图读取buffer.length个字节到buffer中,并返回实际读取的字节数",返回的是实际字节的大小。不要误以为"Hello World!!!"是14个字符即28个字节,字节流底层是以byte为单位的,因此文件里面只有14个字节罢了,至于返回的是20,还是因为"字节对齐"的问题。
这里没有演示skip方法,因为比较简单,skip多少无非调过几个字节罢了,skip(3),那么读出的就是"lo World!!!",可以自己尝试一下。