文件的存储使用的编码格式与文件读取时的格式不一致. 例如, 在java中, 读取文件的默认格式是iso8859-1, 而我们中文存储的时候一般是UTF-8. 所以导致读出来的是乱码,直接抛出如下异常:
Can't find resource for bundle java.util.PropertyResourceBundle, key WebImage
所以要想读中文,只有把文件转换为UTF-8的ascii码才可以。
原来在文件读取的时候,读的文件与被读的文件之间的编码会成为问题。JAVA支持的字符编码集是unicode,即System.out.print("/uXXXX")便可以输出在UNICODE里对应的字符,native2ascii做的就是这件事,把每个各种编码的字符转换成unicode中对应的ascii码(以ascii的形式保存unicode文字内容,所以中文乱码)。在iso8859-1中根本没有对应中文的ascii码那么势必无法利用这样的文件保存中文了,所以,只有使用正确的字符集对编码进行解析才可以获得想要的字符。
经历:
开始的时候记事本建立一个属性文件,保存时编码是:UTF-8, 然后就提示上面的异常。
然后打开后在另存为时把编码选为ASCII,同时把源文件覆盖,然后就没有显示上面的异常了,但是中文出现了乱码。
然后:
把String test = rb.getString("IpToolButton");
替换为
String test = new String(rb.getString("IpToolButton").getBytes("ISO-8859-1"), "GBK");
就没有显示乱码了。
然后干脆用native2ascii命令转化unicode编码: native2ascii GlobalElements.properties GlobalElements.txt
转换后的记事本中原来的中文都是乱码,英文还是原样,然后直接把后缀名改成properties,把原来的那个属性文件删除了。然后
程序中就可以直接用String test = rb.getString("IpToolButton"); 而且输出的就是原来的中文。
native2ascii 后面直接两个相同的文件时,并不能把源文件转化成相应编码的目标文件。
ResourceBundle rb = ResourceBundle.getBundle("GlobalElements2");
//String test = new String(rb.getString("IpToolButton").getBytes("ISO-8859-1"), "GBK");
String test = rb.getString("IpToolButton");
Reporter.log(test);
System.out.println(test);
其他就是关于属性文件放在哪里的问题,参考如下英文【以下转载】:
转:解决 java.util.MissingResourceException: Can't find bundle for base name com...config, locale zh_CN 错误
Solve java.util.MissingResourceException: Can't find bundle for base name com...config, locale zh_CNat java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:836)
at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:805)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:576)
You know java is looking for a properties file in a specific locale. You may be baffled why java keeps complaining it can't find a properties file that is right there. A few things to keep in mind when debugging this type of errors:
- These resource properties files are loaded by classloader, similar to java classes. So you need to include them in your runtime classpath.
- These resources have fully-qualified-resource-name, similar to a fully-qualified-class-name, excerpt you can't import a resource into your java source file. Why? because its name takes the form of a string.
-
ResourceBundle.getBundle("config")
tells the classloader to load a resource named"config"
with default package (that is, no package). It does NOT mean a resource in the current package that has the referencing class. ResourceBundle.getBundle("com.cheng.scrap.config")
tells the classloader to load a resource named"config"
with package"com.cheng.scrap."
Its fully-qualified-resource-name is"com.cheng.scrap.config"
For instance, you have a project like
C:/ws/netbeans5/scrap>
| build.xml
+---build
| /---classes
| /---com
| /---cheng
| /---scrap
| Scrap.class
|
+---src
| /---com
| /---cheng
| /---scrap
| config.properties
| Scrap.java
For this statement in Scrap.java: ResourceBundle config = ResourceBundle.getBundle("config");
to work, you will need to cp src/com/cheng/scrap/config.properties build/classes/
such that config.properties
is directly under classes
, and at the same level as com
. Alternatively, you can put config.properties
into a config.jar
such that config.properties
is at the root of config.jar
without any subdirectories, and include config.jar
in the classpath.
For this statement in Scrap.java: ResourceBundle config = ResourceBundle.getBundle("com.cheng.scrap.config");
to work, you will need to cp src/com/cheng/scrap/config.properties build/classes/
com/cheng/scrap/
such that config.properties
is directly under classes
/
com/cheng/scrap/
, and at the same level as scrap
. Alternatively, you can put com/cheng/scrap/
config.properties
(along with the long subdirectories) into a config.jar
, and include
config.jar
in the classpath.
You may be wondering why it is made so confusing? The benefits are two-fold, as I see it:
- Location transparency. At runtime, config.properties is NOT a file, it's just a a loadable resource. config.properites may not exist in your project at all, and the person who wrote Scrap.java may have never seen this resource. A URLClassLoader can find it in a network path or URL at runtime. This is especially important for server-side components such as EJB, Servlet, JSP, etc, who are normally not allowed to access file systems. When you ask classloaders for a resource, its physical location becomes irrelevant.
- Namespace mechanism. Having a package allows multiple packages to have resources with the same short name without causing conflicts. This is no different from java packages and xml namespaces.