Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否有跨平台的Java方法来删除文件名特殊字符?_Java_Cross Platform_Filesystems_Filenames - Fatal编程技术网

是否有跨平台的Java方法来删除文件名特殊字符?

是否有跨平台的Java方法来删除文件名特殊字符?,java,cross-platform,filesystems,filenames,Java,Cross Platform,Filesystems,Filenames,我正在制作一个跨平台的应用程序,根据在线检索的数据重命名文件。我想清理从当前平台的web API中提取的字符串 我知道不同的平台有不同的文件名要求,所以我想知道是否有跨平台的方法来实现这一点 编辑:在Windows平台上,文件名中不能有问号“?”,而在Linux中,可以。文件名可能包含这样的字符,我希望支持这些字符的平台能够保留这些字符,否则就将其删除 另外,我更喜欢不需要第三方库的标准Java解决方案。您的问题并不清楚,但由于您计划从web表单中接受路径名(?),您可能应该阻止重命名某些内容的

我正在制作一个跨平台的应用程序,根据在线检索的数据重命名文件。我想清理从当前平台的web API中提取的字符串

我知道不同的平台有不同的文件名要求,所以我想知道是否有跨平台的方法来实现这一点

编辑:在Windows平台上,文件名中不能有问号“?”,而在Linux中,可以。文件名可能包含这样的字符,我希望支持这些字符的平台能够保留这些字符,否则就将其删除


另外,我更喜欢不需要第三方库的标准Java解决方案。

您的问题并不清楚,但由于您计划从web表单中接受路径名(?),您可能应该阻止重命名某些内容的尝试;e、 g.“C:\程序文件”。这意味着您需要在进行访问检查之前规范化路径名以消除“.”和“.”


鉴于此,我不会试图删除非法字符。相反,我将使用“new File(str).getCanonicalFile()”来生成规范路径,接下来检查它们是否满足沙箱限制,最后使用“File.exists()”、“File.isFile()”等来检查源和目标是否符合犹太规范,并且不是同一个文件系统对象。我会通过尝试执行操作并捕获异常来处理非法字符。

正如其他地方所建议的,这通常不是您想要做的。通常最好使用安全方法(如file.createTempFile())创建临时文件

您不应该使用白名单,而只保留“好”字符。如果文件仅由中文字符组成,则您将从中删除所有内容。因为这个原因,我们不能使用白名单,我们必须使用黑名单

Linux几乎允许任何可能带来真正痛苦的事情。我只会将Linux限制在与Windows相同的列表中,这样将来就不会让自己头疼了

在Windows上使用此C#代码段,我生成了一个在Windows上无效的字符列表。这个列表中的字符比你想象的要多(41),所以我不建议你尝试创建自己的列表

        foreach (char c in new string(Path.GetInvalidFileNameChars()))
        {
            Console.Write((int)c);
            Console.Write(",");
        }
下面是一个简单的Java类,它“清理”文件名

