可能影响File.getCanonicalPath的java环境或charset设置

时间:2016-05-13 12:42:22

标签: java character-encoding jvm

我想创建一个包含中文字符的文件夹,但文件夹名称错误。中文字符被'?'取代。这是我的代码:

    String pathname = "/tmp/测试-" + Bytes.toHexLower(Bytes.random(16));
    File file = new File(pathname);
    log.info("test", "pathname=[" + pathname + "]");
    log.info("test", "path=[" + file.getPath() + "]");
    log.info("test", "file.encoding=[" + System.getProperty("file.encoding") + "]");
    log.info("test", "defaultCharset=[" + Charset.defaultCharset() + "]");
    try {
        log.info("test", "canonicalPath=[" + file.getCanonicalPath() + "]");
    } catch (IOException e) {
        log.error("test", e);
    }
    file.mkdir();

日志是:

    pathname=[/tmp/测试-7ba077d59e8b6b550fe4f032fc30afda]
    path=[/tmp/测试-7ba077d59e8b6b550fe4f032fc30afda]
    canonicalPath=[/tmp/??-7ba077d59e8b6b550fe4f032fc30afda]
    file.encoding=[UTF-8]
    defaultCharset=[UTF-8]

文件名“/ tmp /测试-7ba0 ...”更改为“/ tmp / ?? - 7ba0 ...”,但file.encoding和defaultCharset似乎没问题。

是否存在可影响File.getCanonicalPath的其他环境或字符集设置?

UPDATE-1

我添加了以下代码来转储System.getenv():

    for (Map.Entry<String, String> entry : new TreeMap<>(System.getenv()).entrySet()) {
        log.info("test", "env(" + entry.getKey() + ")=[" + entry.getValue() + "]");
    }

在创建错误的文件夹名称的环境中,我得到了:

    env(CONSOLETYPE)=[vt]
    env(JAVA_OPTS)=[-Dfile.encoding=UTF-8]
    env(LANG)=[en_US.UTF-8]
    env(LANGSH_SOURCED)=[1]
    env(LC_ALL)=[C]
    env(NLSPATH)=[/usr/dt/lib/nls/msg/%L/%N.cat]
    env(PATH)=[/sbin:/usr/sbin:/bin:/usr/bin]
    env(PREVLEVEL)=[N]
    env(PWD)=[/root]
    env(RUNLEVEL)=[3]
    env(SHLVL)=[4]
    env(TERM)=[linux]
    env(UPSTART_EVENTS)=[runlevel]
    env(UPSTART_INSTANCE)=[]
    env(UPSTART_JOB)=[rc]
    env(XFILESEARCHPATH)=[/usr/dt/app-defaults/%L/Dt]
    env(_)=[/usr/bin/java]
    env(previous)=[N]
    env(runlevel)=[3]

可以使用python脚本启动tomcat(startup.sh)。

在创建正确的文件夹名称的环境中,我得到了:

    env(ENV_GROUP)=[FAT]
    env(ENV_NAME)=[T6]
    env(HISTSIZE)=[1000]
    env(HOME)=[/root]
    env(HOSTNAME)=[t6.dcfservice.com]
    env(LANG)=[en_US.UTF-8]
    env(LC_ALL)=[en_US.UTF-8]
    env(LOGNAME)=[root]
    env(LS_COLORS)=[rs=0:di=01;...
    env(MAIL)=[/var/spool/mail/develop]
    env(NLSPATH)=[/usr/dt/lib/nls/msg/%L/%N.cat]
    env(PATH)=[/sbin:/bin:/usr/sbin:/usr/bin]
    env(PWD)=[/home/develop]
    env(SHELL)=[/bin/bash]
    env(SHLVL)=[2]
    env(SUDO_COMMAND)=[/usr/bin/restart_tomcat.sh]
    env(SUDO_GID)=[1503]
    env(SUDO_UID)=[1503]
    env(SUDO_USER)=[develop]
    env(TERM)=[vt100]
    env(USER)=[root]
    env(USERNAME)=[root]
    env(XFILESEARCHPATH)=[/usr/dt/app-defaults/%L/Dt]
    env(_)=[/usr/bin/java]

使用SSH客户端启动tomcat。

UPDATE-2

根据VGR和zapl的建议使用 Path

    try {
        pathname = "/tmp/测试-" + Bytes.toHexLower(Bytes.random(16));
        Path path = Paths.get(pathname);
        log.info("test", "pathname=[" + pathname + "]");
        Files.createDirectory(path);
    } catch (Error | RuntimeException | IOException e) {
        log.error("test", e);
    }

在第一个tomcat(由python脚本启动)中,我得到了:

SEVERE: Exception sending context initialized event to listener instance of class com.iqunxing.cashier.Context
java.nio.file.InvalidPathException: Malformed input or input contains unmappable characters: /tmp/测试-1ca8f20c3deccbf7aabe625397e2d3
    at sun.nio.fs.UnixPath.encode(UnixPath.java:147)
    at sun.nio.fs.UnixPath.<init>(UnixPath.java:71)
    at sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:281)
    at java.nio.file.Paths.get(Paths.java:84)
    at com.iqunxing.cashier.Context.contextInitialized(Context.java:137)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4994)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5492)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1245)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1895)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

在第二个tomcat(由SSH客户端启动)中,我获得了正确的文件夹名称。

UPDATE-3

设置-Dsun.jnu.encoding = UTF-8(当文件夹未正确创建时为ANSI_X3.4-1968)时,File.mkdir()仍会创建错误的文件夹,但Files.createDirectory(path)工作正常(显示正确的中文)字符)。

分辨

在zapl提示,在catalina.sh中添加export LC_ALL=en_US.UTF-8后,File.getCanonicalPath不再返回错误的文件夹名称。

0 个答案:

没有答案