1.构造方法
1.File(String pathname) 根据路径名创建抽象File对象
//1. 通过路径进行创建 pathname是字符串格式的路径名
public File(String pathname) {
if (pathname == null) {
throw new NullPointerException();
}
// 和系统交互 获取最近的File文件目录文件
this.path = fs.normalize(pathname);
this.prefixLength = fs.prefixLength(this.path);
}
虚拟机负责和Window进行编码交互的
package java.io;
class WinNTFileSystem extends FileSystem
就是将路径根据Windo的格式,格式化一下然后再返回
public String normalize(String path) {
int n = path.length();
char slash = this.slash;// 斜杠
char altSlash = this.altSlash;
char prev = 0;
for (int i = 0; i < n; i++) {
char c = path.charAt(i);
if (c == altSlash)
return normalize(path, n, (prev == slash) ? i - 1 : i);
if ((c == slash) && (prev == slash) && (i > 1))
return normalize(path, n, i - 1);
if ((c == ':') && (i > 1))
return normalize(path, n, 0);
prev = c;
}
if (prev == slash) return normalize(path, n, n - 1);
return path;
}
package java.io;
class WinNTFileSystem extends FileSystem
获取路径的前缀
public int prefixLength(String path) {
char slash = this.slash; // 斜杠
int n = path.length(); // 路径总长
if (n == 0) return 0; // 路径长度为0 直接返回
char c0 = path.charAt(0); // 第一个字符 盘符
char c1 = (n > 1) ? path.charAt(1) : 0;
if (c0 == slash) {
if (c1 == slash) return 2; /* Absolute UNC pathname "\\\\foo" */
return 1; /* Drive-relative "\\foo" */
}
if (isLetter(c0) && (c1 == ':')) {
if ((n > 2) && (path.charAt(2) == slash))
return 3; /* Absolute local pathname "z:\\foo" */
return 2; /* Directory-relative "z:foo" */
}
return 0; /* Completely relative */
}
//normalized将该路径下所有文件名称的字符串数组
// 也就是将里面的文件名 存入字符数组。
private final String[] normalizedList() {
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null) {
//1.检查是否有权限操作该文件
security.checkRead(path);
}
// 2.检查路径有效性 无效直接不往下走了
if (isInvalid()) {
return null;
}
// 3.获取文件路径下的文件目录字符串数组 list 为本地方法
/*
List the elements of the directory denoted by the given abstract pathname. Return an array of strings naming the elements of the directory if successful; otherwise, return null.
列出由给定抽象路径名表示的目录元素。如果成功,则返回命名目录元素的字符串数组;否则,返回null。
*/
String[] s = fs.list(this);
if (s != null && getClass() != File.class) {
String[] normalized = new String[s.length];
for (int i = 0; i < s.length; i++) {
normalized[i] = fs.normalize(s[i]);
}
s = normalized;
}
return s; // 应该是所有的操作文件吧,或者说最近的文件目录
}
public native String[] list(File f);
CheckRead
安全管理器是一个允许应用程序实现安全策略的类。它允许应用程序在执行一个可能不安全或敏感的操作前确定该操作是什么,以及是否是在允许执行该操作的安全上下文中执行它。应用程序可以允许或不允许该操作。
public void checkRead(String file) {
checkPermission(new FilePermission(file,
SecurityConstants.FILE_READ_ACTION));
}
如果拒绝指定的安全上下文访问由给定权限所指定的资源,则抛出 SecurityException。
- 如果调用线程没有创建新类加载器的权限。
public void checkPermission(Permission perm) {
java.security.AccessController.checkPermission(perm);
}
@Deprecated(since="17", forRemoval=true)
public static SecurityManager getSecurityManager() {
if (allowSecurityManager()) {
return security;
} else {
return null;
}
}
allowSecurityManager
private static volatile SecurityManager security; // read by VM
// return true if a security manager is allowed
private static boolean allowSecurityManager() {
return (allowSecurityManager != NEVER);
}
prefixLength 获取前缀长度
public int prefixLength(String path) {
char slash = this.slash;
int n = path.length();
if (n == 0) return 0;
char c0 = path.charAt(0);
char c1 = (n > 1) ? path.charAt(1) : 0;
if (c0 == slash) {
if (c1 == slash) return 2; /* Absolute UNC pathname "\\\\foo" */
return 1; /* Drive-relative "\\foo" */
}
if (isLetter(c0) && (c1 == ':')) {
if ((n > 2) && (path.charAt(2) == slash))
return 3; /* Absolute local pathname "z:\\foo" */
return 2; /* Directory-relative "z:foo" */
}
return 0; /* Completely relative */
}
2.public File(File parent, String child) 父路径是File对象,子路径是String
public File(File parent, String child) {
if (child == null) {
throw new NullPointerException();
}
if (parent != null) {
if (parent.path.isEmpty()) {
this.path = fs.resolve(fs.getDefaultParent(),
fs.normalize(child));
} else {
// resolve 应该是拼接起来吧
this.path = fs.resolve(parent.path,
fs.normalize(child));
}
} else {
this.path = fs.normalize(child);
}
this.prefixLength = fs.prefixLength(this.path);
}
3.字符串格式的爹,孩子依旧字符串
内容区别不大,无非里面可能fs.normalize(parent) ,如果是字符串,爹也的normalize一下子
public File(String parent, String child) {
if (child == null) {
throw new NullPointerException();
}
if (parent != null) {
if (parent.isEmpty()) {
this.path = fs.resolve(fs.getDefaultParent(),
fs.normalize(child));
} else {
this.path = fs.resolve(fs.normalize(parent),
fs.normalize(child));
}
} else {
this.path = fs.normalize(child);
}
this.prefixLength = fs.prefixLength(this.path);
}
4. public File(URI uri) 根据uri对象创建
public File(URI uri) {
// Check our many preconditions
if (!uri.isAbsolute())
throw new IllegalArgumentException("URI is not absolute");
if (uri.isOpaque())
throw new IllegalArgumentException("URI is not hierarchical");
String scheme = uri.getScheme();
if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
throw new IllegalArgumentException("URI scheme is not \"file\"");
if (uri.getRawAuthority() != null)
throw new IllegalArgumentException("URI has an authority component");
if (uri.getRawFragment() != null)
throw new IllegalArgumentException("URI has a fragment component");
if (uri.getRawQuery() != null)
throw new IllegalArgumentException("URI has a query component");
String p = uri.getPath();
if (p.isEmpty())
throw new IllegalArgumentException("URI path component is empty");
// Okay, now initialize
p = fs.fromURIPath(p);
if (File.separatorChar != '/')
p = p.replace('/', File.separatorChar);
this.path = fs.normalize(p);
this.prefixLength = fs.prefixLength(this.path);
}
2.getName 获取文件名
// 获取最后一次分隔符后面的值
也就是最后的文件夹或者文件名称
public String getName() {
int index = path.lastIndexOf(separatorChar);
if (index < prefixLength) return path.substring(prefixLength);
return path.substring(index + 1);
}
3.createNewFile() 创建文件
public boolean createNewFile() throws IOException {
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null) security.checkWrite(path);
if (isInvalid()) {
throw new IOException("Invalid file path");
}
return fs.createFileExclusively(path);
}
4.delete() 删除文件(文件夹) 如果不存在返回失败
如果删除的是文件夹,需要先将文件夹内的内容全部删除,也就是说,必须是空文件夹
public boolean delete() {
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkDelete(path);
}
if (isInvalid()) {
return false;
}
return fs.delete(this);
}
5.exists() 检查路径是否存在 true false
public boolean exists() {
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
}
if (isInvalid()) {
return false;
}
return fs.hasBooleanAttributes(this, FileSystem.BA_EXISTS);
}
6.是否是文件夹
public boolean isDirectory() {
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
}
if (isInvalid()) {
return false;
}
return fs.hasBooleanAttributes(this, FileSystem.BA_DIRECTORY);
}
7.返回绝对路径
public String getAbsolutePath() {
return fs.resolve(this);
}
8.获取父目录
public String getParent() {
int index = path.lastIndexOf(separatorChar);
if (index < prefixLength) {
if ((prefixLength > 0) && (path.length() > prefixLength))
return path.substring(0, prefixLength);
return null;
}
return path.substring(0, index);
}
注意,根目录最高只到盘符,不过,这个是区分绝对目录和根目录的
9.获取路径 这里获取的是String字符串
public String getPath() {
return path;
}
10.getPrefixLength
int getPrefixLength() {
return prefixLength;
}
11.listFiles() 获取File路径下的所有文件名(所以他必须是个文件夹才能出来东西,不然就是NULL)
1.
public File[] listFiles() { // 将目录下的
String[] ss = normalizedList();
if (ss == null) return null;
int n = ss.length;
File[] fs = new File[n];
for (int i = 0; i < n; i++) {
fs[i] = new File(ss[i], this);
}
return fs;
}
2.文件过滤器对象调用
过滤器是接口,使用就必须重写过滤器
过滤器核心
public File[] listFiles(FileFilter filter) {
String ss[] = normalizedList();
if (ss == null) return null;
ArrayList<File> files = new ArrayList<>();
for (String s : ss) {
File f = new File(s, this);
// 注意看, 这里就是过滤器了, 显然看到,过滤器的使用过程
// 用爹 子 的构造方法 构造出子类的对象 然后将子类的File对象放入过滤器方法作为参数
// 所以过滤器处理的,是子对象的对象。
if ((filter == null) || filter.accept(f))
files.add(f);
}
return files.toArray(new File[files.size()]);
}
public interface FileFilter {
/**
* Tests whether or not the specified abstract pathname should be
* included in a pathname list.
*
* @param pathname The abstract pathname to be tested
* @return {@code true} if and only if {@code pathname}
* should be included
*/
boolean accept(File pathname);
}
public static void main(String[] args) {
// homework创建多级目录
File file = new File("D:\\CloudMusic");
int count1 = 0;
int count2 = 0;
for(File i : file.listFiles()){
System.out.println(i.getName());
count1++;
}
System.out.println("--------------");
for(File i : file.listFiles(new FileFilter())){
System.out.println(i.getName());
count2++;
}
System.out.println("count1 = " + count1);
System.out.println("count2 = " + count2);
}
public class FileFilter implements java.io.FileFilter {
// 过滤器方法 假设只要dll后缀的 endwith方法
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".dll");
}
}
3.总结
File的方法操作的都是创建时的String,这里String有绝对和相对路径之分,想要操作绝对路径,就必须获取绝对路径.
File是对文件进行操作 创建文件 遍历文件 删除文件
而创建文件,也可以通过输出流,但是两个不同的是,输出流只能创建单个文件,而File方法是可以创建文件目录(文件夹)的