public class FileNameCleaner {
final static int[] illegalChars = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47};
static {
    Arrays.sort(illegalChars);
}
public static String cleanFileName(String badFileName) {
    StringBuilder cleanName = new StringBuilder();
    for (int i = 0; i < badFileName.length(); i++) {
        int c = (int)badFileName.charAt(i);
        if (Arrays.binarySearch(illegalChars, c) < 0) {
            cleanName.append((char)c);
        }
    }
    return cleanName.toString();
}
}
公共类文件名清理器{
最终静态int[]非法字符={34,60,62,124,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,58,42,63,92,47};
静止的{
数组。排序(非法字符);
}
公共静态字符串cleanFileName(字符串badFileName){
StringBuilder cleanName=新的StringBuilder();
对于(int i=0;i
编辑: 正如Stephen所建议的,您可能还应该验证这些文件访问只发生在您允许的目录中

下面的答案有一个示例代码,用于在Java中建立自定义安全上下文,然后在该“沙箱”中执行代码


有一个非常好的内置Java解决方案-Character.isXxx()

请尝试
Character.isJavaIdentifierPart(c)

String name=“name.de+!@$%^&*(){}][/=?+-\\\\\\\:`~!'\\”,“;
StringBuilder文件名=新的StringBuilder();
for(char c:name.toCharArray()){
if(c='.| | Character.isJavaIdentifierPart(c)){
附加文件名(c);
}
}
结果是“name.é$\”

或者只需执行以下操作:

String filename = "A20/B22b#öA\\BC#Ä$%ld_ma.la.xps";
String sane = filename.replaceAll("[^a-zA-Z0-9\\._]+", "_");
结果:
A20\u B22b\u A\u BC\u ld\u ma.la.xps

说明:

[a-zA-Z0-9\\.\\.\uz]
匹配a-z小写或大写字母、数字、点和下划线

[^a-zA-Z0-9\\.\\.\\.
是相反的。即所有与第一个表达式不匹配的字符

[^a-zA-Z0-9\\.+
是与第一个表达式不匹配的字符序列


因此,不包含a-z、0-9或.u中字符的每个字符序列都将被替换。

以下是我使用的代码:

public static String sanitizeName( String name ) {
    if( null == name ) {
        return "";
    }

    if( SystemUtils.IS_OS_LINUX ) {
        return name.replaceAll( "[\u0000/]+", "" ).trim();
    }

    return name.replaceAll( "[\u0000-\u001f<>:\"/\\\\|?*\u007f]+", "" ).trim();
}
公共静态字符串sanitizeName(字符串名称){
if(null==名称){
返回“”;
}
if(SystemUtils.IS_OS_LINUX){
返回name.replaceAll(“[\u0000/]+”,“”)。trim();
}
返回名称.replaceAll(“[\u0000-\u001f:\”/\\\\\\\\?*\u007f]+”,“”)。trim();
}

SystemUtils
来自

这是基于公认的答案,只要您没有遇到任何字符,就可以正常工作。如果您需要完全的Unicode支持(谁不需要?),请使用此Unicode安全的代码:

public class FileNameCleaner {
  final static int[] illegalChars = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47};

  static {
    Arrays.sort(illegalChars);
  }

  public static String cleanFileName(String badFileName) {
    StringBuilder cleanName = new StringBuilder();
    int len = badFileName.codePointCount(0, badFileName.length());
    for (int i=0; i<len; i++) {
      int c = badFileName.codePointAt(i);
      if (Arrays.binarySearch(illegalChars, c) < 0) {
        cleanName.appendCodePoint(c);
      }
    }
    return cleanName.toString();
  }
}
公共类文件名清理器{
最终静态int[]非法字符={34,60,62,124,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,58,42,63,92,47};
静止的{
数组。排序(非法字符);
}
公共静态字符串cleanFileName(字符串badFileName){
StringBuilder cleanName=新的StringBuilder();
int len=badFileName.codePointCount(0,badFileName.length());

对于(int i=0;i如果您想使用更像[A-Za-z0-9]的字符,请检查,不要忘记过滤掉“…整数表示形式在1到31之间的字符,…”,如Aaron Digulla的示例。例如,来自David Carboni的代码对于这些字符是不够的

包含保留字符列表的摘录:

使用当前代码页中的任何字符作为名称,包括Unicode字符和扩展字符集(128–255)中的字符,但以下字符除外:

以下保留字符:

  • <
    
    public class FileNameCleaner {
      final static int[] illegalChars = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47};
    
      static {
        Arrays.sort(illegalChars);
      }
    
      public static String cleanFileName(String badFileName) {
        StringBuilder cleanName = new StringBuilder();
        int len = badFileName.codePointCount(0, badFileName.length());
        for (int i=0; i<len; i++) {
          int c = badFileName.codePointAt(i);
          if (Arrays.binarySearch(illegalChars, c) < 0) {
            cleanName.appendCodePoint(c);
          }
        }
        return cleanName.toString();
      }
    }
    
    public static String removeInvalidChars(final String fileName)
    {
      try
      {
        Paths.get(fileName);
        return fileName;
      }
      catch (final InvalidPathException e)
      {
        if (e.getInput() != null && e.getInput().length() > 0 && e.getIndex() >= 0)
        {
          final StringBuilder stringBuilder = new StringBuilder(e.getInput());
          stringBuilder.deleteCharAt(e.getIndex());
          return removeInvalidChars(stringBuilder.toString());
        }
        throw e;
      }
    }