properties类不直接支持多语言属性文件的解决方法
我们在开发的时候经常需要使用properties存储需要的一些属性,我们往往将需要的属性存储在一个文件里面,然后使用properties.load()方法加载那些属性,对于中国的用户,这些文件一般都是需要包含中文的,但是properties类的load方法不支持中文或者其他的双字节的编码,我们往往需要使用java的另外一个工具native2ascii将那个文件转换为unicode的转义序列的形式,但是这样一来文件的内容又不可读了,需要我们重复进行转换的工作,有时候很麻烦,笔者也常常遇到这个问题,后来查看了一下properties的源代码,发现其实这个问题很好修正,因为properties的load方法的第一行代码规定了文件的编码,我们简单的去掉那个编码即可。
jdk的源代码的第一行语句为:
bufferedreader in = new bufferedreader(new inputstreamreader(instream, "8859_1"));
我们只去掉后面规定的那个编码就可以实现平台相关的编码方式,为了避免直接修改源代码,我们重新定义一个类,例如:
package org.jr.util;import java.util.*;import java.io.*;public class properties extends java.util.properties { private static final string keyvalueseparators = "=: f"; private static final string strictkeyvalueseparators = "=:"; private static final string specialsavechars = "=: f#!"; private static final string whitespacechars = " f"; public synchronized void load(inputstream instream) throws ioexception { bufferedreader in = new bufferedreader(new inputstreamreader(instream)); while (true) { // get next line string line = in.readline(); if (line == null) { return; } if (line.length() > 0) { // continue lines that end in slashes if they are not comments char firstchar = line.charat(0); if ( (firstchar != ´#´) && (firstchar != ´!´)) { while (continueline(line)) { string nextline = in.readline(); if (nextline == null) { nextline = ""; } string loppedline = line.substring(0, line.length() - 1); // advance beyond whitespace on new line int startindex = 0; for (startindex = 0; startindex < nextline.length(); startindex++) { if (whitespacechars.indexof(nextline.charat(startindex)) == -1) { break; } } nextline = nextline.substring(startindex, nextline.length()); line = new string(loppedline + nextline); } // find start of key int len = line.length(); int keystart; for (keystart = 0; keystart < len; keystart++) { if (whitespacechars.indexof(line.charat(keystart)) == -1) { break; } } // blank lines are ignored if (keystart == len) { continue; } // find separation between key and value int separatorindex; for (separatorindex = keystart; separatorindex < len; separatorindex++) { char currentchar = line.charat(separatorindex); if (currentchar == ´/´) { separatorindex++; } else if (keyvalueseparators.indexof(currentchar) != -1) { break; } } // skip over whitespace after key if any int valueindex; for (valueindex = separatorindex; valueindex < len; valueindex++) { if (whitespacechars.indexof(line.charat(valueindex)) == -1) { break; } } // skip over one non whitespace key value separators if any if (valueindex < len) { if (strictkeyvalueseparators.indexof(line.charat(valueindex)) != -1) { valueindex++; // skip over white space after other separators if any } } while (valueindex < len) { if (whitespacechars.indexof(line.charat(valueindex)) == -1) { break; } valueindex++; } string key = line.substring(keystart, separatorindex); string value = (separatorindex < len) ? line.substring(valueindex, len) : ""; // convert then store key and value key = loadconvert(key); value = loadconvert(value); put(key, value); } } } } /* * returns true if the given line is a line that must * be appended to the next line */ private boolean continueline (string line) { int slashcount = 0; int index = line.length() - 1; while((index >= 0) && (line.charat(index--) == ´/´)) slashcount++; return (slashcount % 2 == 1); } /* * converts encoded /uxxxx to unicode chars * and changes special saved chars to their original forms */ private string loadconvert (string thestring) { char achar; int len = thestring.length(); stringbuffer outbuffer = new stringbuffer(len); for(int x=0; x<len; ) { achar = thestring.charat(x++); if (achar == ´/´) { achar = thestring.charat(x++); if(achar == ´u´) { // read the xxxx int value=0; for (int i=0; i<4; i++) { achar = thestring.charat(x++); switch (achar) { case ´0´: case ´1´: case ´2´: case ´3´: case ´4´: case ´5´: case ´6´: case ´7´: case ´8´: case ´9´: value = (value << 4) + achar - ´0´; break; case ´a´: case ´b´: case ´c´: case ´d´: case ´e´: case ´f´: value = (value << 4) + 10 + achar - ´a´; break; case ´a´: case ´b´: case ´c´: case ´d´: case ´e´: case ´f´: value = (value << 4) + 10 + achar - ´a´; break; default: throw new illegalargumentexception( "malformed /uxxxx encoding."); } } outbuffer.append((char)value); } else { if (achar == ´t´) achar = ´ ´; else if (achar == ´r´) achar = ´´; else if (achar == ´n´) achar = ´´; else if (achar == ´f´) achar = ´f´; outbuffer.append(achar); } } else outbuffer.append(achar); } return outbuffer.tostring(); }}
请注意:以上的代码全部是jdk源代码本身的内容,只是修改了load方法的第一行语句,为了正常编译引入了一些其他的方法。
以上的这个类就可以正常加载中文或者其他的语言的文件,但是有一点需要注意:它只能正常加载文件的编码和操作系统的默认编码相同的文件,如果你的文件是日文的,但是你的操作系统的默认语言是中文,那么这个类读取的文件也会有问题,当然,给这个类增加一个方法指定编码方式也是可以的。
闽公网安备 35060202000074号