概述
IO(Input/Output):输入和输出,指的是某个设备或环境进行数据的输入或者输出。例如:键盘的输入,再比如显示器就是输出设备,输出图像。
IO流在java中从输入输出角度分类:
- 输入流
- 输出流
IO流在java中从数据的角度来分类:
-
字符流
文本,我们能读的懂的都可以认为是字符流。比如:文章,java文件等等
-
字节流
二进制的数据,这种数据一般用文本打开我们读不懂。比如,图片文件,mp3文件,等等。
IO流结构图
字符流
文本,我们能读的懂的都可以认为是字符流。比如:文章,java文件等等
字符输入流(Reader)
Reader
|
|——FileReader
|——BufferedReader
FileReader
import java.io.*;
public class FileReader01 {
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("file01.txt");
int ch;
while((ch=fr.read())!=-1) {
System.out.println((char)ch);
}
fr.close();
fr = new FileReader("file01.txt");
char[] a = new char[2];
int len;
while((len=fr.read(a))!=-1) {
String str = new String(a,0,len);
System.out.println(str);
}
fr.close();
}
}
通过创建一个 FileReader 对象,我们打开了名为 file01 的 txt 文件(文件内容:ABC)
读取数据有两种方式:
- 单个字符读取
调用 read() 方法,如果纯文本文件中有内容的话,就会返回 ASCII 码表中对应的数字值,如果 ASCII 表中不存在,就会去查找 Unicode 表。如果纯文本文件没有内容 ,或者前面的内容已经被读取完了,返回的就是 -1,由于我们不知道文本内容有多少。所以我们需要使用一个循环。
- 多个字符读取
单个字符读取的效率实在低的可怜,所以我们一口气读多点,存放在一个字符类型的数组里。开始之前,我们先看一张图。
当使用 read() 方法的时候,读取字符数组,由于字符数组的长度是 2,所以一口气读的是两个字符,由于文本内容只有 3 个字符,那么第二次读取的时候,可读取的有效长度就是 1 ,那么存放正在字符数组的第一位就会被覆盖掉,但是第二位没有被覆盖,就会保留,如果我们直接读取字符串,而不指定有效长度的话,就会按字符数组的长度读取,而不是只读 有效长度。
所以我们在创建一个 String 对象的时候,要如此使用。
String str = new String(a,0,len);
a 代表的是字符数组,0,代表起始位置,len 代表读取的长度。
BufferedReader
构造方法:
public static void main(String[] args) {
BufferedReader reader = null;
char[] a = new char[2];
try {
reader = new BufferedReader(new FileReader("D:\\test.txt"));
int len;
while((len=reader.read(a))!=-1) {
String str = new String(a,0,len);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
它比FileReader的效率更高
字符输出流(Write)
FileWrite
public static void main(String[] args) {
FileWriter fw = null;
try {
fw = new FileWriter("D:\\test.txt");
fw.write("写进去了吗?");
//把流资源中的数据,即缓冲中的数据,刷新到目的文件中,这样才能把所有数据全部写入文件
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//作用就是关闭系统流资源,在关闭之前,会执行一次flush方法,刷新缓冲区数据。
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
需要注意的是:
writer()方法说明:改方法只是把数据写到系统流资源内,并没有直接把数据写到文件上。有个缓冲的概念存在。要想全部写入文件,得执行flush()方法。
flush()方法说明:作用就是把流资源中的数据,即缓冲中的数据,刷新到目的文件中,这样才能把所有数据全部写入文件。
close()方法说明:作用就是关闭系统流资源,在关闭之前,会执行一次flush方法,刷新缓冲区数据。
以上三个方法都有可能抛IOException异常。
字节流
二进制的数据,这种数据一般用文本打开我们读不懂。比如,图片文件,mp3文件,等等。
字节输入流(InputStream)
FileInputStream
public static void main(String[] args) {
FileInputStream reader = null;
byte[] a = new byte[10];
try {
reader = new FileInputStream("C:\\Users\\45442\\Desktop\\image_model\\LD.jpg");
int len;
while((len=reader.read(a))!=-1) {
for (byte b : a){
System.out.println(b);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节输出流(OutStream)
FileOutputStream
public static void main(String[] args) {
FileOutputStream writer = null;
try {
writer = new FileOutputStream("C:\\Users\\45442\\Desktop\\image_model\\LD.jpg");
writer.write(new byte[]{1,2,3});
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedOutputStream
public static void main(String[] args) {
BufferedOutputStream writer = null;
try {
writer = new BufferedOutputStream(new FileOutputStream("C:\\Users\\45442\\Desktop\\image_model\\LD.jpg"));
writer.write(new byte[]{1,2,3});
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
它比FileOutputStream的效率更高
字符流和字节流的转换
转换流的特点:
-
其是字符流和字节流之间的桥梁
-
可对读取到的字节数据经过指定编码转换成字符
-
可对读取到的字符数据经过指定编码转换成字节
InputStreamReader(字节到字符的桥梁)
public static void main(String[] args) throws IOException {
//采用指定的编码读取txt文件
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"osw.txt"), "UTF-8");
char[] chs = new char[1024];
int len = 0;
while((len=isr.read(chs))!=-1){
System.out.println(String.valueOf(chs, 0, len));
}
isr.close();
}
OutputStreamWriter(字符到字节的桥梁)
public static void main(String[] args){
try {
//采用指定的编码写txt文件
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("c://c.txt"), "GBK");
osw.write("Java很好啊");
osw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
打印流
打印流:只做输出没有输入
打印流分为字节打印流和字符打印流
PrintWriter:字符打印流
特点
- 可以打印各种数据类型
- 封装了字符输出流,还可以字符流和字节流的转换
- 可以使用自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作
- 可以直接向文件中写数据
PrintWriter
使用打印流向文件中打印数据
public static void main(String[] args) {
PrintWriter pw = null;
try {
pw = new PrintWriter("b.txt");
pw.print(true);
pw.print('c');
pw.print(new char[]{'d', 'g', 'g'});
pw.print(123L);
pw.print(12.0F);
pw.print(1);
pw.print(45);
pw.println("张三");
} catch (FileNotFoundException var6) {
var6.printStackTrace();
} finally {
pw.close();
}
}
效果
从文件中读取数据并且打印在控制台
public static void main(String[] args) {
BufferedReader br = null;
PrintWriter pw = null;
try {
br = new BufferedReader(new FileReader("b.txt"));
pw = new PrintWriter(System.out);
String line = null;
while((line = br.readLine()) != null) {
pw.println(line);
}
} catch (Exception var12) {
var12.printStackTrace();
} finally {
if (pw != null) {
pw.close();
}
try {
if (br != null) {
br.close();
}
} catch (IOException var11) {
var11.printStackTrace();
}
}
}
结果
truecdgg12312.0145张三
使用打印流来复制文本文件
public static void main(String[] args) {
BufferedReader br = null;
PrintWriter pw = null;
System.out.println();
try {
br = new BufferedReader(new FileReader("b.txt"));
pw = new PrintWriter("c.txt");
String line = null;
while((line = br.readLine()) != null) {
pw.println(line);
}
} catch (Exception var12) {
var12.printStackTrace();
} finally {
if (pw != null) {
pw.close();
}
try {
if (br != null) {
br.close();
}
} catch (IOException var11) {
var11.printStackTrace();
}
}
}
效果