最近作项目的时候,用java获取文件。
虽然用框架很容易,可是其内部的原理让我很疑惑。在本身写类似的代码的时候,每每会出现各类各样的错误。因此这里,对相关的类以及方法进行一个整合。
好比 file 类,path 类。 绝对路径与相对路径。 getResource 方法 , getRealPath方法等。java
在使用 File 类的时候,发现绝对路径和相对路径的使用有很大的区别。
你们都知道:File类是用来构造文件或文件夹的类,在其构造函数中要求传入一个String类型的参数,用于指示文件所在的路径绝对路径名
是完整的路径名,不须要任何其余信息就能够定位自身表示的文件。相对路径名
必须使用来自其余路径名的信息进行解释linux
由于我使用的是 idea ,因此下面,我就用idea 给你们演示一下,他们的区别。
废话很少说,直接上代码web
public class testFile { public static void main(String[] args) throws IOException { // 绝对路径 File fi1 = new File("D://sy.ini"); // 相对路径 File fi2 = new File("sy.ini"); String test = "000"; try { // 将 test 分别写入 fi1 fi2 FileOutputStream fo1 = new FileOutputStream(fi1); FileOutputStream fo2 = new FileOutputStream(fi2); fo1.write(test.getBytes()); fo2.write(test.getBytes()); } catch (FileNotFoundException e) { e.printStackTrace(); } // 验证 getPath 与 getAbsolubtePath 的区别。 System.out.println(fi1.getPath()); System.out.println(fi1.getAbsolutePath()); System.out.println(fi2.getPath()); System.out.println(fi2.getAbsolutePath()); } }
输出的结果以下网络
D:\sy.ini D:\sy.ini sy.ini D:\Programme\0-Java\J_Example\Arithmetic\sy.ini
用两张图片辅助结果框架
从这个结果中,咱们能够看出两点ide
用代码说话。。。函数
URL resource = testFile.class.getClassLoader().getResource("."); URL resource1 = testFile.class.getResource("."); System.out.println(resource); System.out.println(resource1);
输出的结果为post
file:/D:/Programme/0-Java/J_Example/Arithmetic/out/production/3_basic/ file:/D:/Programme/0-Java/J_Example/Arithmetic/out/production/3_basic/test_01/
因此对于 getResource 来讲 。性能
使用 EL 表达式
${pageContext.request.contextPath} 这里的路径指的是 web 的根目录.测试
Path 类 是 JDK 7 中加入的新内容。比File 类更快,并且有报错机制,因此更容易使用。
他们两个的 区别
我会写在内部的 注释中。
就不单独拿出来写了。
// 若是存在重复 会报错。 Path path = Paths.get("D://test.txt"); Files.createFile(path); // 这里有一个 方法,可直接设置文件的属性。 Set perms= PosixFilePermissions.fromString("rw-rw-rw-") Files.crateFile(path,perms); // 若是存在重复,会从新建立。 // 可使用 file.exists() 来确认是否存在重复。 File file = new File("D://test02.txt"); file.createNewFile();
共同点: 想要建立多级目录下的文件,都必须先建立目录,才能建立文件。
// 能够直接建立多级目录 Path path = Paths.get("D://test/test01/"); Files.createDirectories(path); // mkdir 只能建立一级目录 // mkdirs 能够建立多级目录 File file = new File("D://test02/test3/test3"); file.mkdir(); file.mkdirs();
// 若是文件夹下存在多级目录,则报错 // DirectoryNotEmptyException Path path = Paths.get("D://test/"); Files.delete(path); // 若是文件夹下存在多级目录,则没有反应。。 File file = new File("D://test02"); file.delete();
若是想要删除相应的文件,直接将 路径更改成文件的路径便可。
public static void fileForEach(String path) { File file = new File(path); File[] files = file.listFiles(); for (File f : files) { // 判断是 文件仍是 目录 if (f.isFile()) { System.out.println(f.getName() + "是文件!"); } else if (f.isDirectory()) { System.out.println(f.getName()); fileForEach(f.getPath()); } } } public static void main(String[] args) throws IOException { Path path = Paths.get("D://test/"); Files.walkFileTree(path, new SimpleFileVisitor<Path>() { // 访问文件夹前使用 @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { System.out.println(dir.getFileName()); return super.preVisitDirectory(dir, attrs); } // 访问文件夹后使用 @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { return super.postVisitDirectory(dir, exc); } // 访问文件时使用 @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.toString().endsWith(".txt")) { System.out.println(file.getFileName()); } return super.visitFile(file, attrs); } // 访问文件失败使用 @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { return super.visitFileFailed(file, exc); } }); fileForEach("D://test02/"); }}
这里出现了 SimpleFileVisitor 这个类,具体使用方法就是覆写其内部方法。
通过个人测试 , 由于这个类的方法, 能够比 fileForEach 快大约 30% 。
Path 类
Path path = Paths.get("D://test/test01/cs.txt"); Path to = Paths.get("D://test/test01/test2.txt"); Files.move(path, to, StandardCopyOption.REPLACE_EXISTING); Files.copy(path, to, StandardCopyOption.REPLACE_EXISTING);
这里的 StandardCopyOption 有三个属性。
注意: ATOMIC_MOVE 方法只支持 move 方法。若是将之使用到 copy 方法,则会报错。
/* 若是存在则覆盖 * Replace an existing file if it exists. */ REPLACE_EXISTING, /* 将属性一同拷贝。 * Copy attributes to the new file. */ COPY_ATTRIBUTES, /* 只支持 move 方法,不支持 copy 方法 * Move the file as an atomic file system operation. */ ATOMIC_MOVE;
下面是file 类
// 拷贝 方法 public void copyFile(String oldFile,String newFile){ try{ int bytesum = 0; int byteread = 0; File oldfile = new File(oldFile); //判断文件是否存在,若是文件存在则实现该文件向新文件的复制 if(oldfile.exists()){ //读取原文件 InputStream ins = new FileInputStream(oldFile); //建立文件输出流,写入文件 FileOutputStream outs = new FileOutputStream(newFile); //建立缓冲区,大小为500字节 byte[] buffer = new byte[500]; //每次从文件流中读取500字节数据,计算当前为止读取的数据总数 while((byteread = ins.read(buffer)) != -1){ bytesum += byteread; System.out.println(bytesum); //把当前缓冲区中的数据写入新文件 outs.write(buffer,0,byteread); } ins.close(); } else //若是原文件不存在,则扔出异常 throw new Exception(); }catch(Exception ex){ System.out.print("原文件不存在!"); ex.printStackTrace(); } // 移动 方法 File file = new File("D://test02/test02/test02.txt"); file.renameTo(new File("D://test02/test02/test.txt"));
从这里咱们能够看出, path 类相对应的 复制方法 很是简单,不须要使用 直接使用输入输出流就能够复制文件。
Path类
File类
File file = new File("D://test02/test02/test02.txt"); FileInputStream fileInputStream = new FileInputStream(file); FileReader fileReader = new FileReader(file);
相对比,咱们也能够看出,Path类相对 file类也简化了不少操做。更有利于开发。
path.toFile() File.toPath()
虽然并无针对其 性能做出确切的比较,不过就现有的网络统计来讲, Path 类在使用中大都会比 File 类快 , 而且在最新的 lucene 中,也是用 Path 代替了 file 的操做, 相关的文章请参考 []。
综上,推荐使用 Path 类替代 File 类。
码字不易,各位看官多多点赞哟~~~
谢谢大佬们的支持。
本人我的博客killCode,不定时干货。