概述
- 按照流向可以分为:输入流、输出流。从数据源中读取数据是输入流,将数据写入到目的地是输出流。
- 按照数据处理单位可以分为:字节流、字符流。字节占1个byte即8位,字符占2个byte即16位。对于文本文件(txt、xml、java)应该使用字符流,字符涉及编码格式,对于二进制文件(jpg、doc、mp3)应该使用字节流,字节不涉及编码格式。
InputStream 字节输入流 | OutputStream 字节输入流 | Reader 字符输入流 | Writer 字符输出流 | |
缓存流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
文件流 | FileInputStream | FileOutputStream | FileReader | FileWriter |
数组流 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
字符串流 | - | - | StringReader | StringWriter |
管道流 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
对象流 | ObjectInputStream | ObjectOutputStream | - | - |
转换流 | - | - | InputStreamReader | OutputStreamWriter |
基本数据类型流 | DataInputStream | DataOutputStream |
Java 7 特性
实现了 AutoClose 接口的对象,能自动关闭流资源。格式:try(流对象){读写代码}。
字符流抽象基类 Writer、Reader
Writer:字符写入流的抽象类。
close() | abstract public void close() throws IOException 刷新后关闭流并释放资源,流不能再被使用。 |
flush() | abstract public void flush() throws IOException 刷新该流的缓冲,流可以继续使用。 |
write() | public void write(int c) throws IOException 写入单个字符(0~65535)。 |
public void write(char cbuf[]) throws IOException 写入字符数组。 | |
public void write(String str) throws IOException 写入字符串。 | |
append() | public Writer append(char c) throws IOException 续写字符。 |
public Writer append(CharSequence csq) throws IOException 续写字符序列。 |
Reader:字符读取流的抽象类。
close() | abstract public void close() throws IOException 关闭流并释放资源,流不能再使用。 |
read() | public int read() throws IOException 读取单个字符,返回的是字符在内存中对应的数字(0~65535),该方法再次调用会自动读取下一位,没有了则返回 -1。 |
public int read(char cbuf[]) throws IOException abstract public int read(char cbuf[], int off, int len) throws IOException 将读取的字符存入数组,返回的是读到的个数,没有了则返回 -1。 |
字节流抽象基类 OutputStream、InputStream
OutputStream:字节输出流的抽象类。
close() | public void close() throws IOException 刷新后关闭流并释放资源,流不能再被使用。 |
flush() | public void flush() throws IOException 刷新该流的缓冲,流可以继续使用。 |
write() | public abstract void write(int b) throws IOException |
public void write(byte b[]) throws IOException 写入字节数组。 |
InputStream:字节输入流的抽象类。
close() | public void close() throws IOException 关闭流并释放资源,流不能再使用。 |
available() | public int available() throws IOException 返回的是读到的字节个数,\r 和 \n 各是一位。 |
read() | public abstract int read() throws IOException 读取单个字节,读取有效位int的最低8位,该方法再次调用会自动读取下一位,没有了则返回 -1。 |
public int read(byte b[]) throws IOException 将读取的字节存入数组,返回的是读到的个数,没有了则返回 -1。 |
文件流
文件流可以直接操作文件的读写,
FileWriter:字符文件写入流。用来写字符文件的便捷类。如果有同名文件会覆盖(因此续写模式从构造入手而不是write()方法入手)。
FileWriter() | public FileWriter(File file) throws IOException 根据给定的文件构造,从开头写。 append续写模式,true从结尾处写,false从开头写。 |
public FileWriter(String fileName) throws IOException 根据给定的文件名构造(文件名前不带路径则为当前目录),从开头写。 append续写模式,true从结尾处写,false从开头写。 |
FileReader:字符文件读取流。用来读字符文件的便捷类。
FileReader() | public FileReader(File file) throws FileNotFoundException 根据给定的文件构造。 |
public FileReader(String fileName) throws FileNotFoundException 根据给定的文件名构造(文件名前不带路径则为当前目录)。 |
/*创建一个FileReader对象并和指定文件关联
要保证该文件是已经存在的,否则抛异常*/
try (FileReader fr = new FileReader("demo.txt")) {
int num = 0;
// 每次读取单个字符效率低下不推荐
// while ((num = fr.read()) != -1) {
// System.out.print((char)num);
// }
char[] buffer = new char[1024]; //定义一个数组用于存储读到的字符(建议为1024的整数倍)
while ((num = fr.read(buffer)) != -1) { //直到返回-1读不到数据了便结束
System.out.print(new String(buffer, 0, num)); //最后一次读取,不一定装满1024所以是num不是buffer.length,否则超过num后会把上一次存入的打印出来
}
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream:字节文件输出流。
FileInputStream:字节文件输入流。
缓存流
为了提高数据读写的速度,JavaAPI提供了带缓冲功能的流,在使用这些流类,会创建一个内部缓冲区数组。缓冲流要“套接”在相应的其他流之上(创建时需要传入其他流),对读写的数据提供了缓冲的功能,提高了读写的效率。写出的数据会先在内存中缓存,使用flush()将会使内存中的数据立刻写出。
BufferedWrite:字符写入的缓存流。将文本写入字符输出流,缓存各个字符,从而提供高效写入。
BufferedWrite() | public BufferedWriter(Writer out) 缓冲区的出现是为了提高流的效率,所以创建缓冲区需要提供一个流对象。 |
newLine() | public void newLine() throws IOException 写入一个换行符(回车换行效果)。 |
try (BufferedWriter bw = new BufferedWriter(new FileWriter("demo.txt"))) {
for (int i = 1; i < 5; i++) {
bw.write("Hello" + i);
bw.newLine(); //换行
bw.flush(); //每次刷新避免数据丢失,用到缓存流就要记得刷新
}
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader:字符读取的缓存流。从字符输入流中读取文本,缓存各个字符,从而提供高效读取。
BufferedReader() | public BufferedReader(Reader in) 缓冲区的出现是为了提高流的效率,所以创建缓冲区需要提供一个流对象。 |
readLine() | public String readLine() throws IOException 读取一行文本(不包含换行符)。 |
try (BufferedReader br = new BufferedReader(new FileReader("demo.txt"))) {
String line = null;
while ((line = br.readLine()) != null) { //一行一行读更方便
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
通过字符缓存流复制文本文件
try (BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\original\\demo.txt"));
BufferedReader br = new BufferedReader(new FileReader("E:\\destination\\demo_copy.txt"))
) {
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
BufferedOutputStream:字节输出缓存流。
BufferedInputStream:字节输入缓存流。
ObjectInputStream、ObjectOutputStream
对象流,对象的持久化存储(将对象存储到文件中)。
PipedInputStream、PipedOutputStream
管道流,输入流和输出流直接进行连接,结合线程使用。
ByteArrayInputStream、ByteArrayOutputStream
字节数组流,因为两个流对象操作的是数组,没有使用系统资源所以不会出现 IOException。