我被分配任务,需要生成UTF-8字符集中的所有字符来测试系统如何处理它们。我在字符编码方面没有太多经验。我打算尝试的方法是递增一个计数器,然后尝试将该十进制数转换为其对应的UTF-8字符,但迄今为止我没有找到在C# 3.5中实现这一目标的有效方法。
非常感谢任何建议。
我被分配任务,需要生成UTF-8字符集中的所有字符来测试系统如何处理它们。我在字符编码方面没有太多经验。我打算尝试的方法是递增一个计数器,然后尝试将该十进制数转换为其对应的UTF-8字符,但迄今为止我没有找到在C# 3.5中实现这一目标的有效方法。
非常感谢任何建议。
System.Net.WebClient client = new System.Net.WebClient();
string definedCodePoints = client.DownloadString(
"http://unicode.org/Public/UNIDATA/UnicodeData.txt");
System.IO.StringReader reader = new System.IO.StringReader(definedCodePoints);
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
while(true) {
string line = reader.ReadLine();
if(line == null) break;
int codePoint = Convert.ToInt32(line.Substring(0, line.IndexOf(";")), 16);
if(codePoint >= 0xD800 && codePoint <= 0xDFFF) {
//surrogate boundary; not valid codePoint, but listed in the document
} else {
string utf16 = char.ConvertFromUtf32(codePoint);
byte[] utf8 = encoder.GetBytes(utf16);
//TODO: something with the UTF-8-encoded character
}
}
以上代码应按当前分配的Unicode字符进行迭代。您可能需要在本地解析UnicodeData文件并纠正我所犯的任何C#错误。
当前分配的Unicode字符集小于可以定义的字符集。当您打印其中之一时,是否看到该字符取决于许多其他因素,如字体和它通过的其他应用程序,直到发送到您的眼球。
“UTF-8字符”这个说法并不准确。您是指Unicode字符还是Unicode字符的UTF-8编码?
将int转换为Unicode字符很容易,前提是存在该代码的映射:
char c = (char)theNumber;
byte[] encoded = Encoding.UTF8.GetBytes(c.ToString())
您需要查看Unicode标准,以了解定义Unicode字符的数字范围。
即使您生成了所有字符,您会发现这不是一种有效的测试。其中一些字符是组合标记,这意味着它们将与其后的下一个字符结合 - 拥有一串组合标记的字符串将没有太多意义。还有其他特殊情况。最好使用您需要支持的语言中的实际文本。
Encoding.GetBytes()
(在将Encoding.EncoderFallback
设置为EncoderExceptionFallback
之后)。IEnumerable<int> GetAllWritableCodepoints(Encoding encoding)
{
encoding = Encoding.GetEncoding(encoding.WebName, new EncoderExceptionFallback(), new DecoderExceptionFallback());
var i = -1;
// Docs for char.ConvertFromUtf32() say that 0x10ffff is the maximum code point value.
while (i != 0x10ffff)
{
i++;
var success = false;
try
{
encoding.GetByteCount(char.ConvertFromUtf32(i));
success = true;
}
catch (ArgumentException)
{
}
if (success)
{
yield return i;
}
}
}
这个方法应该支持在 .net 中发现由代理对表示的字符。然而,它非常缓慢(在我的机器上运行需要几分钟),可能不切实际。
UTF-8不是字符集,它是一种编码方式。任何Unicode值都可以使用不同的字节长度进行UTF-8编码。
对于.NET来说,字符是16位的(虽然不是完整的Unicode集合,但这是最实用的),因此您可以尝试以下方法:
for (char i = 0; i < 65536; i++) {
string s = "" + i;
byte[] bytes = Encoding.UTF8.GetBytes(s);
// do something with bytes
}
System.Char
是一个16位的值,没错。但是MSDN明确表示 System.Char
是一个UTF-16编码点,也就意味着它并不是严格意义上的字符。在UTF-8中有很多Unicode字符的编码点超过了65536。你说“这不是完整的Unicode集合,但它是最实用的” - 我不确定这是正确的,并且这绝对不是避免测试U+FFFF以上代码点的好理由。 - Daniel Pryden这将为您提供字符集中的所有字符 - 只需确保在指定编码时指定字符集:
var results = new ConcurrentBag<int> ();
Parallel.For (0, 10, set => {
var encoding = Encoding.GetEncoding ("ISO-8859-1");
var c = encoding.GetEncoder ();
c.Fallback = new EncoderExceptionFallback ();
var start = set * 1000;
var end = start + 1000;
Console.WriteLine ("Worker #{0}: {1} - {2}", set, start, end);
char[] input = new char[1];
byte[] output = new byte[5];
for (int i = start; i < end; i++) {
try {
input[0] = (char)i;
c.GetBytes (input, 0, 1, output, 0, true);
results.Add (i);
}
catch {
}
}
});
var hashSet = new HashSet<int> (results);
//hashSet.Remove ((int)'\r');
//hashSet.Remove ((int)'\n');
var sorted = hashSet.ToArray ();
Array.Sort (sorted);
var charset = new string (sorted.Select (i => (char)i).ToArray ());
Encoding enc = (Encoding)Encoding.GetEncoding("utf-8").Clone();
enc.EncoderFallback = new EncoderReplacementFallback("");
char[] chars = new char[1];
byte[] bytes = new byte[16];
using (StreamWriter sw = new StreamWriter(@"C:\utf-8.txt"))
{
for (int i = 0; i <= char.MaxValue; i++)
{
chars[0] = (char)i;
int count = enc.GetBytes(chars, 0, 1, bytes, 0);
if (count != 0)
{
sw.WriteLine(chars[0]);
}
}
}
正如其他人所说,UTF / Unicode 是一种编码而不是字符集。
如果您浏览http://www.joelonsoftware.com/articles/Unicode.html,它应该有助于澄清Unicode的含义。
使用PowerShell代码,我将Jake建议的代码组合成256行长度的文本文件。
服务符号会创建两个在原始文件中不存在的空行,在进行PowerShell处理之前必须从原始文本文件中删除,以便正确创建结果文件。
这里只是展示ASC2部分应该是什么样子。
NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US 空格 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ PAD HOP BPH NBH IND NEL SSA ESA HTS HTJ VTS PLD PLU RI SS2 SS3 DCS PU1 PU2 STS CCH MW SPA EPA SOS SGCI SCI CSI ST OSC PM APC 不间断空格 ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
在初始文件中,每个字符都将位于新行上。
最好使用Notepad ++查看服务符号。最好用手替换它们为文本。
还包含两个服务符号,一个在asc2部分下方,另一个在结尾处 - 很多。
但是,要欣赏彩色表情符号,您可以将喜欢的文本简单地复制到Word或社交网络中。Word比记事本更好地解释字符,但比网站差。
$arrayFromFile = [IO.File]::ReadAllLines('C:\utf-8.txt')
$counter = [pscustomobject] @{ Value = 0 }
$groupSize = 256
$text=''
$groups = $arrayFromFile | Group-Object -Property { [math]::Floor($counter.Value++ / $groupSize) }
foreach ($group in $groups){
$text+=$group.Group -join (' ')
$text+="`n"
}
$text | Out-File -FilePath 'C:\utf-8 (sorted).txt'