Java实现验证文件名有效性的方法详解

 更新时间:2022年09月28日 08:34:16   作者:指北君  
在本文中,我们将讨论使用 Java 验证一个给定的字符串是否具有操作系统的有效文件名的不同方法,文中的示例代码讲解详细,感兴趣的可以了解一下

在本文中,我们将讨论使用 Java 验证一个给定的字符串是否具有操作系统的有效文件名的不同方法。我们可以根据限制的字符或长度限制来检查该值。

我们将只关注核心解决方案,不使用任何外部依赖。我们将使用JDK的java.io和NIO2包来实现我们验证方法。。

使用java.io.File

让我们从第一个例子开始,使用 java.io.File 类。在这个解决方案中,我们需要用一个给定的字符串创建一个File实例,然后在本地磁盘上创建一个文件。

public static boolean validateStringFilenameUsingIO(String filename) throws IOException {
    File file = new File(filename);
    boolean created = false;
    try {
        created = file.createNewFile();
        return created;
    } finally {
        if (created) {
            file.delete();
        }
    }
}

当给定的文件名不正确时,它会抛出一个IOException。让我们注意,由于里面的文件创建,这个方法需要给定的文件名字符串没有对应存在的文件。

我们知道,不同的文件系统有自己的文件名限制。通过使用 java.io.File 方法,我们不需要指定每个操作系统的规则,因为Java自动为我们解决了这个问题。

然而,我们需要创建一个假文件。当我们成功后,我们必须记得在最后删除它。此外,我们必须确保我们有适当的权限来执行这些操作。任何失败也可能导致IOException,所以也最好检查一下错误信息。

assertThatThrownBy(() -> validateStringFilenameUsingIO("javanorth?.txt"))
  .isInstanceOf(IOException.class)
  .hasMessageContaining("Invalid file path");

使用 NIO2 API

我们知道java.io包有很多缺点,因为它是在Java的第一个版本中创建的。NIO2 API是java.io包的后继者,它带来了许多改进,这也大大简化了我们之前的解决方案。

public static boolean validateStringFilenameUsingNIO2(String filename) {
    Paths.get(filename);
    return true;
}

我们的功能现在被精简了,所以它是进行这种测试的最快方式。我们不创建任何文件,所以我们不需要有任何磁盘权限,也不需要在测试后执行清理。

无效的文件名抛出 nvalidPathException,它扩展了RuntimeException。这个的错误信息也包含了比之前更多的细节。

assertThatThrownBy(() -> validateStringFilenameUsingNIO2(filename))
  .isInstanceOf(InvalidPathException.class)
  .hasMessageContaining("character not allowed");

但是这个解决方案有一个严重的缺点,与文件系统的限制有关。Path类可能表示带有子目录的文件路径。与第一个例子不同,这个方法没有检查文件名字符的溢出限制。让我们用Apache Commons的randomAlphabetic()方法生成的五百个字符的随机String来检查。

String filename = RandomStringUtils.randomAlphabetic(500);
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
  .isInstanceOf(IOException.class)
  .hasMessageContaining("File name too long");

assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();

为了解决这个问题,我们应该像以前一样,创建一个文件并检查结果。

自定义的实现

最后,让我们尝试实现我们自己的自定义函数来测试文件名。我们还将尝试避免任何I/O功能,只使用核心的Java方法。

这类解决方案提供了更多的控制权,允许我们实现我们自己的规则。然而,我们必须考虑不同系统的许多额外限制。

使用String.contains

我们可以使用String.contains()方法来检查给定的String是否包含任何禁止的字符。首先,我们需要手动指定一些示例值。

public static final Character[] INVALID_WINDOWS_SPECIFIC_CHARS = {'"', '`', '<', '>', '?', '|'};
public static final Character[] INVALID_UNIX_SPECIFIC_CHARS = {'\000'};

在我们的例子中,让我们只关注这两个操作系统,Windows的文件名比UNIX的限制更多。另外,一些的空白字符可能会有问题。

在定义了受限制的字符集之后,让我们来确定当前的操作系统。

public static Character[] getInvalidCharsByOS() {
    String os = System.getProperty("os.name").toLowerCase();
    if (os.contains("win")) {
        return INVALID_WINDOWS_SPECIFIC_CHARS;
    } else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
        return INVALID_UNIX_SPECIFIC_CHARS;
    } else {
        return new Character[]{};
    }
}

而现在我们可以用它来测试给定的值。

