为什么在Unicode目录中运行Mac上的Scala失败

时间:2019-04-09 14:26:12

标签: java macos scala unicode

我试图从使用Unicode字符命名的目录中简单地编译helloworld scala文件,但是scala编译器无法运行。当我将目录的unicode更改为文件夹时,它会成功。

详细信息

给出经典的Helloworld.scala类,例如下面的类 位于目录中:

/Users/me/Dev/Company//code_folder

如果我的当前目录位于Helloworld.scala的根目录 code_folder 中,则无法对代码运行scalac。当我用Unicode名称/从文件夹中更改目录时,编译器在相同的代码上也可以正常工作。因此,当在带有unicode字符的文件夹中尝试编译代码时,scalac似乎不起作用。 这是为什么?这是系统错误吗?操作系统在启动scalac进程之间出现无法解析的unicode错误?

object Main{
    def main(args:  Array[String]): Unit = {
        println("Hello world")
    }
}

我希望有一个已编译的文件。我得到的错误是这个

Exception in thread "main" java.lang.ExceptionInInitializerError
    at scala.tools.util.PathResolver$Environment$.scalaExtDirs(PathResolver.scala:77)
    at scala.tools.util.PathResolver$Defaults$.scalaExtDirs(PathResolver.scala:127)
    at scala.tools.nsc.settings.StandardScalaSettings.$init$(StandardScalaSettings.scala:31)
    at scala.tools.nsc.settings.MutableSettings.<init>(MutableSettings.scala:28)
    at scala.tools.nsc.Settings.<init>(Settings.scala:19)
    at scala.tools.nsc.Driver.process(Driver.scala:53)
    at scala.tools.nsc.Driver.main(Driver.scala:80)
    at scala.tools.nsc.Main.main(Main.scala)
Caused by: java.lang.IllegalArgumentException: Error decoding percent encoded characters
    at java.base/sun.net.www.ParseUtil.decode(ParseUtil.java:209)
    at java.base/jdk.internal.loader.FileURLMapper.getPath(FileURLMapper.java:64)
    at java.base/jdk.internal.loader.FileURLMapper.exists(FileURLMapper.java:73)
    at java.base/jdk.internal.loader.URLClassPath$JarLoader.getJarFile(URLClassPath.java:802)
    at java.base/jdk.internal.loader.URLClassPath$JarLoader.access$900(URLClassPath.java:692)
    at java.base/jdk.internal.loader.URLClassPath$JarLoader$1.run(URLClassPath.java:751)
    at java.base/jdk.internal.loader.URLClassPath$JarLoader$1.run(URLClassPath.java:744)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/jdk.internal.loader.URLClassPath$JarLoader.ensureOpen(URLClassPath.java:743)
    at java.base/jdk.internal.loader.URLClassPath$JarLoader.<init>(URLClassPath.java:718)
    at java.base/jdk.internal.loader.URLClassPath$3.run(URLClassPath.java:486)
    at java.base/jdk.internal.loader.URLClassPath$3.run(URLClassPath.java:469)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/jdk.internal.loader.URLClassPath.getLoader(URLClassPath.java:468)
    at java.base/jdk.internal.loader.URLClassPath.getLoader(URLClassPath.java:437)
    at java.base/jdk.internal.loader.URLClassPath.findResource(URLClassPath.java:280)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findResourceOnClassPath(BuiltinClassLoader.java:479)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findResource(BuiltinClassLoader.java:303)
    at java.base/java.lang.ClassLoader.getResource(ClassLoader.java:1393)
    at java.base/java.lang.ClassLoader.getSystemResource(ClassLoader.java:1658)
    at java.base/java.lang.ClassLoader.getSystemResourceAsStream(ClassLoader.java:1762)
    at java.base/java.lang.Class.getResourceAsStream(Class.java:2607)
    at scala.util.PropertiesTrait.scalaProps(Properties.scala:39)
    at scala.util.PropertiesTrait.scalaProps$(Properties.scala:37)
    at scala.tools.reflect.WrappedProperties$AccessControl$.scalaProps$lzycompute(WrappedProperties.scala:49)
    at scala.tools.reflect.WrappedProperties$AccessControl$.scalaProps(WrappedProperties.scala:49)
    at scala.util.PropertiesTrait.scalaPropOrNone(Properties.scala:71)
    at scala.util.PropertiesTrait.scalaPropOrNone$(Properties.scala:71)
    at scala.tools.reflect.WrappedProperties$AccessControl$.scalaPropOrNone(WrappedProperties.scala:49)
    at scala.util.PropertiesTrait.$init$(Properties.scala:83)
    at scala.tools.reflect.WrappedProperties$AccessControl$.<init>(WrappedProperties.scala:49)
    at scala.tools.reflect.WrappedProperties$AccessControl$.<clinit>(WrappedProperties.scala)
    ... 8 more

