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("1>>{0}", @"errors.token=/u753b/u9762/u8868/u793a/u9806/u304c/u4e0d/u6b63/u3067/u3059/u3002");
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;
}
}