将Unicodestring转换为转义的ASCIIstring
我怎样才能转换这个string:
This string contains the Unicode character Pi(π)
转换成一个转义的ASCIIstring:
This string contains the Unicode character Pi(\u03a0)
反之亦然 ?
在C#中可用的当前编码将π字符转换为“?”。 我需要保留这个angular色。
这个往返于\ xXXX格式。
class Program { static void Main( string[] args ) { string unicodeString = "This function contains a unicode character pi (\u03a0)"; Console.WriteLine( unicodeString ); string encoded = EncodeNonAsciiCharacters(unicodeString); Console.WriteLine( encoded ); string decoded = DecodeEncodedNonAsciiCharacters( encoded ); Console.WriteLine( decoded ); } static string EncodeNonAsciiCharacters( string value ) { StringBuilder sb = new StringBuilder(); foreach( char c in value ) { if( c > 127 ) { // This character is too big for ASCII string encodedValue = "\\u" + ((int) c).ToString( "x4" ); sb.Append( encodedValue ); } else { sb.Append( c ); } } return sb.ToString(); } static string DecodeEncodedNonAsciiCharacters( string value ) { return Regex.Replace( value, @"\\u(?<Value>[a-zA-Z0-9]{4})", m => { return ((char) int.Parse( m.Groups["Value"].Value, NumberStyles.HexNumber )).ToString(); } ); } }
输出:
这个函数包含一个unicode字符pi(π)
这个函数包含一个Unicode字符pi(\ u03a0)
这个函数包含一个unicode字符pi(π)
string StringFold(string input, Func<char, string> proc) { return string.Concat(input.Select(proc).ToArray()); } string FoldProc(char input) { if (input >= 128) { return string.Format(@"\u{0:x4}", (int)input); } return input.ToString(); } string EscapeToAscii(string input) { return StringFold(input, FoldProc); }
对于Unescape你可以简单地使用这个function:
System.Text.RegularExpressions.Regex.Unescape(string) System.Uri.UnescapeDataString(string)
我build议使用这种方法(使用UTF-8更好):
UnescapeDataString(string)
作为一个单行:
var result = Regex.Replace(input, @"[^\x00-\x7F]", c => string.Format(@"\u{0:x4}", (int)c.Value[0]));
class Program { static void Main(string[] args) { char[] originalString = "This string contains the unicode character Pi(π)".ToCharArray(); StringBuilder asAscii = new StringBuilder(); // store final ascii string and Unicode points foreach (char c in originalString) { // test if char is ascii, otherwise convert to Unicode Code Point int cint = Convert.ToInt32(c); if (cint <= 127 && cint >= 0) asAscii.Append(c); else asAscii.Append(String.Format("\\u{0:x4} ", cint).Trim()); } Console.WriteLine("Final string: {0}", asAscii); Console.ReadKey(); } }
所有非ASCII字符都被转换为Unicode代码点表示并附加到最终的string。
@Adam Sills的答案的一个小补丁,解决了类似于“c:\ u00ab \ otherdirectory \ ”和RegexOptions.Compiled
这样的inputstring使得正则Regex
编译快得多的情况下的FormatException
:
private static Regex DECODING_REGEX = new Regex(@"\\u(?<Value>[a-fA-F0-9]{4})", RegexOptions.Compiled); private const string PLACEHOLDER = @"#!#"; public static string DecodeEncodedNonAsciiCharacters(this string value) { return DECODING_REGEX.Replace( value.Replace(@"\\", PLACEHOLDER), m => { return ((char)int.Parse(m.Groups["Value"].Value, NumberStyles.HexNumber)).ToString(); }) .Replace(PLACEHOLDER, @"\\"); }
这是我目前的实现:
public static class UnicodeStringExtensions { public static string EncodeNonAsciiCharacters(this string value) { var bytes = Encoding.Unicode.GetBytes(value); var sb = StringBuilderCache.Acquire(value.Length); bool encodedsomething = false; for (int i = 0; i < bytes.Length; i += 2) { var c = BitConverter.ToUInt16(bytes, i); if ((c >= 0x20 && c <= 0x7f) || c == 0x0A || c == 0x0D) { sb.Append((char) c); } else { sb.Append($"\\u{c:x4}"); encodedsomething = true; } } if (!encodedsomething) { StringBuilderCache.Release(sb); return value; } return StringBuilderCache.GetStringAndRelease(sb); } public static string DecodeEncodedNonAsciiCharacters(this string value) => Regex.Replace(value,/*language=regexp*/@"(?:\\u[a-fA-F0-9]{4})+", Decode); static readonly string[] Splitsequence = new [] { "\\u" }; private static string Decode(Match m) { var bytes = m.Value.Split(Splitsequence, StringSplitOptions.RemoveEmptyEntries) .Select(s => ushort.Parse(s, NumberStyles.HexNumber)).SelectMany(BitConverter.GetBytes).ToArray(); return Encoding.Unicode.GetString(bytes); } }
这通过了一个testing:
public void TestBigUnicode() { var s = "\U00020000"; var encoded = s.EncodeNonAsciiCharacters(); var decoded = encoded.DecodeEncodedNonAsciiCharacters(); Assert.Equals(s, decoded); }
与编码值: "\ud840\udc00"
这个实现使用了一个StringBuilderCache (参考源链接)
您需要在Encoding
类中使用Convert()
方法:
- 创build一个表示ASCII编码的
Encoding
对象 - 创build一个表示Unicode编码的
Encoding
对象 - 使用源编码,目标编码和要编码的string调用
Encoding.Convert()
这里有一个例子:
using System; using System.Text; namespace ConvertExample { class ConvertExampleClass { static void Main() { string unicodeString = "This string contains the unicode character Pi(\u03a0)"; // Create two different encodings. Encoding ascii = Encoding.ASCII; Encoding unicode = Encoding.Unicode; // Convert the string into a byte[]. byte[] unicodeBytes = unicode.GetBytes(unicodeString); // Perform the conversion from one encoding to the other. byte[] asciiBytes = Encoding.Convert(unicode, ascii, unicodeBytes); // Convert the new byte[] into a char[] and then into a string. // This is a slightly different approach to converting to illustrate // the use of GetCharCount/GetChars. char[] asciiChars = new char[ascii.GetCharCount(asciiBytes, 0, asciiBytes.Length)]; ascii.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0); string asciiString = new string(asciiChars); // Display the strings created before and after the conversion. Console.WriteLine("Original string: {0}", unicodeString); Console.WriteLine("Ascii converted string: {0}", asciiString); } } }
要存储实际的Unicode代码点,您必须首先将string的UTF-16代码单元解码为UTF-32代码单元(目前与Unicode代码点相同)。 为此,使用System.Text.Encoding.UTF32.GetBytes()
,然后根据需要将结果字节写入StringBuilder
,即
static void Main(string[] args) { String originalString = "This string contains the unicode character Pi(π)"; Byte[] bytes = Encoding.UTF32.GetBytes(originalString); StringBuilder asAscii = new StringBuilder(); for (int idx = 0; idx < bytes.Length; idx += 4) { uint codepoint = BitConverter.ToUInt32(bytes, idx); if (codepoint <= 127) asAscii.Append(Convert.ToChar(codepoint)); else asAscii.AppendFormat("\\u{0:x4}", codepoint); } Console.WriteLine("Final string: {0}", asAscii); Console.ReadKey(); }