Java操作磁盘文件
Java文件目录操作
为什么要先从磁盘文件与路径开始
作为零基础甚至是负基础入门学习编程的用户,在阅读现有图书以及示例代码时经常会遇到一些障碍,其中关于磁盘文件、目录、文件类型、路径等计算机操作系统的基础知识使用极其广泛。
如果不能很好的理解磁盘文件系统,不能熟练掌握路径的使用,将来在开发实际产品时会遇到很大障碍。顺便值得一提的是,新手开发遇到的严重bug中有近三层跟路径处理不正确有关。后续我们的实践案例中,几乎每一个案例都会涉及路径的操作。
磁盘文件目录管理命令回顾
很多普通用户日常使用计算机都在Windows操作系统下进行,而很多开发者和设计师使用的是mac,我们的web应用的服务器端大部分都运行在Linux操作系统上。
Mac和Linux这一类操作系统他们被称为UNIX LIKE,都是符合POSIX标准的操作系统,因此他们在磁盘文件和目录的管理方式上几乎完全相同,而Windows则有一些差异。
在日常的磁盘文件管理中,我们主要使用的就是目录以及文件两种路径类型。刚接触计算机的新人通常把目录看作是一个容器,能在一个目录中装进去其他目录和文件,而文件中只存有自身的数据,无法再切分。
因此,目录又叫文件夹,这种叫法源于微软早期操作系统(如果深入理解磁盘管理的原理后,你可能就不会再把目录当成容器看待。但把目录当成是一个能装其他目录的容器更容易让人学会使用目录和路径,因此我们并不反对初学者用这样的比喻去理解它)。
Windows磁盘文件管理
在Windows中输入win+R键输入CMD命令可以打开CMD窗口,在窗口中可以运行DOS命令操作和管理磁盘文件和目录。
Windows操作系统中,打开资源管理器(我的电脑)会看到机器上所有安装的磁盘,这些磁盘可能是多块硬盘,也可以是一块硬盘通过分区切分出来的多个盘。
每个盘会有一个盘符,如 “C:\” 、 “D:\”、 “E:\”等,通常盘符是按字母表顺序排列的。
Windows的路径分隔符是”\”,对应汉字书写中的捺方向,Windows中的路径默认不区分大小写字母,磁盘操作管理命令有很多,每个命令又对应若干参数,要学习和理解路径,我们至少要掌握cd、dir两个命令的基本用法。
CD命令
cd命令是最常用的Windows命令,用于切换当前的工作目录。cd后的参数可以是盘符也可以是一个路径。cd d:
cd命令后跟盘符表示切换工作目录(当前目录)到对应的盘符的根目录下。cd "c:\Program Files"
表示要进入C盘下的Program Files目录,注意这里cd命令后的路径用双引号引起来,是因为目录名称中有空格,如果没有引号,cd命令就无法准确识别目录名称。
DIR命令
dir命令用于查看目录结构(示例中盘符c:\为当前所在路径,不需要用户输入):c:\dir
dir命令不带任何参数的条件下会列出当前目录下所有文件和文件夹(不包含隐藏文件)。
dir命令后跟路径则是查看对应目录下的文件和文件夹。
Linux磁盘文件管理
在Mac和Linux桌面版可以打开一个叫终端的应用程序,进入shell命令窗口。
Linux中的磁盘文件管理命令比Windows更丰富,更强大,但只需掌握pwd、ls、cd三个命令的基础用法即可。
Linux文件系统中没有盘符的概念,即便计算机安装多块硬盘,每块硬盘在使用时也是对应在整个目录树上的一个具体路径,把目录和磁盘关联的操作称为挂载。
Linux路径中的分隔符使用的是/,对应汉字书写中撇的方向,不同的磁盘分区格式对大小写敏感度有差别。
PWD命令
pwd命令查看当前工作目录:root@8dc787fe6938:/# pwd
cd命令同Windows能力相同,表示进入某个目录。
CD命令
由于没有了盘符,所有文件和文件夹都在以/为根的目录树之下,因此不像Windows有切换盘符这样的操作。
要进入任何文件夹只需要输入cd $PATH就可以了。
如:
root@8dc787fe6938:/# cd /var/log/root@8dc787fe6938:/var/log# pwd/var/log
LS命令
ls命令与Windows中dir作用相似,用于查看指定目录中的内容,如果不加路径参数,则查看当前目录中的内容。
如:
root@8dc787fe6938:~# ls /etc/
adduser.conf fstab legal passwdselinuxalternatives gai.conf libaudit.conf profile shadowaptgroup login.defs profile.d shellsbash.bashrc gshadowlogrotate.d rc0.d skelbindresvport.blacklist host.conf lsb-release rc1.d subgidcron.d hostname machine-id rc2.d subuidcron.dailyhosts mke2fs.conf rc3.d sysctl.confdebconf.conf init.d mtab rc4.d sysctl.ddebian_version issue networksrc5.d systemddefault issue.net nsswitch.conf rc6.d terminfodeluser.conf kernel opt rcS.d update-motd.ddpkg ld.so.cache os-release resolv.conf xattr.confe2scrub.conf ld.so.conf pam.confrmtenvironment ld.so.conf.d pam.d security
相对路径和绝对路径
不管在Windows中还是Linux中,甚至是网页上,路径都可以有2种书写方式,一种叫相对路径,一种叫绝对路径,这两种路径在配合命令使用后的结果可以等效,但选择不同的方式表示路径可能方便程度会有很大差别。
这里举一个例子说明,尽管我们不建议使用类比学习技术,但是恰当的类比能降低理解知识的门槛。
如果有一栋大楼,房间编号是按面向大楼从左到右按以下规律来编制的
一层 01 、 02 、 03 、 04 、05 、06……
二层 01 、 02 、 03 、 04 、05 、06……
如果我当前在103房间,那么要找到104房间去取一个物品:
-
我可以说在我右边第一间房去取。
-
我还可以说到一层第四间房去取。
第一种描述方式叫做相对路径,第二种方式叫绝对路径。
使用linux命令如下:
root@8dc787fe6938:~# pwd/rootroot@8dc787fe6938:~# cd ../etc/root@8dc787fe6938:/etc# pwd/etcroot@8dc787fe6938:/etc# cd /root/root@8dc787fe6938:~# pwd/rootroot@8dc787fe6938:~# ls ../var/backups cache lib local lock log mail opt run spool tmproot@8dc787fe6938:~# ls /var/backups cache lib local lock log mail opt run spool tmp
上面的例子中cd命令和ls命令都分别使用了相对路径和绝对路径两种方式运行,在操作系统中,.(英文句点)表示当前目录 *./var/表示当前目录下的var目录,../*表示上一级目录
在Java中,对文件和文件夹的操作都由一个File类来管理,所以File对象既能代表文件,也能代表文件夹。
Java文件操作
File file = new File(".");
new File(".")中的英文句号.表示项目的根目录
创建一个文件对象,表示当前工作区的文件对象,运行该方法会看到文件或文件夹的绝对路径
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建一个文件或文件夹对象 File file = new File("."); //打印文件或文件夹的绝对路径 System.out.println(file.getAbsolutePath()); }}
String[] list = file.list();
查看当前工作区的所有文件及文件夹的名称,该方法返回一个的是一个字符串数组
import java.io.File;public class FileDemo { public static void main(String[] args) { File file = new File("."); //得到当前文件夹的所有文件和文件夹的名称 String[] list = file.list(); //遍历打印名称 for (String s : list) { System.out.println(s); } }}
File[] files = file.listFiles();
查看当前工作区的所有文件及文件夹,该方法返回一个文件的数组,表示当前工作区的所有文件及文件夹
import java.io.File;public class FileDemo { public static void main(String[] args) { File file = new File("."); File[] files = file.listFiles(); for (File f : files) { System.out.println(f.getName()); } }}
boolean delete = file.delete();
删除一个文件及文件夹,该方法返回一个bool值,用来判断是否删除成功,返回成功之后我们查看工作区的test.text是否还存在
我们先在工作区根目录创建一个test.text,然后运行该方法,会发现文件被删除了
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("./test.text"); boolean delete = file.delete(); System.out.println(delete); }}
boolean isDirectory = file.isDirectory();
检验给出的路径是否是一个文件夹,结果为bool值
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("."); boolean isDirectory = file.isDirectory(); System.out.println(isDirectory); }}
boolean isFile = file.isFile();
检验给出的路径是否是一个文件,结果为bool值
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("."); boolean isFile = file.isFile(); System.out.println(isFile); }}
boolean hidden = file.isHidden();
检验给出的文件是否是一个隐藏文件,结果为bool值
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("."); boolean isFile = file.isFile(); System.out.println(isFile); }}
boolean absolute = file.isAbsolute();
判断是否是绝对路径,返回值为true则为绝对路径,
//在unix系统中/开头则表示绝对路径,在Windows系统中,如果路径名的前缀是驱动器说明符后跟"\" ,或者其前缀是"\\" ,则该路径名是绝对路径名。
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("."); boolean absolute = file.isAbsolute(); System.out.println(absolute); }}
boolean exists = file.exists();
检验给出的路径是否真地存在,返回值为true则表示存在
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("."); boolean exists = file.exists(); System.out.println(exists); }}
String name = file.getName();
获取文件名
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("./test.text"); String name = file.getName(); System.out.println(name); }}
获取路径
String path = file.getPath();
//获取file构造方法中指定的路径String absolutePath = file.getAbsolutePath();
//获取绝对路径
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("./test.text"); String path = file.getPath();//获取file构造方法中指定的路径 System.out.println(path); String absolutePath = file.getAbsolutePath();//获取绝对路径 System.out.println(absolutePath); }}
重命名文件或文件夹,移动文件或文件夹
File file = new File("./aa.text");
//aa.text文件对象boolean b = file.renameTo(new File("./bb.text"));
//重命名为bb.text
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("./aa.text");//aa.text文件对象 boolean b = file.renameTo(new File("./bb.text"));//重命名为bb.text System.out.println(b); }}
boolean mkdirs = file.mkdirs();
创建多级目录
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("./test/test");//在项目根目录创建test/test文件夹 boolean mkdirs = file.mkdirs(); System.out.println(mkdirs); }}
boolean writable = file.setWritable(false);
修改文件为只读
import java.io.File;public class FileDemo { public static void main(String[] args) { //创建文件夹对象 File file = new File("./test.text"); boolean writable = file.setWritable(false);//设置为只读 System.out.println(writable); }}
File类本身没有提供文件复制的方法,但是有大量第三方工具提供了支持,因此我们可以使用第三方工具来实现许多File类本身没有的方法。
在这里我们用到了Apache提供的一个工具包叫commons-io,它封装了许多操作文件的方法,并且经过了大量的使用,可靠性非常高,直接拿来使用即可。
commons-io这个工具包可以在网上下载到,官网地址http://commons.apache.org/proper/commons-io/download_io.cgi,
具体下载地址为https://dlcdn.apache.org//commons/io/binaries/commons-io-2.11.0-bin.zip
下载之后我们将jar包导入导我们的工程中就可以直接使用了
文件的复制
import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;public class FileDemo { public static void main(String[] args) throws IOException { //创建文件夹对象 File file = new File("./test.text"); FileUtils.copyFileToDirectory(file,new File("d:\\"));//复制文件到文件夹中 }}
Java中的数组和集合
数组就类似于一个容器,里面有一个个连续的格子,我们可以将多个数据放到这一个个格子里面。
比如我们现在有三个字符串"apple", "orange", "pear",如果依靠变量去存储的话,就要定义三个变量,但是如果我们放到数组里,只需要一个变量就行
String [] fruits = new String[]{"apple","orange","pear"};
但是数组有一个缺点,它的长度是固定的,它是一种非常底层的数据结构,特点就是简单,功能少,比如我们想要再添加一个字符串"banana"进去,就无能为力了。因此在Java中,JDK封装了一个集合类叫ArrayList,它的底层是数组实现的,但是它的功能比数组多得多。
创建一个Arraylist
List list = new ArrayList();
往里面添加数据
list.add("banana");list.add("apple");list.add("orange");list.add("pear");
Arraylist还有很多其他方法,感兴趣的可以自己去看一看。
递归
本次任务中除了刚才给大家铺垫的知识,还有一个难点,可以说是新手噩梦,不过我们并不急于让大家在一次任务就掌握它,这个噩梦就是递归。
递归的定义是这样的:
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法
看起来很迷糊是不是?简单的说就是程序自己调用自己。