Как создать все символы в кодировке 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. Тем не менее, он очень медленный (требуется несколько минут для запуска на моей машине) и, вероятно, непрактично.