2016-08-02 125 views
4

我想刪除它與\ XF0從字符串(ASCII碼0XF0炭)開始4個字節的UTF8字符,並試圖刪除4個字節的UTF8字符

sText = Regex.Replace (sText, "\xF0...", ""); 

這是行不通的。使用兩個反斜槓也不起作用。

確切輸入是https://de.wikipedia.org/w/index.php?title=Spezial:Exportieren&action=submit&pages=Unicode含量的4字節字符IST文本 「[[Violinschlüssel]]」 之後的一個,以十六進制表示法:.. 0x65 0x6c 0x5d 0x5d 0x20的0XF0 0x9d的0x84 0x20的0x9e ..預期輸出爲0x65 0x6c 0x5d 0x5d 0x20 0x20 ..

怎麼了?

+0

使用兩個反斜槓。 – jdweng

+1

也許是因爲您試圖刪除['ð'字符](https://ideone.com/YizDeh)。你的確切輸入和準確的預期輸出是什麼? –

+1

評論是_us_要求_你的澄清。請通過點擊[編輯](https://stackoverflow.com/posts/38714663/edit)鏈接並更新您的帖子,將您的澄清置於問題本身中。 –

回答

5

這樣的字符將是代理對在.NET,它使用UTF-16。它們中的每一個將是兩個 UTF-16代碼單元,即兩個char的值。

只刪除它們,你可以做(​​using System.Linq;):

sText = string.Concat(sText.Where(x => !char.IsSurrogate(x))); 

(使用介紹在.NET 4.0中的Concat過載(Visual Studio 2010中))。


晚此外:它可以提供更好的性能,使用:

sText = new string(sText.Where(x => !char.IsSurrogate(x)).ToArray()); 

即使它看起來更糟。 (適用於.NET 3.5(Visual Studio 2008))。

+0

這工作。非常感謝。 –

+0

據我瞭解,它將刪除所有3和4字節的UTF8字符(這是C#字符串中的2個UTF16字符值)。這不是我所要求的,但我發現這正是我真正需要的。再次感謝。 –

+0

@André你錯了。如果要刪除對應於3字節UTF-8或更長字符的字符,只需使用'sText = string.Concat(sText.Where(x => x <'\ u0800'));'。 UTF-8可以在文件中使用,但是一旦'string'在內存中,它就不會被.NET或Windows使用。如果一個字符需要UTF-8中的1,2或3個字節,它就可以放在UTF-16中的一個_code unit_(也就是單一的char值)中,這是.NET和Windows內部使用的編碼。如果一個字符需要UTF-8中的4個字節,它需要兩個UTF-16 _code units_(所以_two_'char'值)。這兩個組成了「代理對」。 –

2

您正在嘗試搜索byte值,但C#字符串是從char值中創建的。在「2.4.4.4字符文字」部分的C#語言規範指出:

字符文字代表單個字符,通常由引號中的字符組成,如'a'中。
...
十六進制轉義序列表示單個Unicode字符,其值由\x後面的十六進制數字組成。

因此,對於"\xF0..."搜索正在搜索其將由字節C3 B0被表示的字符U+F0

如果你想找到替換所有的Unicode字符的第一個字節是0xF0那麼我相信你需要搜索的字符值的第一個字節,如果0xFO。

字符U+10000表示爲F0 90 80 80(前面的代碼是U+FFFF,它是EF BF BF)。 F1 .... ..的第一個代碼是U+40000,它是F1 80 80 80,之前的值是U+3FFFF,即F0 BF BF BF

因此,您需要刪除U+10000U+3FFFF範圍內的字符。這應該是可能的,例如

sText = Regex.Replace (sText, "[\\x10000-\\x3FFFF]", ""); 

從問題引述的源有關的字符已被萃取到下面的代碼正則表達式。代碼然後試圖瞭解字符如何保存在字符串中。

static void Main(string[] args) 
{ 
    string input = "] ("; 
    Console.Write("Input length {0} : '{1}' : ", input.Length, input); 
    foreach (char cc in input) 
    { 
     Console.Write(" {0,2:X02}", (int)cc); 
    } 
    Console.WriteLine(); 
} 

該程序的輸出如下。這支持替代對 @Jeppe在他的回答中給出的解釋。

Input length 6 : '] ?? (' : 5D 20 D834 DD1E 20 28 
+0

@Qix爲什麼要修改從語言標準直接引用?引用部分沒有任何粗體文本,並且使用了字符串引號。請解釋。 – AdrianHHH

+1

因爲它更好地強調你的觀點。這不會改變規範的含義。我不得不尋找你爲什麼包含單個字符的註釋,並且必須搜索_real_答案,這是一個Unicode字符和單個字節之間的區別。 – Qix

+0

@Qix我的答案的第一句提到了C中'char'和'byte'的區別。 – AdrianHHH