如何安全地将一个字符串编码为Java中的文件名? [英] How can I safely encode a string in Java to use as a filename?

查看:139
本文介绍了如何安全地将一个字符串编码为Java中的文件名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从外部进程收到一个字符串。我想使用该字符串来创建一个文件名,然后写入该文件。这是我的代码片段:

  String s = ... //来自外部源
文件currentFile = new File(System.getProperty(user.home),s);
PrintWriter currentWriter = new PrintWriter(currentFile);

如果s包含无效字符,例如基于Unix的操作系统中的/,则java.io.FileNotFoundException是(正确地)抛出。



如何安全地对String进行编码,以便它可以用作文件名?



编辑:我希望是一个API调用,为我做这个。



我可以这样做:

  String s = ... //来自外部源
文件currentFile =新文件(System.getProperty(user.home ),URLEncoder.encode(s,UTF-8));
PrintWriter currentWriter = new PrintWriter(currentFile);

但我不知道URLEncoder是否可靠,为此目的。

解决方案

如果您希望结果与原始文件类似,SHA-1或任何其他散列方案不是答案。相反,你想要这样的东西。

  char fileSep ='/'; // ...或者可以这样做。 
char escape ='%'; // ...或一些其他合法的字符。
String s = ...
int len = s.length();
StringBuilder sb = new StringBuilder(len); (int i = 0; i char ch = s.charAt(i);

if(ch <''|| ch> = 0x7F || ch == fileSep || ... //添加其他非法字符
||(ch =='。'& & i == 0)//我们不想与。或..碰撞
|| ch == escape){
sb.append(escape);
if(ch< 0x10){
sb.append('0');
}
sb.append(Integer.toHexString(ch));
} else {
sb.append(ch);
}
}
文件currentFile =新文件(System.getProperty(user.home),sb.toString());
PrintWriter currentWriter = new PrintWriter(currentFile);

此解决方案提供了一种可逆编码(无冲突),其中编码的字符串与大部分原始字符串相似案例。我假设你正在使用8位字符。



URLEncoder的缺点是它编码了大量合法的文件名字符。



如果你想要不可保证的可逆解决方案,然后简单地删除坏字符,而不是用转义序列替换它们。


I'm receiving a string from an external process. I want to use that String to make a filename, and then write to that file. Here's my code snippet to do this:

    String s = ... // comes from external source
    File currentFile = new File(System.getProperty("user.home"), s);
    PrintWriter currentWriter = new PrintWriter(currentFile);

If s contains an invalid character, such as '/' in a Unix-based OS, then a java.io.FileNotFoundException is (rightly) thrown.

How can I safely encode the String so that it can be used as a filename?

Edit: What I'm hoping for is an API call that does this for me.

I can do this:

    String s = ... // comes from external source
    File currentFile = new File(System.getProperty("user.home"), URLEncoder.encode(s, "UTF-8"));
    PrintWriter currentWriter = new PrintWriter(currentFile);

But I'm not sure whether URLEncoder it is reliable for this purpose.

解决方案

If you want the result to resemble the original file, SHA-1 or any other hashing scheme is not the answer. Instead you want something like this.

char fileSep = '/'; // ... or do this portably.
char escape = '%'; // ... or some other legal char.
String s = ...
int len = s.length();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++) {
    char ch = s.charAt(i);
    if (ch < ' ' || ch >= 0x7F || ch == fileSep || ... // add other illegal chars
        || (ch == '.' && i == 0) // we don't want to collide with "." or ".."!
        || ch == escape) {
        sb.append(escape);
        if (ch < 0x10) {
            sb.append('0');
        }
        sb.append(Integer.toHexString(ch));
    } else {
        sb.append(ch);
    }
}
File currentFile = new File(System.getProperty("user.home"), sb.toString());
PrintWriter currentWriter = new PrintWriter(currentFile);

This solution gives a reversible encoding (with no collisions) where the encoded strings resemble the original strings in most cases. I'm assuming that you are using 8-bit characters.

URLEncoder has the disadvantage that it encodes a whole lot of legal file name characters.

If you want a not-guaranteed-to-be-reversible solution, then simply remove the 'bad' characters rather than replacing them with escape sequences.

这篇关于如何安全地将一个字符串编码为Java中的文件名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