我的目标是将.NET字符串(Unicode)转换为Windows1252,并在必要时将原始的UTF-8字符串存储在Base64实体中。
例如,转换为1252的字符串“Doena”仍然是“Doena”。
但是,如果您将日语的kanjii for tree (木)转换为1251,您将得到一个问号。
这些是我的测试字符串:
String doena = "DJ Doena";
String umlaut = "äöüßéèâ";
String allIn = "< ä ß á â & 木 >";
首先,我是这样转换字符串的:
using (MemoryStream ms = new MemoryStream())
{
using (StreamWriter sw = new StreamWriter(ms, Encoding.UTF8))
{
sw.Write(decoded);
sw.Flush();
ms.Seek(0, SeekOrigin.Begin);
using (StreamReader sr = new StreamReader(ms, Encoding.GetEncoding(1252)))
{
encoded = sr.ReadToEnd();
}
}
}
问题是,虽然调试字符串比较声称两者确实是相同的,所以简单的==
或.Equals()
是不够的。
这就是我试图找出是否需要base64并生成它的方法:
private static String GetBase64Alternate(String utf8Text, String windows1252Text)
{
Byte[] utf8Bytes;
Byte[] windows1252Bytes;
String base64;
utf8Bytes = Encoding.UTF8.GetBytes(utf8Text);
windows1252Bytes = Encoding.GetEncoding(1252).GetBytes(windows1252Text);
base64 = null;
if (utf8Bytes.Length != windows1252Bytes.Length)
{
base64 = Convert.ToBase64String(utf8Bytes);
}
else
{
for(Int32 i = 0; i < utf8Bytes.Length; i++)
{
if(utf8Bytes[i] != windows1252Bytes[i])
{
base64 = Convert.ToBase64String(utf8Bytes);
break;
}
}
}
return (base64);
}
第一个字符串doena
完全相同,不产生base64结果
Console.WriteLine(String.Format("{0} / {1}", windows1252Text, base64Text));
结果:
DJ Doena /
但是,第二个字符串umlauts
在UTF-8中的字节已经是1252年的两倍,因此产生了一个Base64字符串,尽管它似乎没有必要:
äöüßéèâ / w6TDtsO8w5/DqcOow6I=
第三个做的是它应该做的事情(不再是"木“,而是"?",因此木需要):
< ä ß á â & ? > / PCDDpCDDnyDDoSDDoiAmIOacqCA+
有什么线索可以帮助我的Base64吸气剂增强( a)性能b)以获得更好的结果?
提前谢谢你。:-)
发布于 2014-12-16 11:11:54
我不确定我是否完全理解这个问题。但我试过了。)如果我确实正确理解了,此代码将执行您想要的操作:
static void Main(string[] args)
{
string[] testStrings = { "DJ Doena", "äöüßéèâ", "< ä ß á â & 木 >" };
foreach (string text in testStrings)
{
Console.WriteLine(ReencodeText(text));
}
}
private static string ReencodeText(string text)
{
Encoding encoding = Encoding.GetEncoding(1252);
string text1252 = encoding.GetString(encoding.GetBytes(text));
return text.Equals(text1252, StringComparison.Ordinal) ?
text : Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
}
也就是说,它将文本编码到Windows1252,然后解码回string
对象,然后将其与原始对象进行比较。如果比较成功,则返回原始字符串,否则将其编码为UTF8,然后编码为base64。
它产生以下输出:
DJ Doena 埃莱纳 PCDDpCDDnyDDoSDDoiAmIOacqCA+
换句话说,前两个字符串保持不变,而第三个字符串被编码为base64。
发布于 2014-12-16 11:43:55
在第一段代码中,您使用一种编码方式对字符串进行编码,然后使用不同的编码方式对其进行解码。这根本不能给出任何可靠的结果;这相当于用八进制写出一个数字,然后把它读成十进制。对于7以下的数字来说,它似乎很好,但是在那之后,你得到了无用的结果。
GetBase64Alternate
方法的问题是,它将一个字符串编码成两个不同的编码,并且假设第一个编码不支持某些字符,如果第二个编码导致了不同的字节集。
比较字节序列并不能告诉您编码是否失败。如果编码失败,则序列将有所不同,但如果编码之间存在编码不同的字符,则序列也会有所不同。
您要做的是确定编码是否对所有字符都有效。您可以通过为不受支持的字符创建一个Encoding
实例来实现这一点。您可以为此使用一个EncoderExceptionFallback
类,如果调用它,它将抛出一个EncoderFallbackException
。
此代码将尝试对字符串使用Windows1252编码,如果编码不支持字符串中的所有字符,则将ok
变量设置为false
:
Encoding e = Encoding.GetEncoding(1252, new EncoderExceptionFallback(), new DecoderExceptionFallback());
bool ok = true;
try {
e.GetByteCount(allIn);
} catch (EncoderFallbackException) {
ok = false;
}
由于您实际上不会将编码的结果用于任何事情,所以可以使用GetByteCount
方法。它将检查如何在不产生编码结果的情况下对所有字符进行编码。
在您的方法中使用的方法如下:
private static String GetBase64Alternate(string text) {
Encoding e = Encoding.GetEncoding(1252, new EncoderExceptionFallback(), new DecoderExceptionFallback());
bool ok = true;
try {
e.GetByteCount(allIn);
} catch (EncoderFallbackException) {
ok = false;
}
return ok ? null : Convert.ToBase64(Encoding.UTF8.GetBytes(text));
}
https://stackoverflow.com/questions/27511937
复制