在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不算纯文本文件
字符流 = 字节流 + 编码表
OutputStream 字节输出流
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读取换行时 \r\n
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()一个一个读取
/*
int b = 0;
while ((b = fis.read()) != -1) {
System.out.println(b + " : " + (char) b);
}
*/
复制文件夹操作+过滤
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 字符输出流
InputStreamReader
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 不能进行指定编码表 字符集 本质底层还是用字节流操作