IO流基本导图
----字节流
输入字节流:
------| InputStream 输入字节流基类
-----------| FileInputStream 输入字节流管道
-----------| BufferedInputStream 缓冲输入字节流(内部维护了一个8kb的字节数组)
输出字节流:
------| OutputStream 输出字节流基类
-----------| FileOutputStream 输出字节流管道
-----------| BufferedOutputStream 缓冲输出字节流(内部维护了一个8kb的字节数组)
---字符流 = 字节流+ 编码(解码)
输入字符流
-----| Reader 输入字符流基类
-----------| FileReader 输入字符流管道
-----------| BUfferedReader 缓冲输入字符流(维护了一个1024个长度的字符数组) 拓展功能---->readLine()
输出字符流
-----| Writer 抽象类 输出字符流基类
-----------| FileWriter 输出字符流管道
-----------| BuffereWriter 缓冲输出字符流(维护了一个1024个长度的字符数组) 拓展功能---->newLine()
File类仅能
获取文件的属性数据
修改文件的属性数据
不能读取文件内容数据
操作文件内容数据需要学习---> "IO流"技术
IO流类别:
1. 流向划分:输入流 + 输出流
以当前程序作为参照物,数据流入则使用输入流, 数据流出则使用输出流。
2. 处理单位:
字节流:读取文件的(纯)字节数据
字符流:读取字节数据+解码字节数据
输入字节流:
------| InputStream 输入字节流基类
-----------| FileInputStream 输入字节流管道
-----------| BufferedInputStream 缓冲输入字节流(内部维护了一个8kb的字节数组)
使用 FileInputStream 读取文件数据:
1.找到目标文件
2.建立数据的输入通道
3.读取文件的数据
--------------------------------------------------------------
先理解两个方法:string和read
public int read(byte[] b) throws IOException
从输入流中将最多 b.length 个字节的数据读入一个字节数组中
覆盖:类 InputStream 中的 read
参数:b 缓冲数组
返回:读入缓冲区的字节总数,如果已经到达文件末尾,则返回 -1。
抛出:IOException - 如果发生 I/O 错误。
public String(byte[] bytes, int offset, int length)
构造一个新的 String,方法是使用指定的字符集解码字节的指定子数组。
新的 String 的长度是一个字符集函数,因此不能等于该子数组的长度。
参数:
bytes - 要解码为字符的字节
offset - 要解码的首字节的索引
length - 要解码的字节数
方式一:使用 循环 配合 缓冲数组 读取(用这个)
File file = new File("F:\\a.txt"); //获取目标文件对象
//建立数据的通道
FileInputStream fileInputStream= new FileInputStream(file);
//读取数据
byte[] buf = new byte[1024]; //缓冲字节数组的长度一般都是1024的倍数。
int length = 0 ; //记录本次读取的自己个数。
while((length = fileInputStream.read(buf))!=-1){
System.out.print(new String(buf,0,length));
}
fileInputStream.close(); //关闭资源(释放资源文件)
注意用System.out.print 不要用System.out.println因为读取完会换行
--------------------------------------------------------------------
方式二:使用(缓冲数组)字节数组读取 :无法完整读取一个文件的数据
//找到目标文件
File file = new File("F:\\a.txt");
//建立数据的通道
FileInputStream fileInputStream= new FileInputStream(file);
//创建一个字节数组,读取文件数据
byte[] buf = new byte[10];
//read(byte[] buf) 先把读取到的数据存储到字节数组中,然后返回的是本次读取到字节数。
int length = fileInputStream.read(buf);
System.out.println("读取到的内容:"+ new String(buf,0,length));
------------------------------------------------------------------------------------------------------------------------
方式三:每次读取一个字节的数据,可以读取完整文件数据 (效率低)
// 第一步:找到目标文件
File file = new File("g:/a.txt");
// 第二步: 建立数据通道
FileInputStream fileInputStream = new FileInputStream(file);
// 第三步:读取文件的数据
int content = 0; // 用于保存读取到的数据
while ((content = fileInputStream.read()) != -1) {
// read() 方法如果读取了文件的末尾则返回-1表示。
System.out.print((char) content);
}
// 关闭资源
fileInputStream.close();
================================================================
输出字节流:
------| OutputStream 输出字节流基类
-----------| FileOutputStream 输出字节流管道
-----------| BufferedOutputStream 缓冲输出字节流(内部维护了一个8kb的字节数组)
使用FileOutputStream步骤:
1. 找到目标文件
2. 建立数据的输出通道
3.写入文件
理解write方法:
public void write(byte[] b) throws IOException
将 b.length 个字节从指定字节数组写入此文件输出流中
write(byte[] b, int off, int len)
FileOutputStream要注意的细节:
1. new FileOutputStream 目标文件不存在会先创建目标然后再写入。
2. new FileOutputStream(file) 目标文件已经存在,先清空然后再写入。
3. 以追加的形式写入,需要使用new FileOutputStream(file,true) 构造函数。
4. 使用write(int b)方法实际上只会把数据的低八位写出,其他位丢弃。
方式一:普通方法(getByte()方法转换成字节数组) 新建写入
// 找到目标文件
File file = new File("F:\\a.txt");
// 建立数据的输出通道
FileOutputStream fileOutputStream = new FileOutputStream(file);
String data = "abcd";
byte[] buf = data.getBytes(); // 转换成字节数组97 98 99 100
fileOutputStream.write(buf, 0, 2); // 指定开始的索引值与字节个数写出。
fileOutputStream.close();
方式二:追加写入FileOutputStream(file,true)
// 找到目标文件
File file = new File("F:\\a.txt");
// 建立数据的输出通道
FileOutputStream fileOutputStream = new FileOutputStream(file, true);
// 第二个参数为true时,写入文件数据就是以追加的形式写入的
// 准备数据, 把数据写出
String str = "\r\nhello world";
// 把字符串转成字节数组
byte[] buf = str.getBytes();
// 把字节数组写出
fileOutputStream.write(buf);
// 关闭资源
fileOutputStream.close();
应用:拷贝图片
File infile=new File("g:/a.jpg");
File outfile=new File("f:/女神.jpg");
FileInputStream fi=new FileInputStream(infile);
FileOutputStream fo=new FileOutputStream(outfile);
byte[] buf=new byte[1024];
int length=0;
while((length=fi.read(buf))!=-1){
fo.write(buf, 0, length);
}
fo.close();
fi.close();
IO异常处理:
应用一:比较正常的操作
public static void main(String[] args) {
readTest();
}
public static void readTest() {
FileInputStream fileInputStream = null;
try {
File file = new File("g:\\a.txt");
// 建立文件的输入流通道
fileInputStream = new FileInputStream(file);
// 建立缓冲字节数组读取文件数据
byte[] buf = new byte[1024];
int length = 0; // 记录本次读取的字节个数
// 读取文件的数据
while ((length = fileInputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, length));
}
} catch (IOException e) {
System.out.println("读取文件出错...");
throw new RuntimeException(e);
// 把真正的异常原因包装到RuntimeException中然后再抛出。
} finally {
try {
// 关闭资源()
if (fileInputStream != null) {
fileInputStream.close();
System.out.println("关闭资源成功...");
}
} catch (IOException e) {
System.out.println("关闭资源失败...");
throw new RuntimeException(e);
}
}
}
应用二:拷贝文件 读写操作都具备的异常
public static void main(String[] args) {
copyImage();
}
// 拷贝图片
public static void copyImage() {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
// 找到目标文件
File inFile = new File("g:/a.jpg");
File outFile = new File("F:/拷贝.jpg");
// 建立数据的输入输出通道
fileInputStream = new FileInputStream(inFile);
fileOutputStream = new FileOutputStream(outFile);
// 建立缓冲字节数组,边读边写
byte[] buf = new byte[1024];
int length = 0;
while ((length = fileInputStream.read(buf)) != -1) {
fileOutputStream.write(buf, 0, length);
}
} catch (IOException e) {
System.out.println("拷贝出错了...");
throw new RuntimeException(e);
// 关闭资源的原则: 先开后关, 后开先关。
} finally {
try {
if (fileOutputStream != null) {
// 关闭资源
fileOutputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
缓冲字节流
缓冲输入字节流 BufferedInputStream 作用: 提高读取文件数据的效率
缓冲输出字节流 BufferedOutputStream 作用: 提高读写文件数据的效率
注意:凡是缓冲流都没有读写文件的能力,只是内部维护数组,提高效率(类似内存读取)
BufferedInputStream
BufferedInputStream没有读取文件 数据的能力,但是又要读取文件的数据,这时候只能依赖一个具备读取文件数据能力的对象。
应用代码1: 读取效率不怎么高的,不想用
public static void main(String[] args) throws IOException {
readTest();
}
// 因为内部判断,读取大文件时效率并不怎么高的不如用 :字节数组+循环
public static void readTest() throws IOException {
// 第一步:找到目标文件
File file = new File("g:\\a.txt");
// 第二步:建立文件与程序的输入通道
FileInputStream fileInputStream = new FileInputStream(file);
// 第三部:建立缓冲输入字节流
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
// 读取文件数据
int content = 0;
while ((content = bufferedInputStream.read()) != -1) {
System.out.print((char) content);
}
// 关闭资源
bufferedInputStream.close();
}
BufferedOutputStream
注意:
1.BufferedOutputStream的write方法,数据只是写入了BufferedOutputStream内部维护的字节数组中,只有调用BufferedOutputStream的close方法或者flush方法数据才会真正的写到硬盘上 ;或者内部维护的字节数组数据已经存储满,这时数据也会写到硬盘
2. BufferedOutputStream的close方法实际上关闭的是传入的OutputStream对象的 close方法
应用代码1:
public static void main(String[] args) throws IOException {
// 找到目标文件对象
File file = new File("f:/d.txt");
// 建立数据的输出通道
FileOutputStream fileOutputStream = new FileOutputStream(file);
// 建立缓冲输出字节流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
// 写数据
String data = "hello world";
bufferedOutputStream.write(data.getBytes());
// bufferedOutputStream.flush(); //把缓冲字节数组的数据写到硬盘上去。
bufferedOutputStream.close();
}
字符流 = 字节流+ 编码(解码) 读取 的数据是以字符为单位
输入字符流
-----| Reader
-----------| FileReader
-----------| BUfferedReader
-----| Writer
-----------| FileWriter
-----------| BuffereWriter
字节流可以写中文,但不会读中文,因为字节流不会编码;字节流之所以可以写中文,是因为它借用了String类的getBytes方法,把字符串转成了数字。
public byte[] getBytes() 使用平台默认的字符集将此 String 解码为字节序列,并将结果存储到一个新的字节数组中。
FileWriter 使用步骤:
1. 找到目标文件
2. 建立数据的输出通道
3. 写出数据
4. 关闭资源
方式一:每次只会读取一个字符的数据
public static void readTest1() throws IOException {
// 找到目标对象
File file = new File("f:\\a.txt");
// 建立数据的输入通道
FileReader fileReader = new FileReader(file);
// 读取文件数据
int content = 0;
while ((content = fileReader.read()) != -1) {
// FileReader的read()方法每次读取一个字符的数据,如果读到
// 了文件末尾返回-1表示。
System.out.print((char) content);
}
// 关闭资源
fileReader.close();
}
// 方式二:缓冲数组(推荐)
public static void readTest2() throws IOException {
// 找到目标文件
File file = new File("F:\\Demo1.java");
// 建立数据的输入通道
FileReader fileReader = new FileReader(file);
// 建立缓冲字符数组,读取文件的数据
char[] buf = new char[1024];
int length = 0;
// read(char[] buf) 读取到的字符数组存储到了字符数组中,返回了本次读取到的字符个数。
while ((length = fileReader.read(buf)) != -1) {
System.out.print(new String(buf, 0, length));
}
// 关闭资源
fileReader.close();
}
FileWriter 注意:
1.使用new FileWriter(file)时,目标文件不存在则先创建;存在不创建。
2.使用new FileWriter(file)构造方法时,先清空文本的数据,再写入新的数据。
3.需要追加数据则需要使用 new FileWriter(file,true)构造方法
4.使用FileWriter的write方法的时候,数据只是写入了FileWriter内部维护的字符数组中,把数据真正的写到硬盘上去,需要调用flush方法或者 是close方法或者是内部维护的字符数组已经满了,这时也会写到硬盘
public static void readTest2() throws IOException {
// 找到目标文件
File file = new File("f:\\a.txt");
// 建立数据的输入通道
FileReader fileReader = new FileReader(file);
// 建立缓冲字符数组,读取文件的数据
char[] buf = new char[1024];
int length = 0;
// read(char[] buf) 读取到的字符数组存储到了字符数组中,返回了本次读取到的字符个数。
while ((length = fileReader.read(buf)) != -1) {
System.out.print(new String(buf, 0, length));
}
// 关闭资源
fileReader.close();
}
字符流和字节流选用:
纯文本数据:使用字符流。(txt)
非文本数据:使用字节流。(图片,视频,音频,word)
拷贝文件应用:
public static void main(String[] args) throws IOException {
// 找到目标文件
File inFile = new File("g:/a.txt");
File outFile = new File("E:/b.txt");
// 建立数据 的输入输出通道
FileReader fileReader = new FileReader(inFile);
FileWriter fileWriter = new FileWriter(outFile);
// 边写边读
char[] buf = new char[1024];
int length = 0;
while ((length = fileReader.read(buf)) != -1) {
fileWriter.write(buf, 0, length);
// System.out.print(new String(buf, 0, length));
}
// 关闭资源
fileWriter.close();
fileReader.close();
}
BufferedReader 缓冲输入字符流 作用:提高读取文件字符数据的效率
对FileReader的功能进行了拓展---readLine()。
public String readLine() throws IOException
读取一个文本行。
返回:该行内容的字符串,如果已到达流末尾,则返回 null
File file = new File("G:\\a.txt");
// 建立文件的输入通道。
FileReader fileReader = new FileReader(file);
// 缓冲输入字符流
BufferedReader bufferedReader = new BufferedReader(fileReader);
// 读取文件的数据
String line = null;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(Arrays.toString(line.getBytes()));
}
// 关闭资源
bufferedReader.close();
BufferedWriter 缓冲输出字符流 作用:提高写入文件字符数据的效率
// 找到目标文件
File file = new File("f:\\a.txt");
// 建立数据输出通道
FileWriter fileWriter = new FileWriter(file, true);
// 建立缓冲输出字符流
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
// 准备数据,把数据写出
bufferedWriter.newLine();
bufferedWriter.write("奥特曼");
// 刷新一个缓冲区
bufferedWriter.close();