关于读属性文件(properties)的若干问题

时间:2021-12-07 19:39:30

文件的存储使用的编码格式与文件读取时的格式不一致. 例如, 在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_CN

at 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:

  1. These resource properties files are loaded by classloader, similar to java classes.  So you need to include them in your runtime classpath.
  2. 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.
  3. 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.
  4. 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.jarand 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: 

  1. 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. 
  2. 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.