首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >File.toURI不编码加号

File.toURI不编码加号
EN

Stack Overflow用户
提问于 2017-10-09 10:30:30
回答 5查看 1.7K关注 0票数 4

我只想用这个问题来检查我自己的理智。我有一个文件名,其中包含一个+ (加号)字符,它在某些操作系统和文件系统(例如MacOS和HFS+)上完全有效。

然而,我看到一个问题,我认为java.io.File#toURI()的操作不正确。

例如:

代码语言:javascript
复制
new File("hello+world.txt").toURI().toString()

在我的Mac机器上返回:

代码语言:javascript
复制
file:/Users/aretter/code/rocksdb/hello+world.txt

但是IMHO,这是不正确的,因为文件名中的+ (加号)字符没有在URI中编码。URI根本不表示原始文件名,URI中的+与文件名中的+字符的含义非常不同。

因此,如果我们解码URI,加号将被替换为(空格)字符,并且我们丢失了信息。例如:

代码语言:javascript
复制
URLDecoder.decode(new File("hello+world.txt").toURI().toURL().toString)

其结果是:

代码语言:javascript
复制
file:/Users/aretter/code/rocksdb/hello world.txt

相反,我所期望的是:

代码语言:javascript
复制
new File("hello+world.txt").toURI().toString()

其结果是:

代码语言:javascript
复制
file:/Users/aretter/code/rocksdb/hello+world.txt

因此,在以后使用和解码时,加号将被保留。

我很难相信这样一个明显的错误可能存在于Java中。有人能指出我哪里弄错了吗?

另外,如果有解决办法,我想听听吗?请记住,我实际上并不是将静态字符串作为文件名提供给File,而是从磁盘读取文件目录,其中一些文件可能包含一个+ (加号)字符。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2017-10-23 20:45:16

让我澄清一下,

  • 在HTML表单(a.k.a )的上下文中,“+”加号用作编码字符,以编码“”空间。应用程序/x表单-urlencoded格式)。
  • “%20”字符用作编码字符,在URL/URI格式的上下文中编码“”空间。

'+‘+字符是作为URL上下文中的正常字符的威胁,它不以任何形式编码(例如%20)。

因此,当您调用new File("hello+world.txt").toURI().toString()时,它不会对'+‘字符执行任何编码(仅仅因为它不是必需的)。

现在来看看URLDecoder这个类是一个用于HTML解码的实用类。它将“+”加号视为编码字符,从而将其解码为“”空格字符。在您的示例中,该类将URI的字符串值作为普通的html表单字段的值(而不是URI值)。这个类不应该用于解码完整的URI/URL值,因为它不是为此目的而设计的)

来自URLDecoder#decode的java文档(字符串)

解码x-www格式-urlencoded字符串。平台的默认编码用于确定由窗体"%xy“的任何连续序列表示的字符。

希望能帮上忙。

基于注释的更新#1:

根据第2.2节,如果URI组件的数据与保留字符有冲突,那么在形成URI之前,冲突的数据必须是百分比编码的。

同样重要的一点是,URI的不同部分根据上下文有不同的保留词集。例如,只在URI的路径部分保留/符号,在查询字符串部分保留+符号。因此,在查询部分不需要转义/,在路径部分也不需要转义+

在您的示例中,URI生产者File.toURI不会在URI的路径部分编码+签名(因为+' is not considered as reserved word in path part) and you see the +‘登录到URI的字符串表示形式。

有关更多细节,您可以参考URI推荐

有关答覆:

  1. https://stackoverflow.com/a/1006074/1700467
  2. https://stackoverflow.com/a/2678602/1700467
  3. https://stackoverflow.com/a/4571518/1700467
票数 3
EN

Stack Overflow用户

发布于 2017-10-24 16:33:41

我假设,您希望将+签名编码到%2B文件名中。所以,当你把它解码回来的时候,你会得到它作为+签名。

如果是这样的话,则需要使用URLEncoder.encode

代码语言:javascript
复制
System.out.println(URLEncoder.encode(new File("hello+world.txt").toURI().toString()));

它将编码所有特殊字符,包括+符号。输出将是

代码语言:javascript
复制
file%3A%2Fhome%2FT8hvs7%2Fhello%2Bworld.txt

现在,要使用URLDecoder.decode进行解码

代码语言:javascript
复制
System.out.println(URLDecoder.decode("file%3A%2Fhome%2FwQCXni%2Fhello%2Bworld.txt"));

它会显示

代码语言:javascript
复制
file:/home/wQCXni/hello+world.txt
票数 1
EN

Stack Overflow用户

发布于 2017-10-23 20:32:32

显然,这不是一个bug,文档清楚地说

代码语言:javascript
复制
The plus sign "+" is converted into a space character " " .

你可以这样做:https://ideone.com/JHDkM4

代码语言:javascript
复制
import java.util.*;
import java.lang.*;
import java.io.*;
import static java.lang.System.out;


class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        out.println(new File("hello+world.txt").toURI().toString());
        out.println(java.net.URLDecoder.decode(new File("hello+world.txt").toURI().toURL().toString()));
        out.println(new File("hello+world.txt").toURI().toString().replaceAll("\\+", "%2B"));
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46644306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档