4KB【读取】原理
我们文件的大小和所占空间的大小往往是不同的,文件大小为实际大小,而占用空间的大小是方便内存读取的。
为了减轻CPU的读取压力,提高读取效率,CPU向内存读取数据往往不是一个字节一个字节读取的,而是以4KB为单位读取,所以内存想硬盘文件的读取也是4KB,这也就是为什么文件所占空间大小都是4的倍数。
文件字节流
输入InputStream,常用子类FileInputStream
一、构造方法
//根据传入的File类对象,操作对应的文件
FileInputStream(File file);
//根据传入的String类型文件路径,操作对应文件
FileInputStream(String pathName);
二、读取文件的基本流程
- 获取该文件
- 判断文件是否存在,是否为一个普通文件
- 创建FileInputStream管道
- 读取数据
- 关闭管道
三、获取文件数据方法
1. int read() 方法【不推荐】
该方法返回值是读取到的字节数据,文件内容的第一个字节的数据,,如果读取到文件末尾,返回-1 EOF(End Of File),不推荐的原因:
|--- 每一次只能读取一个字节,所以需要循环遍历,不能用于中文
|--- 浪费4KB空间
|--- 反复从硬盘读取数据(每次循环),效率低,对硬盘也有损伤
//代码演示
public class Demo1 {
public static void main(String[] args) throws IOException {
//1.获取文件
File file = new File("D:\\Java\\md.txt");
//2.判断是否为普通文件
if (!file.isFile()) {
throw new FileNotFoundException();
}
//3.创建输入流管道
FileInputStream fis = new FileInputStream(file);
//4.读取,content记录字节,后面转char
int content = -1;
while ((content = fis.read()) != -1) {
System.out.println((char) content);
}
//5.关闭资源
fis.close();
}
}
2. 使用缓存的方法
自定义buffer,其大小决定了读取量的大小,即缓冲空间大小,一次性读满缓冲量再输出,提高效率,保护硬盘
//两种方法
int read(byte[] buffer);
int read(byte[] buffer, int offset, int length);
//代码演示(仅演示读取部分)
int length = -1;
//设置一个4KB的缓存空间
byte[] buffer = new byte[1024 * 4];
while ((length= fis.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, length)); //字符串形式打印
}
输出OutputStream,常用子类FileOutputStream
一、构造方法
//覆盖写
FileOutputStream(File file);
FileOutputStream(String pathName);
//追加写
FileOutputStream(File file, boolean append);
FileOutputStream(String pathName, boolean append);
二、写入文件的基本流程
- 找到目标文件(文件可以存在,可以不存在,要求操作的文件必须有后缀名)
- 创建FileOutputStream管道,如果文件不存在,而且当前操作的文件夹有写入权限,可以自动创建目标文件
- 写入数据
- 关闭管道
三、写入文件数据方法
1. void write(int i) 方法【不推荐】
该方法对参数默认强转为int类型,这里可以输入任意类型,使用很少
一方面损失硬盘,另一方面强转会产生问题,代码演示:
public class Demo2 {
public static void main(String[] args) throws IOException {
//1.获取文件
File file = new File("D:\\Java\\md2.txt");
//2.创建输出流管道
FileOutputStream fos = new FileOutputStream(file, true);
//3.写入
fos.write('o');
fos.write(353);
//4.关闭资源
fos.close();
}
}
//文本中的结果为
oa
/**
* 强转原理:
* 1.传入的353位int类型,即4字节,32位,完整二进制为: 0000 0000 0000 0000 0000 0001 0110 0001
* 2.强制转为低八位,即0110 0001,十进制就是97,即a
*/
2. 使用缓存的方法
void write(byte[] buffer);
void write(byte[] buffer, int offset, int length);
//代码演示
public class Demo1 {
public static void main(String[] args) throws IOException {
//1.获取文件
File file = new File("D:\\Java\\md.txt");
//2.创建输出流管道
FileOutputStream fos = new FileOutputStream(file, true);
//3.写入
String str = "\r\nWorld of WarCraft"; //\r\n 表示换行
byte[] buffer = str.getBytes();
fos.write(buffer);
fos.flush();
//4.关闭资源
fos.close();
}
}
使用字节流拷贝文件
拷贝流程:
- 确定源文件src
- 判断原文件是否存在,是否是一个普通文件
- 确定拷贝目标文件dst
- 打开输入输出管道
- 利用字节数组作为缓冲读取和写入文件
- 关闭资源,原则是先开后关,后开先关
public class Demo1 {
public static void main(String[] args) throws IOException {
//1.获取文件
File srcfile = new File("D:\\Java\\流.png");
//2.判断是否存在
if (!srcfile.isFile()) {
throw new FileNotFoundException();
}
//3.确定拷贝的目标位置
File dstFile = new File("D:\\Java\\流2.png");
//4.创建输入输出流管道
FileInputStream fis = new FileInputStream(srcfile);
FileOutputStream fos = new FileOutputStream(dstFile);
//5.拷贝
int len = -1;
byte[] buffer = new byte[1024 * 4];
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
fos.flush(); //清空缓存,存储到硬盘,避免因为断电等原因,导致数据丢失
}
//6.关闭资源
fos.close();
fis.close();
}
}
文件字符流
输入字符流Reader,常用子类FileReader
构造方法
FileReader(File file);
FileReader(String path);
读取文件数据方法
int read() 方法,一次只读取一个字符,返回的是字符编码,不建议使用
缓冲字符流读取:
//方法
int read(char[] cbuf);
//代码演示
public class Demo3 {
public static void main(String[] args) throws IOException {
File file = new File("D:\\Java\\md2.txt");
FileReader fr = new FileReader(file);
//字符读取
int len = -1;
char[] buffer = new char[4 * 1024];
while ((len = fr.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, len));
}
fr.close();
}
}
输出字符流Writer,常用子类FileWriter
构造方法
FileWriter(File file, booean append);
FileWriter(String pathName, boolean append);
写入文件数据方法
//方法
void write(char[] buf);
void write(String str);
//代码演示
public class Demo3 {
public static void main(String[] args) throws IOException {
File file = new File("D:\\Java\\md2.txt");
FileWriter fw = new FileWriter(file);
String str = "为了联盟!!!\r\n";
fw.write(str);
fw.flush();
fr.close();
}
}
注意事项
- 采用字符流读取文件,会把文件中的内容看做是字符来处理, 比如图片会按照当前编码集的字符编码来读取数据,有可能导致读取到一些在编码集之外的编码, 计算机会认为是无效编码,扔掉这部分数据,从而导致图片文件损坏,变大或变小
- 字符流能够操作的文件只能是用notepad/txt文本编辑打开的普通文件
- 【字节流】可以处理所有文件, 是最常用!!! 网络端传输,音视频传输,数据的拷贝