我想构建resourcebundles,它只包含属性文件中键/值对的一部分,因此与在单个文件中存储这些部分或节相比,可以节省大量的文件。各节以“#”开头的标题行标记,并用空行分隔。下面代码后面的示例属性文件包含两个部分:
文件选择器
选项窗格
我试图通过在getbundle(…)方法中传递一个定制的类加载器来实现这一点,该类加载器只读取所需的部分。customclassloader可以很好地减少键定义,但是resourcebundle仍然包含属性文件的所有键。
import java.io.*;
import java.util.*;
public class ResourceReader {
public ResourceReader() {
Locale locale= Locale.getDefault();
ResourceBundle i18n= ResourceBundle.getBundle("ComponentBundle", locale,
new CustomClassLoader("#FileChooser"));
Enumeration<String> enu= i18n.getKeys();
System.out.println("Keys of ResourceBundle");
printEnumeration(enu);
}
public static void main(String args[]) {
new ResourceReader();
}
public void printEnumeration(Enumeration<String> enu) {
int i= 1;
while (enu.hasMoreElements()) {
System.out.println(i+".: "+enu.nextElement());
i++;
}
}
//////////////////////////////////////////////////////////////////////////////
public class CustomClassLoader extends ClassLoader {
String section;
public CustomClassLoader(String section) {
this.section= section;
}
@Override
public Class findClass(String name) throws ClassNotFoundException {
byte[] b = loadClassFromFile(name);
//System.out.writeBytes(b); // OK.
return defineClass(name, b, 0, b.length);
}
private byte[] loadClassFromFile(String fileName) {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(
fileName.replace('.', File.separatorChar) + ".properties");
byte[] buffer;
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
int nextValue = 0;
try {
while ( (nextValue = inputStream.read()) != -1 ) {
byteStream.write(nextValue);
}
} catch (IOException e) {
e.printStackTrace();
}
buffer = extractSection(byteStream.toString(), section);
return buffer;
}
private byte[] extractSection(String stream, String caption) {
final String LINE_SEP= System.getProperty("line.separator", "\n");
String[] lines= stream.split(LINE_SEP);
// Detect first and last line (exclusive) of section.
int iEnd= 0, iStart= -1;
for (int i=0; i<lines.length; i++) {
lines[i]= lines[i].trim();
if (iStart==-1) {
if (!lines[i].equals(caption)) continue;
iStart= i+1;
i++;
}
else if (lines[i].isEmpty()) {
iEnd= i;
break;
}
}
if (iEnd==0) iEnd= lines.length+1;
StringBuilder sb= new StringBuilder();
for (int i=iStart; i<iEnd; i++)
sb.append(lines[i]+LINE_SEP);
return sb.toString().getBytes();
}
}
}
//////////////////////////////////////////////////////////////////////////////
/*//文件componentbundle.properties
# FileChooser
acceptAllFileFilterText= All files (*.*)
cancelButtonText= Cancel
cancelButtonToolTipText= Cancel
# OptionPane
Cancel= Cancel
Input= Input
Message= Message
No= No
// End of ComponentBundle.properties
- /
2条答案
按热度按时间jtoj6r0c1#
如果您确实想使用resourcebundle的一个子集,这可能是一种方法——尽管不是很优雅,因为需要读取和过滤整个包。
wgx48brx2#
你不会得到你的限制资源包这样,因为你已经过度骑
findClass
以类的形式返回属性文件的字节。要了解发生了什么,请添加以下代码:然后你就可以看到
ResourceBundle
会查找所有键,因为它正在加载文件url的内容-并且您的代码未被使用:如果您重写,就有可能使捆绑程序正常工作
getResource(String name)
并使其生成一个适合于密钥子集的文件,将url传回子集文件。当您可以为所有应用程序定义一个资源包文件,或者为每个子组件定义一个资源包文件时,似乎需要做很多工作。