Javase 基础加强 —— 08 IO流
本系列为笔者学习Javase的课堂笔记,视频资源为B站黑马程序员出品的《黑马程序员Java+AI智能辅助编程全套视频教程,java零基础入门到大牛一套通关》,章节分布参考视频教程,为同样学习Javase系列课程的同学们提供参考。
01 概述
内存和磁盘有啥区别呀?
- 内存(RAM,随机访问存储器):是计算机中运行程序时临时存储数据的地方。程序运行时,代码和数据会从硬盘加载到内存里,然后CPU直接从内存读写数据,速度非常快。
- 磁盘(硬盘,HDD或固态硬盘SSD):是计算机长期存储数据的地方,保存操作系统、程序、图片、视频等文件。断电后数据依然保留,容量通常比内存大很多。
02 IO 流的体系
- 字节输入流
InputStream
(读字节数据的) - 字节输出流
OutputStream
(写字节数据出去的) - 字符输入流
Reader
(读字符数据的) - 字符输出流
Writer
(写字符数据出去的)
03 文件字节输入流
FileInputstream
(文件字节输入流) 是以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
package FileDemo;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;public class InputStreamDemo1 {public static void main(String[] args) throws Exception {//目标:文件字节输入流//1.创建文件字节输入流管道,接通源文件//a.绝对路径//InputStream is = new FileInputStream(new File("E:\\JAVA\\javase0331\\0416-oop\\src\\FileDemo\\name.txt"));//b.相对路径InputStream is = new FileInputStream(new File("0416-oop\\src\\FileDemo\\name.txt"));//2.读取文件字节,输出//a.一个一个读int b;while((b = is.read()) != -1){System.out.print((char) b);}//b.一批一批读byte[] buffer = new byte[3];int len;while((len = is.read(buffer)) != -1){String str = new String(buffer, 0, len);System.out.print(str);}//注:存在截断文字3字节的隐患!可以一次性读完所有字节以避免该问题。//3.关闭文件字节输出流is.close();}
}
04 文件字节输出流
package FileDemo;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;public class OutputStreamDemo1 {public static void main(String[] args) throws Exception {//目标:文件字节输出流//1.创建文件字节输出流管道,接通目标文件//OutputStream os = new FileOutputStream(new File("0416-oop\\src\\FileDemo\\name2.txt"));//true代表数据追加OutputStream os = new FileOutputStream(new File("0416-oop\\src\\FileDemo\\name2.txt"), true);//2.写入数据,输出os.write(97);os.write('a');os.write("\r\n".getBytes());byte[] bytes = "我爱你中国666".getBytes();os.write(bytes);os.write("\r\n".getBytes());os.write(bytes, 0, 3);os.write("\r\n".getBytes());//3.关闭文件字节输出流os.close();}
}
os.write("\r\n".getBytes());
啥意思?
"\r\n"
是回车换行符,也就是Windows
系统的换行表示(Carriage Return + Line Feed)
。"".getBytes()
是把这个字符串转换成字节数组(byte[]),因为os.write()
方法需要的是字节数组。os
是一个输出流(OutputStream)
,通过write(byte[] b)
方法向流中写入数据。
05 案例:文件复制
package FileDemo;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;public class CopyDemo {public static void main(String[] args) {//目标:文件复制//源文件:E:\JAVA\IMG_4623.jpg//目标文件:D:\IMG_4623.jpgtry{copyFile("E:\\JAVA\\IMG_4623.jpg","D:\\IMG_4623.jpg");}catch (Exception e){e.printStackTrace();}}public static void copyFile(String srcPath, String destPath) throws Exception {//1.创建文件字节输入输出流管道FileInputStream fis = new FileInputStream(srcPath);FileOutputStream fos = new FileOutputStream(destPath);//2.读取一个字节数组,写入一个字节数组byte[] buffer = new byte[1024];int len;while((len = fis.read(buffer)) != -1){fos.write(buffer, 0, len); //读多少,倒多少}System.out.println("复制成功!");//3.非专业关闭fos.close();fis.close();}
}
任何文件的底层都是字节,字节流做复制,是一字不漏的转移完全部字节,只要复制后的文件格式一致就没问题!
06 资源释放
Ctrl + Alt + T
召唤try/catch
package FileDemo;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class CopyDemo {public static void main(String[] args) {//目标:文件复制//源文件:E:\JAVA\IMG_4623.jpg//目标文件:D:\IMG_4623.jpgcopyFile("E:\\JAVA\\IMG_4623.jpg","D:\\IMG_4623.jpg");}public static void copyFile(String srcPath, String destPath){FileInputStream fis = null;FileOutputStream fos = null;try {//1.创建文件字节输入输出流管道fis = new FileInputStream(srcPath);fos = new FileOutputStream(destPath);//2.读取一个字节数组,写入一个字节数组byte[] buffer = new byte[1024];int len;while((len = fis.read(buffer)) != -1){fos.write(buffer, 0, len); //读多少,倒多少}System.out.println("复制成功!");} catch (IOException e) {e.printStackTrace();} finally {//3.专业关闭(臃肿)try {if(fos != null) fos.close();} catch (IOException e) {e.printStackTrace();}try {if(fis != null) fis.close();} catch (IOException e) {e.printStackTrace();}}}
}
finally
代码区的特点为,无论try
中的程序是正常执行了,还是出现了异常,最后都一定会执行finally
区,除非JVM
终止,其一般用于在程序执行完成后进行资源的释放操作(专业级做法)。
public static void copyFile(String srcPath, String destPath){try (//1.创建文件字节输入输出流管道FileInputStream fis = new FileInputStream(srcPath);FileOutputStream fos = new FileOutputStream(destPath);){//2.读取一个字节数组,写入一个字节数组byte[] buffer = new byte[1024];int len;while((len = fis.read(buffer)) != -1){fos.write(buffer, 0, len); //读多少,倒多少}System.out.println("复制成功!");} catch (IOException e) {e.printStackTrace();}
}
注:()
中只能放资源,否则报错,而资源一般是指最终实现了AutoCloseable
接口。
07 文件字符输入流
FileReader
文件字符输入流是以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
package FileDemo;import java.io.FileReader;
import java.io.Reader;public class FileReaderDemo1 {public static void main(String[] args) {//目标:文件字符输入流//1.创建文件字符输入流管道try (Reader f1 = new FileReader("0416-oop\\src\\FileDemo\\name.txt")) {//2.定义一个字符数组,一次读取多个字符char[] chars = new char[3];int len;while((len = f1.read(chars)) != -1){String str = new String(chars, 0, len);System.out.print(str); //不要换行!}}catch (Exception e){e.printStackTrace();}}
}
注:文件字符输入流一次读取多个字符,按照字符读取中文,性能好,速度高。
08 文件字符输出流
FileWriter
文件字符输出流是以内存为基准,把内存中的数据以字符的形式写出到文件中去。
package FileDemo;import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;public class FileWriterDemo1 {public static void main(String[] args) {try {//1.创建文件字符输出流管道Writer w1 = new FileWriter("0416-oop\\src\\FileDemo\\name2.txt");//2.写一个字符w1.write(98);w1.write('c');w1.write('戈');//3.写一个字符串w1.write("java");w1.write("亲爱的你躲在哪里发呆");//4.写一个字符数组char[] chars = "javaWeb".toCharArray();w1.write(chars);w1.write(chars, 0, 3);//5.刷新内存缓冲区//w1.flush(); //嘿嘿,上面()自动关闭流} catch (IOException e) {e.printStackTrace();}}
}
注:字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效。
注:刷新后,流可以继续使用,关闭后,流不能继续使用。