版本: 标度转换 Scala compiler version 2.12.8 -- Copyright 2002-2018, LAMP/EPFL and Lightbend, Inc.

MacOS版本10.13.6

1 个答案:

答案 0 :(得分:1)

并不是真正的解决方案,而是一些信息:

我以这种方式设置文件夹:

/home/nicolas/Private//

ClassLoader尝试加载您的项目的类时,它会在其中查找类的路径列表作为URLClassPath的列表 现在,当代码继续执行并尝试解析这些路径时,它将调用sun.net.www.ParseUtil.decode()

当我在此处放置一个断点时,我可以看到我们课程的路径是:

/home/nicolas/Private/%ed%a0%b5%ed%b4%98%ed%a0%b5%ed%b4%ab%ed%a0%b5%ed%b4%a6%ed%a0%b5%ed%b4%a0%ed%a0%b5%ed%b4%ac%ed%a0%b5%ed%b4%a1%ed%a0%b5%ed%b4%a2/target/scala-2.12/classes/

因此它以某种方式将转换为百分比编码的字符串:%ed%a0%b5%ed%b4%98%ed%a0%b5%ed%b4%ab%ed%a0%b5%ed%b4%a6%ed%a0%b5%ed%b4%a0%ed%a0%b5%ed%b4%ac%ed%a0%b5%ed%b4%a1%ed%a0%b5%ed%b4%a2

这反过来为UTF-8创建一个CharsetDecoder:

CharsetDecoder dec = ThreadLocalCoders.decoderFor("UTF-8")
                                      .onMalformedInput(CodingErrorAction.REPORT)
                                      .onUnmappableCharacter(CodingErrorAction.REPORT);

并尝试解码上述url,但失败了,这就是为什么无法加载类的原因。

现在,如果我去这里https://www.branah.com/unicode-converter并尝试将转换为%编码的字符串,它将给我

%f0%9d%94%98%f0%9d%94%ab%f0%9d%94%a6%f0%9d%94%a0%f0%9d%94%ac%f0%9d%94%a1%f0%9d%94%a2

如果在调试时,我使用此编码的字符串值更改了网址,即

/home/nicolas/Private/%f0%9d%94%98%f0%9d%94%ab%f0%9d%94%a6%f0%9d%94%a0%f0%9d%94%ac%f0%9d%94%a1%f0%9d%94%a2/target/scala-2.12/classes/

然后正确解析它并继续运行。

所以我不知道%ed%a0%b5%ed%b4%98%ed%a0%b5%ed%b4%ab%ed%a0%b5%ed%b4%a6%ed%a0%b5%ed%b4%a0%ed%a0%b5%ed%b4%ac%ed%a0%b5%ed%b4%a1%ed%a0%b5%ed%b4%a2的来源

有趣的是,如果我使用相同的网站并尝试将其转换回%ed%a0%b5%ed%b4%98%ed%a0%b5%ed%b4%ab%ed%a0%b5%ed%b4%a6%ed%a0%b5%ed%b4%a0%ed%a0%b5%ed%b4%ac%ed%a0%b5%ed%b4%a1%ed%a0%b5%ed%b4%a2,那么我也会得到

所以我有点困惑