在java中,计算机中所有的文件和目录都用File这个类描述,IO input与output对文件进行数据的写入与读取。
File类会自动甄别文件系统路径Linux/Windows,因为Linux/Unix/Windows/MAC这些操作系统中 路径分割符是不统一的,当我们不确定程序所运行的系统环境 如果需要用到文件路径 路径分割符采用File自带的separator方法
File:
| 方法 | 说明 |
| exist() | 判断文件是否存在 |
| getAbsolutePath() | 打印文件的绝对路径 |
| getName() | 获取文件名 |
| getPath() | 获取相对路径 |
| length() | 获取文件大小 单位字节 b |
| mkdir() | 创建一个目录 |
| mkdirs() | 若果创建多级目录用mkdirs |
| delete() | 删除文件 |
| list() | 返回该目录下第一层级的所有文件和目录的名字的字符串数组 |
从文件中读取输入到内存 输入流
从内存把数据写入带文件 输出流
流就是文件到内存的一个桥梁 数据传输的载体 单向
按照方向
输入流
输出流
按照数据的类型
字节流
字符流
对于任何OS来说 文件最终都是以二进制的形式存储在硬盘里
.txt .mp3 .avi .doc 最终都是二进制文件
但是对于.txt .java .py .cpp 这些文件而言 唯一存储的数据是字符
所以对于上述文件的操作 既可以是字节流操作 字符流操作
注意:字符流只能针对纯文本文件 .doc不算纯文本文件
字符流 = 字节流 + 编码表
FileOutputStream 文件字节输出流
File f1 = new File("test01.txt");
//如果文件不存在 则创建
//如果文件存在 删除原先的再创建 - 覆盖
//如果路径不存在 则报错
//如果关联的是目录 报错
FileOutputStream fos = new FileOutputStream(f1);
fos.write(97);
fos.write(100);
String info = "I Love U";
byte[] bytes = info.getBytes();
//字符串 -> 字节 编码
System.out.println(Arrays.toString(bytes));
fos.write(bytes);
//用文本程序打开一个文本文件 读取字节 经过码表 得到字符
//字节 -> 字符串 解码
fos.close(); //关闭流
InputStream 字节输入流
FileInputStream 文件字节输入流
File f1 = new File("test01.txt");
//如果存在 则正常
//如果不存在 则报错
FileInputStream fis = new FileInputStream(f1);
//此处在Windows读取换行时 rn
StringBuilder sb = new StringBuilder();
byte[] buff = new byte[4];
int len = 0;
while ((len = fis.read(buff)) != -1) {
sb.append(new String(buff,0,len));
}
System.out.println(sb.toString());
//read()一个一个读取
复制文件夹操作+过滤
public static void main(String[] args) {
//选择桌面文件
File sourceDir = new File("C:\Users\xiaoJin\Desktop\Java");
File copyDir = new File("D:\Java_Copy");
copy(sourceDir,copyDir);
// deleteEmptyDir(copyDir);
}
private static void deleteEmptyDir(File copyDir) {
File[] files = copyDir.listFiles();
if (files == null || files.length == 0) {
System.out.println(copyDir.getName() + "被删掉了");
System.out.println(copyDir.delete());
}
for (File file : files) {
if (file.isDirectory()) {
deleteEmptyDir(file);
}
}
files = copyDir.listFiles();
if (files == null || files.length == 0) {
System.out.println(copyDir.getName() + "被删掉了");
System.out.println(copyDir.delete());
}
}
private static void copy(File sourceDir, File copyDir) {
if (!copyDir.exists()) {
copyDir.mkdir();
}
//创建过滤器对象
MyFileFilter mff = new MyFileFilter();
File[] files = sourceDir.listFiles(mff);
if (files == null) {
return;
}
for (File file : files) {
if (file.isFile()) {
String sourceFilePath = file.getAbsolutePath();
String copyFilePath = copyDir.getAbsolutePath() + File.separator + file.getName();
copyFile(sourceFilePath,copyFilePath);
} else {
copy(file,new File(copyDir.getAbsolutePath() + File.separator + file.getName()));//循环递归
}
}
}
private static void copyFile(String sourceFilePath, String copyFilePath) {
File sourceFile = new File(sourceFilePath);
File copyFile = new File(copyFilePath);
FileInputStream fis = null;
FileOutputStream fos = null;
try {//文件写入
fis = new FileInputStream(sourceFile);
fos = new FileOutputStream(copyFile);
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
fos.write(buf,0,len);
}
} catch (IOException e ) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//提取文件尾部为".java"的过滤器
public static class MyFileFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".java") || pathname.isDirectory();
}
}
BufferedInputStream与BufferedOutputStream缓冲流 目的就是为了提高IO效率 缓冲大小8mb
FileInputStream而言
无论是read()一个字节一个字节读取
还是read(byte[])一堆字节一堆字节读取
它们都是直接从硬盘上读取数据的
如果文件中有1000个字节的数据 每次对硬盘进行一次读取操作假设是1秒
read() 需要 1000秒
read(byte[10]) 需要100秒
BufferedInputStream 自身也带一个缓冲区
并且BufferedInputStream是其它InputStream(FileInputStream)的装饰类
FileInputStream纯粹是从硬盘进行读取数据 硬盘的计算速度跟不上内存的计算速度的
如果一个一个读 或者一批一批(阙值)读的话 速度相对而言都是慢的
BufferedInputStream自身内部有一个缓冲区在内存中 假设缓冲区大小为500
对于文件中1000个字节的数据只需要两次IO就读到内存中了 耗时2秒
第1次 读取500个 程序中再用byte[10]从内存缓冲区中进行读取 一次0.1秒 耗时5秒
如果前500个数据被读取完毕之后 要进行填充
第2次 读取500个 程序中再用byte[10]从内存缓冲区中进行读取 一次0.1秒 耗时5秒
总耗时12秒
BufferedOutputStream 程序先将数据byte[10]写入到缓冲区中byte[500] 等到缓冲区满的时候
一次将缓冲区的内容写入到硬盘文件中1秒
XXXInputStream 字节输入流
XXXOutputStream 字节输出流
XXXReader 字符输入流
XXXWriter 字符输出流
public static void main(String[] args) throws IOException {
File f1 = new File("IO笔记.txt");
FileInputStream fis = new FileInputStream(f1);
InputStreamReader isr = new InputStreamReader(fis,"gbk");
char[] cbuf = new char[100];
int len = 0;
while ((len = isr.read(cbuf)) != -1) {
System.out.println(new String(cbuf));
}
isr.close();
}
OutputStreamWriter
public static void main(String[] args) throws IOException {
//赋值一个文本文件
File f1 = new File("IO笔记.txt");
File f2 = new File("IO_copy.txt");
FileInputStream fis = new FileInputStream(f1);
FileOutputStream fos = new FileOutputStream(f2);
InputStreamReader isr = new InputStreamReader(fis);
OutputStreamWriter osw = new OutputStreamWriter(fos);
char[] cbuf = new char[100];
int len = 0;
while ((len = isr.read(cbuf)) != -1) {
osw.write(cbuf,0,len);
}
isr.close();
osw.close();
}
FileReader和FileWriter
FileReader 功能= InputStreamRead + FileInputStream
FileWriter 功能= OutputStreamWriter + FileOutputStream
FileReader FileWriter 不能再操作非文本文件了
其次 FileReader FileWriter 不能进行指定编码表 字符集 本质底层还是用字节流操作



