一、File类
变量、数组、对象、集合,这些数据都是存储在内存中的,但是只要程序执行结束,或者断点了,数据就消失了。不能永久存储。有些数据要长久保存,可以将数据以文件的形式存在硬盘里,即使程序结束了,断点了只要硬盘没坏,数据就永久存在。
而File类就用来表示当前系统下的文件(也可以是文件夹),但是需要我们注意:File对象只能对文件进行操作,不能操作文件中的内容。
1.1 File对象的创建
-
需求我们注意的是:路径中"\"要写成"\", 路径中"/"可以直接用
-
File对象可以指代一个不存在的文件路径
-
相对路径:不带盘符,默认是直接去工程下寻找文件的。
下面是创建文件的示例代码:
/**
* 目标:掌握File创建对象,代表具体文件的方案。
*/
public class FileTest1 {
public static void main(String[] args) {
// 1、创建一个File对象,指代某个具体的文件。
// 路径分隔符
// File f1 = new File("D:/resource/ab.txt");
// File f1 = new File("D:\\resource\\ab.txt");
File f1 = new File("D:" + File.separator +"resource" + File.separator + "ab.txt");
System.out.println(f1.length()); // 文件大小
File f2 = new File("D:/resource");
System.out.println(f2.length());
// 注意:File对象可以指代一个不存在的文件路径
File f3 = new File("D:/resource/aaaa.txt");
System.out.println(f3.length());
System.out.println(f3.exists()); // false
// 我现在要定位的文件是在模块中,应该怎么定位呢?
// 绝对路径:带盘符的
// File f4 = new File("D:\\code\\javasepromax\\file-io-app\\src\\itheima.txt");
// 相对路径(重点):不带盘符,默认是直接去工程下寻找文件的。
File f4 = new File("file-io-app\\src\\itheima.txt");
System.out.println(f4.length());
}
}
1.2 File判断和获取方法
刚才我们创建File对象的时候,会传递一个文件路径过来。但是File对象封装的路径是存在还是不存在,是文件还是文件夹其实是不清楚的。
除了判断功能还有一些获取功能,看代码:
File f1 = new File("D:/resource/ab.txt");
// 5.public String getName():获取文件的名称(包含后缀)
System.out.println(f1.getName());
// 6.public long length():获取文件的大小,返回字节个数
System.out.println(f1.length());
// 7.public long lastModified():获取文件的最后修改时间。
long time = f1.lastModified();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(sdf.format(time));
// 8.public String getPath():获取创建文件对象时,使用的路径
File f2 = new File("D:\\resource\\ab.txt");
File f3 = new File("file-io-app\\src\\itheima.txt");
System.out.println(f2.getPath());
System.out.println(f3.getPath());
// 9.public String getAbsolutePath():获取绝对路径
System.out.println(f2.getAbsolutePath());
System.out.println(f3.getAbsolutePath());
1.3 创建和删除方法
File类提供了创建和删除文件的方法,话不多少,看代码。
/**
* 目标:掌握File创建和删除文件相关的方法。
*/
public class FileTest3 {
public static void main(String[] args) throws Exception {
// 1、public boolean createNewFile():创建一个新文件(文件内容为空),创建成功返回true,反之。
File f1 = new File("D:/resource/itheima2.txt");
System.out.println(f1.createNewFile());
// 2、public boolean mkdir():用于创建文件夹,注意:只能创建一级文件夹
File f2 = new File("D:/resource/aaa");
System.out.println(f2.mkdir());
// 3、public boolean mkdirs():用于创建文件夹,注意:可以创建多级文件夹
File f3 = new File("D:/resource/bbb/ccc/ddd/eee/fff/ggg");
System.out.println(f3.mkdirs());
// 3、public boolean delete():删除文件,或者空文件,注意:不能删除非空文件夹。
System.out.println(f1.delete());
System.out.println(f2.delete());
File f4 = new File("D:/resource");
System.out.println(f4.delete());
}
}
1.mkdir(): 只能创建单级文件夹、
2.mkdirs(): 才能创建多级文件夹
3.delete(): 文件可以直接删除,但是文件夹只能删除空的文件夹,文件夹有内容删除不了。
1.4 遍历文件夹方法
代码如下:
/**
* 目标:掌握File提供的遍历文件夹的方法。
*/
public class FileTest4 {
public static void main(String[] args) {
// 1、public String[] list():获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。
File f1 = new File("D:\\course\\待研发内容");
String[] names = f1.list();
for (String name : names) {
System.out.println(name);
}
// 2、public File[] listFiles():(重点)获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)
File[] files = f1.listFiles();
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
File f = new File("D:/resource/aaa");
File[] files1 = f.listFiles();
System.out.println(Arrays.toString(files1));
}
}
这里需要注意几个问题:
1.当主调是文件时,或者路径不存在时,返回null
2.当主调是空文件夹时,返回一个长度为0的数组
3.当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹路径放在File数组中,并把数组返回
4.当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在FIle数组中,包含隐藏文件
5.当主调是一个文件夹,但是没有权限访问时,返回null
1.5 递归文件搜索
案例需求:在D:\\
判断下搜索QQ.exe这个文件,然后直接输出。
1.先调用文件夹的listFiles方法,获取文件夹的一级内容,得到一个数组
2.然后再遍历数组,获取数组中的File对象
3.因为File对象可能是文件也可能是文件夹,所以接下来就需要判断
判断File对象如果是文件,就获取文件名,如果文件名是`QQ.exe`则打印,否则不打印
判断File对象如果是文件夹,就递归执行1,2,3步骤
所以:把1,2,3步骤写成方法,递归调用即可。
代码如下:
/**
* 目标:掌握文件搜索的实现。
*/
public class RecursionTest3 {
public static void main(String[] args) throws Exception {
searchFile(new File("D:/") , "QQ.exe");
}
/**
* 去目录下搜索某个文件
* @param dir 目录
* @param fileName 要搜索的文件名称
*/
public static void searchFile(File dir, String fileName) throws Exception {
// 1、把非法的情况都拦截住
if(dir == null || !dir.exists() || dir.isFile()){
return; // 代表无法搜索
}
// 2、dir不是null,存在,一定是目录对象。
// 获取当前目录下的全部一级文件对象。
File[] files = dir.listFiles();
// 3、判断当前目录下是否存在一级文件对象,以及是否可以拿到一级文件对象。
if(files != null && files.length > 0){
// 4、遍历全部一级文件对象。
for (File f : files) {
// 5、判断文件是否是文件,还是文件夹
if(f.isFile()){
// 是文件,判断这个文件名是否是我们要找的
if(f.getName().contains(fileName)){
System.out.println("找到了:" + f.getAbsolutePath());
Runtime runtime = Runtime.getRuntime();
runtime.exec(f.getAbsolutePath());
}
}else {
// 是文件夹,继续重复这个过程(递归)
searchFile(f, fileName);
}
}
}
}
}
二、字符集、IO流
2.1 字符集
由于计算机能够处理的数据只能是0和1组成的二进制数据,为了让计算机能够处理字符,于是美国人就把他们会用到的每一个字符进行了编码(所谓编码,就是为一个字符编一个二进制数据)
美国人把他们用到的字符(英文字母、标点符号、数字以及一些特殊字符)和字符对应的编码总结成了一张码表,用1个字节来存储1字符,这张码表叫做ASCII码表。
中国人为了在计算机中存储中文,也编了一个中国人用的字符集叫做GBK字符集,这里面包含2万多个汉字字符,GBK中一个汉字采用两个字节来存储,为了能够显示英文字母,GBK字符集也兼容了ASCII字符集,在GBK字符集中一个字母还是采用一个字节来存储。(GB2312)
需要我们注意汉字和字母的编码特点:
-
如果是存储字母,采用1个字节来存储,一共8位,其中第1位是0
-
如果是存储汉字,采用2个字节来存储,一共16位,其中第1位是1
如果读取到第1位是0,就认为是一个字母,此时往后读1个字节。如果读取到第1位是1,就认为是一个汉字,此时往后读2个字节。
2.2 Unicode字符集
在Unicode字符集(万国码)中,采用一个字符4个字节的编码方案,又造成另一个问题:如果是说英语的国家,他们只需要用到26大小写字母,加上一些标点符号就够了,本身一个字节就可以表示完,用4个字节就有点浪费。
于是又对Unicode字符集中的字符进行了重新编码,一共设计了三种编码方案。分别是UTF-32、UTF-16、UTF-8; 其中比较常用的编码方案是UTF-8
-
UTF-32:4个字节编码
-
UTF-16:2个字节编码
-
UTF-8(可变长编码)
1.UTF-8是一种可变长的编码方案,工分为4个长度区 2.英文字母、数字占1个字节兼容(ASCII编码) 3.汉字字符占3个字节 4.极少数字符占4个字节
2.3 编码和解码
-
编码:把字符串按照指定的字符集转换为字节数组
-
解码:把字节数组按照指定的字符集转换为字符串
/**
* 目标:掌握如何使用Java代码完成对字符的编码和解码。
*/
public class Test {
public static void main(String[] args) throws Exception {
// 1、编码
String data = "a我b";
byte[] bytes = data.getBytes(); // 默认是按照平台字符集(UTF-8)进行编码的。
System.out.println(Arrays.toString(bytes));
// 按照指定字符集进行编码。
byte[] bytes1 = data.getBytes("GBK");
System.out.println(Arrays.toString(bytes1));
// 2、解码
String s1 = new String(bytes); // 按照平台默认编码(UTF-8)解码
System.out.println(s1);
String s2 = new String(bytes1, "GBK");
System.out.println(s2);
}
}
以上涉及图片资源,均出自于B站黑马程序员java进阶视频ppt。