资讯专栏INFORMATION COLUMN

Kill_Java -- 文件类相关

printempw / 829人阅读

摘要:如果使用类,则代表该类所在的包为相对路径的起点。虽然并没有针对其性能作出确切的比较,不过就现有的网络统计来说,类在使用中大都会比类快并且在最新的中,也是用代替了的操作,相关的文章请参考。综上,推荐使用类替代类。

前言

最近做项目的时候,用java获取文件。
虽然用框架很容易,但是其内部的原理让我很疑惑。在自己写相似的代码的时候,往往会出现各种各样的错误。所以这里,对相关的类以及方法进行一个整合。
比如 file 类,path 类。 绝对路径与相对路径。 getResource 方法 , getRealPath方法等

绝对路径与相对路径

在使用 File 类的时候,发现绝对路径和相对路径的使用有很大的区别。
大家都知道:File类是用来构造文件或文件夹的类,在其构造函数中要求传入一个String类型的参数,用于指示文件所在的路径
绝对路径名是完整的路径名,不需要任何其他信息就可以定位自身表示的文件。
相对路径名必须使用来自其他路径名的信息进行解释

因为我使用的是 idea ,所以下面,我就用idea 给大家演示一下,他们的区别。
废话不多说,直接上代码

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-JavaJ_ExampleArithmeticsy.ini

用两张图片辅助结果

从这个结果中,我们可以看出两点

getPath 只是简单的返回 你赋予的String 值,不管是 相对路径还是绝对路径。

相对路径是相对于自身的项目地址。并且不加 "/"

getResource

用代码说话。。。

        URL resource = testFile.class.getClassLoader().getResource(".");
        URL resource1 = testFile.class.getResource(".");
        System.out.println(resource);
        System.out.println(resource1);

输出的结果为

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 来说 。

如果使用 Class 类 ,则代表该类所在的包为 相对路径的起点。

如果使用 ClassLoader类 , 则代表该类所在的 模块为 相对路径的起点。

JSP 中的路径

使用 EL 表达式
${pageContext.request.contextPath} 这里的路径指的是 web 的根目录.

File类 与 Path类

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() {
            // 访问文件夹前使用
            @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%

复制与移动
移动的同时可以更改名字。这一点,都一样。并且与 linux 的操作也类似

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 类的使用总结。
Path 类 相比较于 File 类 ,在操作上更直观,没有涉及到更深的层面.可以看出 研发人员 从中作出了很多改进。 可以让人更专注于逻辑的编写,而非是 底层的基础。

虽然并没有针对其 性能作出确切的比较,不过就现有的网络统计来说, Path 类在使用中大都会比 File 类快 , 并且在最新的 lucene 中,也是用 Path 代替了 file 的操作, 相关的文章请参考 []。

综上,推荐使用 Path 类替代 File 类。

结语

码字不易,各位看官多多点赞哟~~~
谢谢大佬们的支持。
本人个人博客killCode,不定时干货。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70469.html

相关文章

  • Kill_Java -- ConcurrentHashMap源码分析

    摘要:原因是它支持多线程进行扩容操作,而并没有加锁。多线程的情况下如果一个或多个线程正在对进行扩容操作,当前线程也要进入扩容的操作中。 KillCode系列 -- Java篇 原文发布在我的个人博客中killCode 因为JDK1.8 与 1.7 里对ConcurrentHashMap 有很多不同的更改以提高性能。所以特别找出类似的方面,进行分析。 1. 内部参数 //初始容积为 16 p...

    Karrdy 评论0 收藏0
  • 监控服务管理 智能大数据平台 USDP

    摘要:其他监控类服务管理其他监控类服务管理其他监控类服务管理其他监控类服务还包括等,对这些监控服务的管理方式,均与本篇指南中服务管理的管理方式类似,此处不再过多赘述。 监控类服务管理本篇目录Prometheus服务管理Grafana服务管理其他监控类服务管理在USDP1.0.0.0版本中,集群监控类服务组件主要有AlterManager、Grafana、InfluxDB、NodeExporter、...

    ernest.wang 评论0 收藏2270
  • 存储服务管理 智能大数据平台 USDP

    摘要:服务配置文件修改服务配置文件修改参考服务配置文件管理方式。其他存储类服务管理其他存储类服务管理其他存储类服务管理其他存储服务还有等,对这些存储服务的管理方式,均与本篇指南中服务管理的管理方式类似,此处不再过多赘述。 存储类服务管理本篇目录Zookeeper服务管理HDFS服务管理其他存储类服务管理在USDP1.0.0.0版本中,集群存储类服务组件主要有Elasticsearch、HBase、...

    ernest.wang 评论0 收藏239
  • Laravel5.1基于Entrust扩展包实现的RBAC权限控制模块(迁移到其他项目中的方法)

    摘要:基于扩展包实现的权限控制模块迁移到其他项目中的方法大部分的项目中,都需要权限控制,我们的项目用的是的框架,基于扩展包,写了一个通用的权限控制模块,方便后续其他项目需要时可用直接迁移使用。拷贝权限控制中间件。 Laravel5.1基于Entrust扩展包实现的RBAC权限控制模块(迁移到其他项目中的方法) 大部分的项目中,都需要权限控制,我们的项目用的是Laravel5.1的框架,基于E...

    li21 评论0 收藏0
  • phpDocument(PHPDoc) 标签大全

    摘要:标签适用描述方法声明此元素适用于第三方任何记录相关作者文件类分类任何记录相关版权信息任何声明此元素不推荐使用以后将会弃用任何显示一部分示例代码文件变量告知全局变量及其用法任何告知忽略的元素任何说明此元素是相关程序或库的内部元素,默认隐藏文件 标签 适用 描述 api 方法 声明此元素适用于第三方 author 任何 记录相关作者 category 文件,类 分类 ...

    wfc_666 评论0 收藏0

发表评论

0条评论

printempw

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<