Java从一个byte流中读取一个字符串时,将把平台相关的byte转变为平台无关的Unicode字符串。在输出时Java将把Unicode字符串转变为平台相关的byte流,如果某个Unicode字符在某个平台上不存在,将会输出一个′?′。举个例子:在日文Windows中,Java读出一个"SHIFT_JIS"编码的文件(可以是任何流)到内存中构造字符串对象,将会把"SHIFT_JIS"编码的文字转变为Unicode编码的字符串,如果把这个字符串输出又将会把Unicode字符串转化为"SHIFT_JIS"的byte流或数组:"新規作成"----->"/u65b0/u898f/u4f5c/u6210"----->"新規作成"。 由于Java 2 只能处理基于ASCII的属性文件,所以所有Unicode编码文件都要转换一下,使用ASCII转义代码。举个例子,用Notepad, EmEdit或者是Editplus打开properties文件,你将看到的都是一堆ASCII转义字符串:
# -- application --
msg.common.complete.process={0}/u304C/u5B8C/u4E86/u3057/u307E/u3057/u305F/u3002
用StreamReader, 无论是用什么编码来读取该文件,你获取到的都是那些像密码一样的东东。
再来看看下面两个语句的比较:
Console.WriteLine("2>>{0}", "errors.token=/u753b/u9762/u8868/u793a/u9806/u304c/u4e0d/u6b63/u3067/u3059/u3002");
输出结果:
1>> errors.token=/u753b/u9762/u8868/u793a/u9806/u304c/u4e0d/u6b63/u3067/u3059/u3002
2>> errors.token=画面表示順が不正です。
也就是从文件里读取出时,都如同输出1一样,无论你用什么编码。。。
因此我们要做的事就是,如何把 “/u753b”字符串 变成一个“画”字, 看上去像是在破译密码。日文环境下,日文汉字是双字节编码,由高低两个byte组合成。
[STAThread]
static void Main(string[] args)
{
string strFileName = "E://Visual Studio Project//MessageResources.properties";
Console.WriteLine(GetPropertiesText(strFileName));
Console.Read();
}
public static string GetPropertiesText(string strFileName)
{
StringBuilder sb = new StringBuilder();
using(StreamReader sr = new StreamReader(strFileName))
{
string str = null;
while ((str = sr.ReadLine()) != null)
{
Regex regex = new Regex("(////u[A-Fa-f0-9]{4})");
if(regex.IsMatch(str))
{
foreach(Match m in regex.Matches(str))
{
str = str.Replace(m.Result("$1"), GetUnicodeString(m.Result("$1").Replace("//u", "")));
}
sb.Append(str);
}
else
{
sb.Append(str);
}
sb.Append("/n");
}
}
return sb.ToString();
}
public static string GetUnicodeString(string strInput)
{
try
{
byte[] array = new byte[2];
string str = strInput;
string s1 = str.Substring(0, 2);
string s2 = str.Substring(2);
array[0] = Convert.ToByte(s1, 16);
array[1] = Convert.ToByte(s2, 16);
return System.Text.Encoding.BigEndianUnicode.GetString(array);
}
catch(Exception)
{
return strInput;
}
}