IO流原理及流的分类
Java IO 流原理
流的分类
字节流在处理二进制文件的时候有好处:声音文件,视频文件,word文件等等·····可以保证文件是无损文件。
字符流则是文本文件用它处理比较好。
字节流分为字节输入流和字节输出流。对应的顶级父类是InputStream和OutPutStream。
字符流分为字符输入流和字符输出流。对应的顶级父类是Reader和Writer。
InputStream和OutPutStream、Reader和Writer,都是抽象类,我们在使用的时候,去创建它们的实现子类才可以。
IO 流体系图-常用的类
IO 流体系图
流和文件区别
关于流的理解我们通过一个例子来说明:
平时我们在网上买商品的时候,物品是买到了,但是需要通过外卖小哥把快递从物流中心送到用户手上,而用户不满意的时候还是需要外卖小哥帮我们拿快递拿去退换,这是一个很简单的例子。
可以这么说:流是数据交换的媒介
FileInputStream 介绍
FileInputStream是文件输入流
/** * 演示读取文件... * 单个字节读取,效率比较低 */ @Test public void readFile01() throws IOException { String filePath="e:\\hello.txt"; int readData=0; FileInputStream fileInputStream=null; try { //创建FileInputStream对象,用于读取文件 fileInputStream = new FileInputStream(filePath); /** * 从该输入流读取一个字节的数据。如果没有输入可用,此方法将阻止。 * 如果返回-1,表示读取完毕,那么读的话肯定是循环读取,不可能只读取一个字节。 * 那么while的条件就是如果不等于-1就一直读取 */ while((readData = fileInputStream.read())!=-1){ //读完了后把数据放入readData,判断是否等于-1,如果不等于就继续读,返回-1就一直读 System.out.print((char)readData); //转成char显示 } } catch (IOException e) { e.printStackTrace(); } finally { //关闭文件流,释放资源 fileInputStream.close(); } }
虽然可以读取到文件的内容,hello.txt里面的内容是:hello,world!这种方法是可以读取出来的,但是文本里面要是有个中文我们读取出来就是乱码。
FileOutputStream 介绍
要求: 请使用 FileOutputStream 在 a.txt 文件,中写入 “hello,world”
/** * 演示FileOutputStream 将数据写入到文件中 * 如果文件不存在,则创建该文件 */ @Test public void writeFile() { //创建FileOutputStream对象 String filePath = "e:\\a.txt"; FileOutputStream fileOutputStream = null; try { /** * 得到FileOutputStream对象 * 说明 * 1. new FileOutputStream(filePath) 创建方式,当写入内容时,会覆盖原来的内容 * 2. 如果不想覆盖,要追加的方式把内容加入 * new FileOutputStream(filePath,true); * 可以在后面加入个true,就可以追加在后面 */ fileOutputStream = new FileOutputStream(filePath,true); //写入一个字符串 String str = "godairo"; //这个方法可以把一个字符串转成字节数组 fileOutputStream.write(str.getBytes()); System.out.println("写入成功!!"); } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
要求: 编程完成图片/音乐 的拷贝
package com.godairo.outputStream_; import java.io.*; /** * @author GodAiro * Creation Time: 2022/7/23 10:08. */ public class FileCopy { public static void main(String[] args) throws IOException { //完成文件拷贝,将e:\\PPT图片\\222.jpg 拷贝到 d:\\ //思路分析 //1.创建文件的输入流,把e盘的文件读入到程序 //2.创建文件的输出流,将读取到的文件数据写入到指定的位置 String srcFilePath="e:\\PPT图片\\222.jpg"; String destFilePath="d:\\222.jpg"; FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(srcFilePath); fileOutputStream = new FileOutputStream(destFilePath); //定义一个字节数组,提高读取效率 byte[] buf = new byte[1024]; int readLen = 0; //一次读取几个? while((readLen=fileInputStream.read(buf))!=-1){ /** * 读取到后,就写入到文件,通过fileOutputStream * 即,一边读,一边写 * * 一定要使用这个方法:fileOutputStream.write(buf,0,readLen); * 如果使用fileOutputStream.write(buf);以下举个例子说明 * 如果这个文件有1039个字节,我们设置了一次读取1024,但是还剩下的几个字节还是以1024读取,那就会造成文件损失。 */ fileOutputStream.write(buf,0,readLen); } System.out.println("拷贝成功!"); } catch (IOException e) { e.printStackTrace(); } finally { if (fileInputStream!=null){ fileInputStream.close(); } if (fileOutputStream!=null){ fileInputStream.close(); } } } }
这里要注意的是,读取部分数据的时候就需要写入到指定文件,这里使用的是循环操作。
FileReader 介绍
相关方法:
package com.godairo.reader_; import org.junit.Test; import java.io.FileReader; import java.io.IOException; /** * @author GodAiro * Creation Time: 2022/7/23 10:43. */ @SuppressWarnings({"all"}) public class FileReader_ { public static void main(String[] args) { } @Test //单个字符读取文件 public void readFile01() { String filePath = "e:\\story.txt"; FileReader fileReader = null; int data = 0; //1. 创建一个FileReader对象 try { fileReader = new FileReader(filePath); //循环读取 使用read long start = System.currentTimeMillis(); while ((data = fileReader.read()) != -1) { System.out.print((char) data); } long end = System.currentTimeMillis(); System.out.println("耗时:" + (end - start)); } catch (IOException e) { e.printStackTrace(); } finally { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test /** * 使用字符数组读取文件 */ public void readFile02() { String filePath = "e:\\story.txt"; FileReader fileReader = null; int readLen = 0; char[] buf = new char[8]; //1. 创建一个FileReader对象 try { fileReader = new FileReader(filePath); /** * 循环读取 使用read(buf),返回的是实际读取到的字符数 * 如果返回-1 说明文件结束 */ long start = System.currentTimeMillis(); while ((readLen = fileReader.read(buf)) != -1) { System.out.print(new String(buf, 0, readLen)); } long end = System.currentTimeMillis(); System.out.println("耗时:" + (end - start)); } catch (IOException e) { e.printStackTrace(); } finally { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
readFile01()这个方法是单个字符单个字符的读取,效率比较慢,而readFile02()可以设置8个字符8个字符读取,效率比较快。
我们可以试着比较一下。
这是readFile01()的耗时:
这是readFile02()的耗时:
FileWriter 介绍
package com.godairo.writer_;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author GodAiro
* Creation Time: 2022/7/23 14:30.
*/
public class FileWriter_ {
public static void main(String[] args) {
String filePath="e:\\note.txt";
//创建FileWriter对象
FileWriter fileWriter = null;
char[] chars={'a','b','c'};
try {
fileWriter = new FileWriter(filePath);
//write(int):写入单个字符
fileWriter.write('H');
//write(char[]):写入指定数组
fileWriter.write(chars);
//write(char[],off,len)
fileWriter.write("取前三个啊哈".toCharArray(),0,3);
//write(string):写入整个字符串
fileWriter.write("你好,北京~");
//write(string,off,len):写入字符串的指定部分
fileWriter.write("上海天津",0,2);//意思就是从下标为0的位置从右取两个字符进去,这样的话天津就没了!
} catch (IOException e) {
e.printStackTrace();
}finally {
//对应FileWriter,一定要关闭流,或者flush,才能真正的把数据写入到文件
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}