public static boolean validateStringFilenameUsingContains(String filename) {
    if (filename == null || filename.isEmpty() || filename.length() > 255) {
        return false;
    }
    return Arrays.stream(getInvalidCharsByOS())
      .noneMatch(ch -> filename.contains(ch.toString()));
}

如果我们定义的任何字符不在给定的文件名中,这个Stream谓词返回真。此外,我们还实现了对null值和不正确长度的支持。

正则表达式模式匹配

我们也可以在给定的String上直接使用正则表达式。让我们来实现一个只接受字母数字和点字符的模式,其长度不超过255。

public static final String REGEX_PATTERN = "^[A-za-z0-9.]{1,255}$";

public static boolean validateStringFilenameUsingRegex(String filename) {
    if (filename == null) {
        return false;
    }
    return filename.matches(REGEX_PATTERN);
}

现在,我们可以根据先前准备的模式测试给定的值。我们还可以轻松地修改模式。在这个例子中,我们跳过了操作系统的检查功能。

总结

在这篇文章中,我们集中讨论了文件名及其限制。我们介绍了不同的算法,用Java检测无效的文件名。

我们从java.io包开始,它为我们解决了大部分的系统限制,但执行了额外的I/O动作,可能需要一些权限。然后我们检查了NIO2 API,它是最快的解决方案,但有文件名长度检查的限制。

最后,我们实现了我们自己的方法,不使用任何I/O API,但需要自定义实现文件系统规则。

到此这篇关于Java实现验证文件名有效性的方法详解的文章就介绍到这了,更多相关Java验证文件名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实现数独小游戏

    Java实现数独小游戏

    这篇文章主要为大家详细介绍了Java实现数独小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • java进行error捕获和处理示例(java异常捕获)

    java进行error捕获和处理示例(java异常捕获)

    通常来说,大家都是对Java中的Exception进行捕获和进行相应的处理,有些人说,error就无法捕获了。其实,error也是可以捕获的。Error和Exception都是Throwable的子类。既然可以catch Throwable,那么error也是可以catch的
    2014-01-01
  • java使用Abobe Acrobat DC生成模板

    java使用Abobe Acrobat DC生成模板

    这篇文章主要介绍了java使用Abobe Acrobat DC生成模板,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • 谈谈为JAXB和response设置编码,解决wechat4j中文乱码的问题

    谈谈为JAXB和response设置编码,解决wechat4j中文乱码的问题

    中文乱码是每个程序员都会遇到的问题,本篇文章主要介绍了谈谈为JAXB和response设置编码,解决wechat4j中文乱码的问题,具有一定的参考价值,有兴趣的可以了解一下。
    2016-12-12
  • 关于SpringBoot创建存储令牌的媒介类和过滤器的问题

    关于SpringBoot创建存储令牌的媒介类和过滤器的问题

    这篇文章主要介绍了SpringBoot创建存储令牌的媒介类和过滤器的问题,需要在配置文件中,添加JWT需要的密匙,过期时间和缓存过期时间,具体实例代码参考下本文
    2021-09-09
  • jetty运行时无法保存文件的解决方法

    jetty运行时无法保存文件的解决方法

    这篇文章主要为大家详细介绍了jetty运行时无法保存文件的解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Mybatis关联查询结果集对象嵌套的具体使用

    Mybatis关联查询结果集对象嵌套的具体使用

    在查询时经常出现一对多”的关系,所有会出现嵌套对象的情况,本文主要介绍了Mybatis关联查询结果集对象嵌套的具体使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • JVM要双亲委派的原因及如何打破它

    JVM要双亲委派的原因及如何打破它

    平时做业务开发比较少接触类加载器,但是如果想深入学习,了解类加载的原理是必不可少的.java的类加载器有哪些?什么是双亲委派?为什么要双亲委派?如何打破它?接下来本文就带大家详细介绍这些知识 ,需要的朋友可以参考下
    2021-06-06
  • Java中的引用类型和使用场景详细

    Java中的引用类型和使用场景详细

    这篇文章介绍的是Java中的引用类型和使用场景,主要内容展开Java中的引用类型,有强引用、软引用 、弱引用、虚引用,需要的朋友可以参考一下
    2021-10-10
  • SpringCloud Alibaba使用Seata处理分布式事务的技巧

    SpringCloud Alibaba使用Seata处理分布式事务的技巧

    在传统的单体项目中,我们使用@Transactional注解就能实现基本的ACID事务了,随着微服务架构的引入,需要对数据库进行分库分表,每个服务拥有自己的数据库,这样传统的事务就不起作用了,那么我们如何保证多个服务中数据的一致性呢?跟随小编一起通过本文了解下吧
    2021-06-06

最新评论