Как создать все символы в кодировке UTF-8 в .net
Мне была поручена генерация всех символов в наборе символов UTF-8, чтобы проверить, как система обрабатывает каждый из них. У меня нет большого опыта кодирования символов. Подход, который я собирался попробовать, заключался в том, чтобы увеличить счетчик, а затем попытаться перевести это базовое десять чисел в эквивалентный символ UTF-8, но до сих пор мне не удалось найти эффективный путь к этому в С# 3.5
Приветствуются любые предложения.
Ответы
Ответ 1
Нет символов "UTF-8". Вы имеете в виду символы Unicode или кодировку UTF-8 символов Unicode?
Легко преобразовать int в символ Юникода, конечно, если есть сопоставление для этого кода:
char c = (char)theNumber;
Если вам нужна кодировка UTF-8 для этого символа, это тоже не очень сложно:
byte[] encoded = Encoding.UTF8.GetBytes(c.ToString())
Вам нужно будет проверить стандарт Unicode, чтобы увидеть диапазоны номеров, где указаны символы Unicode.
Ответ 2
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
}
}
Вышеприведенный код должен перебирать символы, присвоенные в настоящее время Юникодом. Вероятно, вы захотите проанализировать файл UnicodeData локально и исправить любые ошибки С#, которые я сделал.
Набор присвоенных в настоящее время символов Unicode меньше установленного набора. Конечно, независимо от того, видите ли вы персонаж, когда вы печатаете один из них, зависит от множества других факторов, таких как шрифты и другие приложения, которые он пропустит, прежде чем он будет выпущен на ваше глазное яблоко.
Ответ 3
Даже после того, как вы сгенерируете все символы, вы обнаружите, что это не эффективный тест. Некоторые из символов объединяют метки, а это означает, что они будут сочетаться со следующим персонажем, который должен последовать за ними - наличие последовательности, заполненной комбинацией меток, не имеет большого смысла. Есть и другие особые случаи. Вам будет гораздо лучше использовать фактический текст на языках, которые вам нужны для поддержки.
Ответ 4
UTF-8 не является набором символов - это кодировка символов, которая способна кодировать любой символ в наборе символов Юникода в двоичные данные.
Не могли бы вы дать больше информации о том, что вы пытаетесь сделать? Вы можете кодировать все возможные символы Юникода (включая те, которые не выделены в данный момент), хотя, если вам нужно справиться с символами вне базовой многоязычной плоскости (то есть выше U + FFFF), тогда она становится немного сложнее...
Ответ 5
UTF-8 не является кодировкой, это кодировка.
Любое значение в Юникоде может быть закодировано в UTF-8 с разными байтами.
Для .net символы 16-бит (это не полный набор юникодов, но наиболее практичный), поэтому вы можете попробовать следующее:
for (char i = 0; i < 65536; i++) {
string s = "" + i;
byte[] bytes = Encoding.UTF8.GetBytes(s);
// do something with bytes
}
Ответ 6
Это даст вам все символы в кодировке - просто убедитесь, что вы указываете кодировку при указании кодировки:
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 ());
Ответ 7
Как говорили другие люди, UTF/Unicode - это кодировка, а не набор символов.
Если вы не используете http://www.joelonsoftware.com/articles/Unicode.html, это должно помочь прояснить, что такое unicode.
Ответ 8
Этот код выдаст результат в файле. Все символы, печатаемые или нет, будут там.
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]);
}
}
}
Ответ 9
Вы можете перетащить Encoding
, чтобы определить, какой код он поддерживает. Для этого просто пройдите все возможные кодовые точки, преобразуйте их в строки и посмотрите, если 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;
}
}
}
Этот метод должен поддерживать обнаружение символов, представленных суррогатными парами Char
в .net. Тем не менее, он очень медленный (требуется несколько минут для запуска на моей машине) и, вероятно, непрактично.