Convertire una stringa Unicode in una stringa ASCII con escape

Come posso convertire questa stringa:

This string contains the Unicode character Pi(π) 

in una stringa ASCII con escape:

 This string contains the Unicode character Pi(\u03a0) 

e viceversa ?

La codifica corrente disponibile in C # converte il carattere π in “?”. Ho bisogno di preservare quel personaggio.

Questo va avanti e indietro da e verso il formato \ uXXXX.

 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(?[a-zA-Z0-9]{4})", m => { return ((char) int.Parse( m.Groups["Value"].Value, NumberStyles.HexNumber )).ToString(); } ); } } 

Uscite:

Questa funzione contiene un carattere unicode pi (π)

Questa funzione contiene un carattere unicode pi (\ u03a0)

Questa funzione contiene un carattere unicode pi (π)

Per Unescape puoi semplicemente usare queste funzioni:

 System.Text.RegularExpressions.Regex.Unescape(string) System.Uri.UnescapeDataString(string) 

Suggerisco di usare questo metodo (funziona meglio con UTF-8):

 UnescapeDataString(string) 
 string StringFold(string input, Func 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); } 

Come un solitario:

 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(); } } 

Tutti i caratteri non ASCII vengono convertiti nella loro rappresentazione Unicode Code Point e aggiunti alla stringa finale.

Una piccola patch alla risposta di @Adam Sills che risolve FormatException nei casi in cui la stringa di input come “c: \ uababbiadirectory \ ” oltre a RegexOptions.Compiled rende la compilazione Regex molto più veloce:

  private static Regex DECODING_REGEX = new Regex(@"\\u(?[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, @"\\"); } 

Ecco la mia attuale implementazione:

 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); } } 

Questo supera un test:

 public void TestBigUnicode() { var s = "\U00020000"; var encoded = s.EncodeNonAsciiCharacters(); var decoded = encoded.DecodeEncodedNonAsciiCharacters(); Assert.Equals(s, decoded); } 

con il valore codificato: "\ud840\udc00"

Questa implementazione utilizza un StringBuilderCache (collegamento sorgente di riferimento)

È necessario utilizzare il metodo Convert() nella class Encoding :

  • Creare un object di Encoding che rappresenta la codifica ASCII
  • Creare un object di Encoding che rappresenta la codifica Unicode
  • Chiama Encoding.Convert() con la codifica sorgente, la codifica della destinazione e la stringa da codificare

C’è un esempio qui :

 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); } } } 

Per memorizzare i codepoint effettivi Unicode, è necessario prima decodificare le codeunita UTF-16 della stringa in codeunits UTF-32 (che sono attualmente uguali ai codepoint Unicode). Usa System.Text.Encoding.UTF32.GetBytes() per quello, e poi scrivi i byte risultanti sullo StringBuilder secondo necessità, cioè

 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(); }