文章目录
java.io.File类
java.io.File类,是文件和目录的抽象表示形式,与平台无关。
File可以新建、删除、重命名文件和目录,可以得到文件的属性,但不能访问文件的内容。访问内容需要输入/输出流。
File对象可以作为参数传递给流的构造函数
相对路径&绝对路径
绝对路径:有盘符
相对路径:没有盘符,相对于当前工程目录,可以用下面的代码获取工程目录
System.getProperty("user.dir");
File类的常见构造方法
- public File(String pathname)
以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果是相对路径,则默认当前路径在系统属性user.dir中存储。 - public File(String parent,String child)
以parent为父路径,child为子路径创建File对象。(父路径和子路径可以拼接成一个完整路径即可) - public File(File parent,String child)
public class TestFile {
public static void main(String[] args) {
File f = new File("G:\\test\\abc\\test.txt"); //对象f就是test.txt文件
File f1 = new File("G:\\test", "abc\\test.txt"); //对象f1也是test.txt文件
File f2 = new File(new File("G:\\test")+"abc\\test.txt")
}
}
需要注意的是:\ 在文件中是路径分隔符,但在java中是转义符,所以java中\\才能表示路径分隔符,或者可以使用反斜杠 / 来作为路径分隔符。
此外,File的静态属性String separator存储了当前系统的路径分隔符,UNIX中为"/",在Windows中为"\\"。
public class TestFile {
public static void main(String[] args) {
//对象f2、f3也是test.txt文件
File f2 = new File("G:/test/abc/test.txt");
File f3 = new File("G:" + File.separator + "test\\abc\\test.txt");
}
}
File类的常见方法
访问文件名
String getName() : 获取当前文件或文件夹的名称
String getPath() : 获取当前文件或文件夹的路径
public class TestFile {
public static void main(String[] args) {
//使用绝对路径创建File对象
File f = new File("G:\\test\\abc\\test.txt"); //文件
File f4 = new File("G:\\test\\abc"); //文件夹
//获取当前文件名
System.out.println(f.getName()); //test.txt
//获取当前文件路径
System.out.println(f.getPath()); //G:\test\abc\test.txt
//获取当前文件夹名称
System.out.println(f4.getName()); //abc
//获取当前文件夹路径
System.out.println(f4.getPath()); //G:\test\abc
File getAbsoluteFile() : 返回一个当前文件/文件夹用绝对路径构建的File对象
String getAbsolutePath() : 获取当前文件/文件夹的绝对路径
public class TestFile {
public static void main(String[] args) {
//使用绝对路径创建File对象
File f = new File("G:\\test\\abc\\test.txt");
//使用相对路径创建File对象
File f5 = new File("src/io/TestFile.java");
//getPath()获取当前文件路径
//(如果File对象用绝对路径创建,getPath()返回的就是绝对路径)
System.out.println(f.getPath()); //G:\test\abc\test.txt
//(如果File对象用相对路径创建,getPath()返回的就是相对路径)
System.out.println(f5.getPath()); //src\io\TestFile.java
//getAbsolutePath()获取当前文件绝对路径
System.out.println(f5.getAbsolutePath()); //F:\java\JavaWorkspace\demo\src\io\TestFile.java
//getAbsoluteFile()返回一个当前文件用绝对路径构建的File对象,实际上和f5是同一个对象
System.out.println(f5); //src\io\TestFile.java
System.out.println(f5.getAbsoluteFile()); //F:\java\JavaWorkspace\demo\src\io\TestFile.java
}
}
String getParent() :返回当前文件/文件夹的父级路径
boolean renameTo(File newName) :给当前文件/文件夹重命名
//返回当前文件/文件夹的父级路径
System.out.println(f.getParent()); //G:\test\abc
System.out.println(f5.getParent()); //src\io
//给当前文件/文件夹重命名
f.renameTo(new File("G:\\test\\abc\\test1.txt"));
文件检测
boolean exists() : 判断当前File对象是否存在
boolean canWrite() : 判断当前File对象是否可写
boolean canRead() : 判断当前File对象是否可读
boolean isFile() : 判断当前File对象是否为文件
boolean isDirectory() : 判断当前File对象是否为文件夹(目录)
//判断当前File对象是否存在
System.out.println(f.exists()); //false 因为test已经改名为test1,所以不存在
System.out.println(f6.exists()); //true
//此处手动在文件夹中新建了一个test2,并设置为只读
File f7 = new File("G:\\test\\abc\\test2.txt");
//f8 是一个不存在的文件夹路径
File f8 = new File("G:\\test\\abc1");
//判断当前File对象是否可读可写
System.out.println(f7.canWrite()); // false
System.out.println(f7.canRead()); // true
System.out.println(f8.canWrite()); // false
System.out.println(f8.canRead()); // false
File f9 = new File("G:\\test\\abc");
//判断当前File对象是否为文件
System.out.println(f7.isFile()); // true
System.out.println(f9.isFile()); // false
//判断当前File对象是否为文件夹(目录)
System.out.println(f7.isDirectory()); // false
System.out.println(f9.isDirectory()); // true
获取常规文件信息
long length() : 返回文件的长度,单位是字节数(如果是0,可能是空文件,也可能是目录)
long lastModified() : 获取File对象的最后修改时间,返回的是一个毫秒数
//获取File对象的最后修改时间,返回的是一个毫秒数(与1970年1月1日00:00:00的时间差)
System.out.println(f6.lastModified());
//返回文件的长度,单位是字节数
System.out.println(f6.length());
文件操作
boolean createNewFile() : 新建文件(不存在才会创建,返回true,文件存在创建失败,返回false)
boolean delete() : 删除已经存在的文件,返回删除是否成功
//新建一个文件
File f10 = new File("G:\\test\\abc\\test3.txt");
System.out.println(f10.exists()); //false
if(!f10.exists()) { //先判断f10不存在,再新建(此处需抛出一个IO异常)
try {
f10.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(f10.exists()); //true
//删除文件
f10.delete();
System.out.println(f10.exists()); //false
目录操作
boolean mkdir() : 创建单级目录
boolean mkdirs() : 创建多级目录
boolean delete() 也可以删除目录,但只能逐级删除。
//mkdir()新建单级目录(文件夹)
//若想创建多层目录,需要逐级新建
File f11 = new File("G:\\test\\abc\\a");
File f12 = new File("G:\\test\\abc\\a\\b");
System.out.println(f12.exists()); //false
f12.mkdir();
System.out.println(f12.exists()); //false mkdir()无法直接创建多级目录
f11.mkdir();
f12.mkdir();
System.out.println(f12.exists()); //true
//mkdirs()创建多级目录
File f13 = new File("G:\\test\\abc\\d\\e");
System.out.println(f13.exists()); //false
f13.mkdirs();
System.out.println(f13.exists()); //true
String[] list() : 获取当前目录下所有文件/文件夹的名称
File[] listFiles() : 获取当前目录下所有文件/文件夹的对象
File[] listRoot() : 获得所有盘符
//获取当前目录下所有文件/文件夹的名称,返回的是一个String集合
File f14 = new File("G:\\test\\abc");
String[] strs = f14.list();
for(String s : strs) {
System.out.println(s);
}
//获取当前目录下所有文件/文件夹的对象,返回的是一个File集合
File[] files = f14.listFiles();
for (File file : files) {
System.out.println(file);
}
//获得所有盘符
File[] roots = File.listRoots();
for (File r : roots) {
System.out.println(r);
}
遍历指定目录下的所有文件及文件夹
使用递归的思想
import java.io.File;
public class TestFile2 {
public static void main(String[] args) {
String pathName = "G:\\test";
//f为要遍历的文件对象
File f = new File(pathName);
//调用方法
showFiles3(f,0);
}
public static void showFiles3(File file,int level) {
//level用来确定目录层级
for(int i = 0; i < level; i++) {
System.out.print("-");
}
//判断传入的File对象是否为文件
if (file.isFile()) {
//若是文件则直接输出该文件
System.out.println(file.getName());
}else {
//若是文件夹则先输出文件夹
System.out.println(file.getName());
//然后获得该文件夹中所有File对象
File[] files = file.listFiles();
//若文件夹中不为空,则对文件中每一个File重复调用方法本身
if(files != null && files.length >0) {
for(File f : files) {
showFiles3(f,level+1);
}
}
}
}
}
使用面向对象思想获得指定目录的大小和文件/文件夹个数
import java.io.File;
public class DirCount {
String path;
long len;
int fileSize;
int dirSize = -1;
File src;
public DirCount(String path) {
super();
this.path = path;
this.src = new File(path);
count(src);
}
public long getLen() {
return len;
}
public int getFileSize() {
return fileSize;
}
public int getDirSize() {
return dirSize;
}
private void count(File file) {
if (file.isFile()) {
len += file.length();
fileSize++;
}else {
dirSize++;
File[] files = file.listFiles();
if(files != null && files.length >0) {
for(File f : files) {
count(f);
}
}
}
}
public static void main(String[] args) {
String pathName = "G:\\test";
DirCount dirCount = new DirCount(pathName);
System.out.println("目录 " + pathName);
System.out.println("大小:" + dirCount.getLen());
System.out.print("包含 " + dirCount.getDirSize() + " 个文件夹 ");
System.out.println(dirCount.getFileSize() + " 个文件 ");
}
}
运行结果:
文件夹属性:
文件编码
Java采用的是Unicode国际字符集,使用双字节16位存储。
但实际文件存储的数据有各种字符集,如果没有转换正确,就会出现乱码情况。
从字节到字符叫做编码encode
从字符到字节叫做解码decode
字符集中的码表给每一个字符对应一个代码,这个代码可以转成二进制,从而实现编码和解码
常用字符集
字符集 | 说明 |
---|---|
US-ASCII | 英文的ASCII字符集 |
ISO-8859-1 | Latin-1拉丁字符,包含中文、日文等 |
UTF-8 | 变长的Unicode字符(1-3个字节),节约空间,国际通用 |
UTF-16BE | 定长Unicode字符(2个字节),大端Big-endian表示,高字节低地址 |
UUTF-16LE | 定长Unicode字符(2个字节),小端Little-endian表示,低字节低地址 |
UTF-16 | 定长Unicode字符(2个字节),文件开头指定大端还是小端表示 即BOM(Byte-Order-Mark):FE FF表示大端,FF FE表示小端 |
编码、解码
编码:byte[] getBytes()
解码:String类构造方法,例如new String(byte[] bytes, int offset, int length, String charsetName)
//编码:字符串→字节数组
String msg1 = "香辣鸡枞菌菌菇鸡腿双层堡";
String msg2 = "kfc香辣鸡枞菌菌菇鸡腿双层堡";
//getBytes()编码,默认使用工程字符集编码,此工程使用GBK
byte[] datas1 = msg1.getBytes();
byte[] datas2 = msg2.getBytes();
System.out.println(datas1.length); //24 GBK每个中文字符占2个字节
System.out.println(datas2.length); //27 GBK每个英文字符占1个字节
//getBytes(String charsetName) 按照指定字符集编码
byte[] datas3 = msg1.getBytes("utf-8");
byte[] datas4 = msg2.getBytes("utf-8");
System.out.println(datas3.length); //36 utf-8,中文字符占3个字节
System.out.println(datas4.length); //39 utf-8,英文字符占1个字节
byte[] datas5 = msg2.getBytes("utf-16LE");
System.out.println(datas5.length); //30 utf-16LE 所有字符都占2个字节
//解码:字节数组→字符串
String msg = new String(datas3, 0, datas3.length, "utf-8");
System.out.println(msg); //香辣鸡枞菌菌菇鸡腿双层堡
乱码
- 字节数不够
- 字符集不统一
//乱码
//1)字节数不够
//例如utf-8中文字符占3个字节,但最后一个“堡”字只剩1个字节,就会导致乱码
msg = new String(datas3, 0, datas3.length-2, "utf-8");
System.out.println(msg); //香辣鸡枞菌菌菇鸡腿双层?
//2)字符集不统一
//例如使用utf-8进行编码,但使用gbk进行解码,就会造成乱码
msg = new String(datas3, 0, datas3.length, "gbk");
System.out.println(msg); //乱码