目录
给定起始目录,遍历这个目录下的所有文件(普通文件&&文件名是.png)
目前Java语言比较少用于系统开发(开发系统软件),相较而言,做业务开发多一点。
I/O计算机硬件视角下,非内存数据的读写动作。当下文件(硬盘)IO为主。之前我们接触的I/O基本上都是在内存上,(System.in、System.out、System.err)。
硬盘存储和内存存储区别
硬盘存储:非易失性存储(non-volatile storage):可以在断电的时候进行数据的存储。硬盘存储是低速存储,读写速度远低于内存存储。
访问延时的直观数据:越上面读写速度越快,存储容量越小;越下面,读写速度越慢,存储容量越大。
易失性存储 | L0 | 寄存器(Register) |
易失性存储 | L1 | CPU内部的一级缓存(L1cache) |
易失性存储 | L2 | CPU内部的二级缓存(L2cache) |
易失性存储 | L3 | CPU内部的三级缓存(L3cache) |
易失性存储 | L4 | 内存RAM(Memory) |
非易失性存储 | L5 | 硬盘HD(Hard Driver) |
非易失性存储 | L6 | 脱机存储(offline storage) |
非易失性存储 | L7 | 网络存储/分布式存储(网盘) |
非易失性+低速:为了弥合速度差,所以针对硬盘数据的读写提出了各种各样的数据结构,算法、来解决。
硬盘上的数据更适合:
1.块状读取(block):块状读取尽可能的减少读写频次。相对的字节读取就是频繁的进行读写。
2.块状更适合连续的读写,内存上的读写是随机的读写。(操作系统中的磁盘寻道就是解决这里的连续读写问题)。
缓冲区(Buffer)技术
由于硬盘存储的低速性,会有一个缓冲区技术(更多的是针对写的):减少硬盘的读写频次。
以OS为代表:会在内存中开辟出一段空间——缓冲区;
当我们进行写入操作:第一次写入100字节,第二次写入100字节,第三次写入100字节,第四次写入100字节,会先在内存中写四次,达到一定的条件后,统一的写回硬盘。以减少硬盘的读写频次。
其中,一定条件一般是指:
1.应用程序主动要求:冲刷缓冲区(flush操作);
2.定时刷新:每隔一定时间冲刷;
3.定量冲刷:满了之后必须写硬盘;
IO中进行flush是必不可少的操作,否则数据会丢失(需要考虑,遗留在缓冲区中的数据丢失问题)。
对数据的认识
在计算机硬件看来,一般把数据抽象成数字(什么进制,什么宽度);如何解释这些数据->文本、波、像素等。一般分为两类:
1.文本数据:可以按照一定的字符集编码解释成文本的数据;
2.二进制数据:不可以解释成文本;
文件
狭义上的文件(File):一种抽象概念,表示硬盘中的数据块。
变量、对象是对内存中数据的抽象,文件是对硬盘中数据的抽象。
文件系统(FileSystem):对硬盘上的数据——文件进行直接组织和管理的一个模块。
Window的文件系统:
文件的几个概念
1.逻辑上,一个文件是由两块数据组成的; 管理数据+文件内容本身
2.文件系统是按照树形结构进行文件组织的。
3.目录/文件夹本身也是一种文件,是一种特殊的文件。
文件=文本文件 or 二进制文件;
文件=普通文件(文件) or 文件夹文件;
4.文件的位置(location)|路径(Path)-->非常重要的一个概念
用于定位到是哪个文件的(用树的视角看,就是树上的一个节点):
5.绝对路径(absolute path):从一棵树的根结点出发,达到对应节点但的完整路径。一个唯一的路径一定可以描述一个唯一的节点。
Windows使用反斜杠" \ "作为分隔符(path separator):C:\Program Files\Java\a.text
程序中反斜杠需要转义,所以写在程序中:C:\\Program Files\\Java\\a.text
路径存在,并不代表文件一定存在。路径是描述树中一个可能的位置,但并不代表这个位置一定有节点。
比如:C:\Program Files\Java\abcd.txt是一个合法的路径,但文件并不存在。
6.相对路径(relative path):相对...而言的路径,不再是从根目录出发了,从当前所在的位置/当前工作目录出发。
当前处于C:\Windows\目录下,要去找到上一层->Java->a.txt :..\Program Files\Java\a.text。
使用..代表回到上一层,使用.就在当前路径下。
从几个角度理解:我们身处何处?
绝对路径:D:\WH\企业管理
小结:
1.狭义上文件是关于硬盘中数据的抽象(非易失+低速->尽量减少读写频次->连续、块状读写+缓冲区)
2.文件可以分为:普通文件 or 目录文件;二进制文件 or 文本文件;
3.文件中的数据=管理数据+内容数据
4.文件时按照树形结构组织的,通过路径描述结点的方式,来唯一确定一个文件。
5.路径分为:
a.绝对路径(absolute path):从根开始进行结点描述的路径,无论身处何处,路径是唯一的。
b.相对路径(relative path):从当前位置出发,进行节点描述的路径,路径不变的情况,当前位置变化了,描述的结点也跟着变化
c:"."代表当前位置;".."代表上一层位置。
6.一个唯一的路径并不代表对应的文件一定存在。
代码部分:
Java提供了java.io.File类:File对象就是对文件的管理数据的抽象,描述文件
通过一个路径(绝对路径or相对路径都行),来创建File对象,但是File对象被创建出来,并不代表文件存在。
import java.io.File;
public class Main {
public static void main(String[] args) {
{
//以绝对路径为例
File file = new File("D:\\WH\\企业管理\\a.txt");
System.out.println(file);
// 对象存在
// 文件并不存在
}
{
// 父结点,一般都是目录
File parent = new File("D:\\WH\\企业管理");
File file = new File(parent, "a.txt");
System.out.println(file);
}
{
// 父结点,一般都是目录
File file = new File("D:\\WH\\企业管理", "a.txt");
System.out.println(file);
}
}
}
Java程序运行时的我们身处何处?
import java.io.File;
public class Main1 {
public static void main(String[] args) {
//工作目录,在IDEA中是配置出来的(进程的启动目录)
//并不是代码一样,运行出来的结果就一样
File file=new File("1.txt");
System.out.println(file.getAbsoluteFile());
}
}
进程在运行过程中,身处:D:\WH\文件\
其实这个文件不一定处于这个地方,只是因为:
1.在IDEA中配置的当前工作目录:默认是工程所在的目录,可以手动在Working directory中改变的,但一般是不会去改变它的。
我们身处何处:是一个运行期间的概念,和代码编写的时候是没有关系的,每次运行都有自己的身处何处。我写的代码给A去运行,A在哪个目录下启动,完全是A决定,与代码编写无关,出来的结果也不一样。
File类中的常见方法
以下三个方法,判断如果File对应的文件是存在的,是否用于可执行权限,可读权限和可写权限。
文件是被OS进行了权限管理的,以用户为单位进行管理。(普通用户/管理员用户)
import java.io.File;
public class Main1 {
public static void main(String[] args) {
//工作目录,在IDEA中是配置出来的(进程的启动目录)
//并不是代码一样,运行出来的结果就一样
File file=new File("1.txt");
System.out.println(file.getAbsoluteFile());
}
}
import java.io.File;
import java.io.IOException;
public class Main2 {
public static void main(String[] args) throws IOException {
File file=new File("..\\1.txt");
System.out.println(file.getCanonicalPath());
//存在吗
System.out.println(file.exists());//最常见
//是目录吗
System.out.println(file.isDirectory());//最常见
//是普通文件吗
System.out.println(file.isFile());//最常见
//是否可执行
System.out.println(file.canExecute());
//是否可读
System.out.println(file.canRead());
//是否可写
System.out.println(file.canWrite());
}
}
import java.io.File;
import java.io.IOException;
public class Main3 {
public static void main(String[] args) throws IOException {
File file=new File("..\\1.txt");
System.out.println(file.getAbsolutePath());
System.out.println(file.getCanonicalPath());
System.out.println(file.length());
System.out.println(file.getName());
System.out.println(file.getParent());
}
}
创建一个普通文件
前提:路径对应的文件原来是不存在的
import java.io.File;
import java.io.IOException;
public class Main4 {
public static void main(String[] args) throws IOException {
//前提:路径对应的文件原来是不存在的
File file=new File("..\\world.txt");
System.out.println(file.createNewFile());
//运行时会抛出异常:由于../xxx目录本身不存在,所以无法创建,以异常的形式体现
File file1=new File("../xxx/world.txt");
System.out.println(file.createNewFile());
}
}
创建目录
import java.io.File;
public class Main5 {
public static void main(String[] args) {
// File file = new File("../a/b/c/d");
//创建失败
// System.out.println(file.mkdir());
//一个一个去创建
// File f1 = new File("../a");
// f1.mkdir();
// File f2 = new File("../a/b");
// f2.mkdir();
// File f3 = new File("../a/b/c");
// f3.mkdir();
// File file = new File("../a/b/c/d");
// System.out.println(file.mkdir());
//用mkdirs()一次创建多个目录
File file = new File("../a/b/c/d");
System.out.println(file.mkdirs());
}
}
删除文件和目录
只是标记要删除,真正删除的时候是JVM退出的时候(deleteOnExit()),这里的删除时彻底删除,不是放到回收站。
文件删除是正常删除,目录删除要求必须是空目录。
Windows上的回收站只是一个特殊的目录:回收站的删除其实不是彻底删,只是把文件移动到对应的目录。
目录重命名
通过重命名的形式,把一个文件移动成另一个节点。
import java.io.File;
public class Main6 {
public static void main(String[] args) {
File file=new File("../hello/a.txt");
File file1=new File("../world/a.txt");
System.out.println(file.renameTo(file1));
}
}
小结:
1.文件的创建:正确的前提:文件的父目录存在&&文件不存在(creatNewFile());
2.目录的创建:正确的前提:文件的父目录存在&&文件不存在(mkdir()),想连同不存在的父目录一起创建(mkdirs())
3.删除:普通文件直接删除,目录文件要求目录是空目录。
给定起始目录,遍历这个目录下的所有文件(普通文件&&文件名是.png)
List<String>保存所有的路径,本质上,遍历目录下的所有文件实际上就是树的遍历,遍历过程中对所有借点进行条件判断(深度优先遍历)。
列出目录下的所有文件的方法:
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Main7 {
static List<String> a=new ArrayList<>();
public static void main(String[] args) {
File file=new File("要找的文件名");
traversal(file);
for (String path:a){
System.out.println(path);
}
}
private static void traversal(File dir){
File[] files=dir.listFiles();//该目录的所有孩子
if(files==null){
return;
}
for (File file:files){
if(file.isDirectory()){
traversal(file);
}else if(file.isFile()){
if(file.getName().equals("要找的文件名")){
a.add(file.getAbsolutePath());
}
}
}
}
}