Java file.encoding

简介: 问题 在idea上开发阿里云SCB接口时,发现一个问题,在main方法中执行方法: STDOrg org = CSBUtil.getRealOrgInfo("李氏餐饮店", "92120610MA16CR3U21"); 能够正确获取到信息。

问题

在idea上开发阿里云SCB接口时,发现一个问题,在main方法中执行方法:

STDOrg org = CSBUtil.getRealOrgInfo("李氏餐饮店", "92120610MA16CR3U21");

能够正确获取到信息。而使用idea启动项目,在项目的定时任务中执行相同的代码,却报出了:

signature verification failed

一模一样的代码,为什么执行结果会一个成功一个签名验证呢。

参数都是一样的,首先排除了参数问题。回头去查看SCB文档,发现:

SDK在将参数签名完成后,在发送给服务端之前,会把请求参数进行URLEncoder编码,编码方式为当前Java系统中的file.encoding系统参数所指定的值。

如请求参数中包含有中文,并且客户单的系统Charset编码参数与服务端的不一致的时候,当使用GET方式调用就可能出现验签失败的问题;

当这种情况发生时要检查两端的Charset编码是否一致, 可以在SDK客户端设置编码方式(如: -Dfile.encoding=UTF-8)使编码与服务器一致。如果你的中文参数是写死在Java程序代码中,需要保证源码的编码方式与服务端要求的一致,否则也会出现签名失败的问题.

怀疑是编码问题。于是在main方法和项目中分别使用:

System.out.println(System.getProperty("file.encoding"));

输出file.encoding属性,果然main中编码为UTF-8,项目中是GBK,至此确认了是编码问题。

main中执行成功,说明对方的编码是使用的UTF-8。因为我的项目在tomcat中部署,所以打开idea的tomcat部署设置:
_

在图中处填入jvm参数:

-Dfile.encoding=UTF-8

如果是jar启动,请在参数中也指定:

-Dfile.encoding=UTF-8

还可以直接修改tomcat配置文件,如果部署在Linux系统,可以在catalina.sh加入如下配置:

JAVA_OPTS="-Xms7168m -Xmx7168m -Dfile.encoding=UTF8"

如果是windows系统,则为:

set "JAVA_OPTS=-Xms7168m -Xmx7168m -Dfile.encoding=UTF8"

忽略内存配置,主要是-Dfile.encoding=UTF8,这时候就解决了file.encoding的问题。
当然如果编码和对方一致,不需做如上处理。

什么决定了file.encoding属性?

在main方法中,main方法所在类文件的编码决定了file.encoding属性。在启动java虚拟机时,idea自动将文件属性中的编码设置为运行时参数。所以在main中执行成功。

在使用tomcat启动项目时,如果不手动设置file.encodinng值,这时系统不知道用什么编码,所以只能采用系统默认编码,windows系统的默认编码是GBK,所以签名验证失败了。

可以看下面关于file.encoding的一段话:

This property is used for the default encoding in Java, all readers and writers would default to use this property. “file.encoding” is set to the default locale of Windows operationg system since Java 1.4.2. System.getProperty(“file.encoding”) can be used to access this property. Code such as System.setProperty(“file.encoding”, “UTF-8”) can be used to change this property. However, the default encoding can not be changed dynamically even this property can be changed. So the conclusion is that the default encoding can’t be changed after JVM starts. “java -Dfile.encoding=UTF-8” can be used to set the default encoding when starting a JVM.

附1:String获取默认编码源码:

查看String的getBytes方法,可以看到如下:

    public byte[] getBytes() {
        return StringCoding.encode(value, 0, value.length);
    }

继续:

    static byte[] encode(char[] ca, int off, int len) {
        String csn = Charset.defaultCharset().name();
        // 省略......
    }

看到获取默认编码的是Charset.defaultCharset(),查看:

    public static Charset defaultCharset() {
        if (defaultCharset == null) {
            synchronized (Charset.class) {
                String csn = AccessController.doPrivileged(
                    new GetPropertyAction("file.encoding"));
                Charset cs = lookup(csn);
                if (cs != null)
                    defaultCharset = cs;
                else
                    defaultCharset = forName("UTF-8");
            }
        }
        return defaultCharset;
    }

先去获取file.encoding属性,如果没有,默认返回"UTF-8"。在windows系统file.encoding=GBK,所以会导致文中的错误。

附2:idea控制台乱码处理

修改tomcatfile.encoding属性后,发现idea控制台乱码了,处理方法为打开Intellij的安装的bin目录,找到如下两个文件:

idea.exe.vmoptions
idea64.exe.vmoptions

根据系统是32位或64位选择其中一个配置文件,在配置文件中添加:

-Dfile.encoding=UTF-8
目录
相关文章
|
6月前
启动报错:java.nio.charset.MalformedInputException: Input length = 1
启动报错:java.nio.charset.MalformedInputException: Input length = 1
106 0
|
5月前
|
Scala
scala 读取文件(中文)异常 thread "main" java.nio.charset.MalformedInputException: Input length = 1
scala 读取文件(中文)异常 thread "main" java.nio.charset.MalformedInputException: Input length = 1
53 0
|
6月前
|
Java Spring
解决org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 2
解决org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 2
251 1
|
6月前
|
Java
SpringBoot 运行出现java.nio.charset.MalformedInputException: Input length = 1
SpringBoot 运行出现java.nio.charset.MalformedInputException: Input length = 1
124 0
|
6月前
|
Java
Java-File
Java-File
27 0
|
Java
【Java】File类
【Java】File类
139 0
|
Java
Java中File类的使用
Java中File类的使用
91 0
Caused by: java.nio.charset.MalformedInputException: Input length = 1
Caused by: java.nio.charset.MalformedInputException: Input length = 1
328 0
Caused by: java.nio.charset.MalformedInputException: Input length = 1
|
Java Maven Nacos
org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1
IDEA中使用maven的打包命令install来对项目打包,出现了这个错误。 org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1
677 0
org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1
|
Java
【java】之File类
【java】之File类
112 0
【java】之File类