Converter uma string Unicode em uma string ASCII com escape

Como posso converter essa string:

This string contains the Unicode character Pi(π) 

em uma string ASCII com escape:

 This string contains the Unicode character Pi(\u03a0) 

e vice-versa ?

A codificação atual disponível em c # converte o caractere π para “?”. Eu preciso preservar esse personagem.

Isso vai e volta do / para o 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(); } ); } } 

Saídas:

Esta function contém um caractere unicode pi (π)

Esta function contém um caractere unicode pi (\ u03a0)

Esta function contém um caractere unicode pi (π)

Para Unescape Você pode simplesmente usar estas funções:

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

Eu sugiro usar este método (funciona melhor com 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); } 

Como um one-liner:

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

Todos os caracteres não-ASCII são convertidos para sua representação em Unicode Code Point e anexados à string final.

Um pequeno patch para a resposta de @Adam Sills que resolve FormatException nos casos em que a string de input como “c: \ u00ab \ otherdirectory \ ” mais RegexOptions.Compiled torna a compilation Regex muito mais rápida:

  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, @"\\"); } 

Aqui está minha implementação atual:

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

Isso passa um teste:

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

com o valor codificado: "\ud840\udc00"

Esta implementação faz uso de um StringBuilderCache (link de origem de referência)

Você precisa usar o método Convert() na class Encoding :

  • Criar um object de Encoding que representa a codificação ASCII
  • Criar um object de Encoding que representa a codificação Unicode
  • Chame Encoding.Convert() com a codificação de origem, a codificação de destino e a cadeia a ser codificada

Há um exemplo aqui :

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

Para armazenar pontos de código Unicode reais, primeiro é necessário decodificar as unidades de código UTF-16 da String para as unidades de código UTF-32 (que são atualmente as mesmas que as codepoints Unicode). Use System.Text.Encoding.UTF32.GetBytes() para isso e, em seguida, gravar os bytes resultantes para o StringBuilder conforme necessário, ou seja,

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