如何从双字节字符集打印字符

本文关键字:字符集 打印 字符 字节 | 更新日期: 2023-09-27 18:07:27

看看如何从单个字节字符集输出可打印或不可打印的所有字符。输出文件将包含日语字符,如。

Encoding enc = Encoding.GetEncoding("shift_jis");
byte[] m_bytes = new  byte [1];
StreamWriter sw = new StreamWriter(@"C:'shift_jis.txt");
for (int i = 0; i < 256; i++)
{
    m_bytes.SetValue ((byte)i,0);
    String Output = enc.GetString(m_bytes);
    sw.WriteLine(Output);
}
sw.Close();
sw.Dispose();

这是我尝试用双字节字符集来做到这一点。

Encoding enc = Encoding.GetEncoding("iso-2022-jp");
byte[] m_bytes = new byte[2];
StreamWriter sw = new StreamWriter(@"C:'iso-2022-jp.txt");
for (int i = 0; i < 256; i++)
{
    m_bytes.SetValue((byte)i, 0);
    for (int j = 0; j < 256; j++)
    {
        m_bytes.SetValue((byte)j, 1);
        String Output = null;
        Output = enc.GetString(m_bytes);
        sw.WriteLine(Output);
    }
}
sw.Close();
sw.Dispose();

问题是输出文件仍然只包含前255个字符。每个字节分别求值,并分别返回该字节对应的字符。输出字符串总是包含两个字符而不是一个。由于字符集中的字符是用两个字节表示的,所以必须用两个字节来指定它们,对吗?

那么如何遍历并打印双字节字符集中的所有字符呢?

如何从双字节字符集打印字符

如果可以按unicode顺序排列,则可以:

Encoding enc = (Encoding)Encoding.GetEncoding("iso-2022-jp").Clone();
enc.EncoderFallback = new EncoderReplacementFallback("");
char[] chars = new char[1];
byte[] bytes = new byte[16];
using (StreamWriter sw = new StreamWriter(@"C:'temp'iso-2022-jp.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]);
        }
    }
}

如果你想按字节顺序排序,你可以:

Encoding enc = (Encoding)Encoding.GetEncoding("iso-2022-jp").Clone();
enc.EncoderFallback = new EncoderReplacementFallback("");
char[] chars = new char[1];
byte[] bytes = new byte[16];
var lst = new List<Tuple<byte[], char>>();
for (int i = 0; i <= char.MaxValue; i++)
{
    chars[0] = (char)i;
    int count = enc.GetBytes(chars, 0, 1, bytes, 0);
    if (count != 0)
    {
        var bytes2 = new byte[count];
        Array.Copy(bytes, bytes2, count);
        lst.Add(Tuple.Create(bytes2, chars[0]));
    }
}
lst.Sort((x, y) =>
{
    int min = Math.Min(x.Item1.Length, y.Item1.Length);
    for (int i = 0; i < min; i++)
    {
        int cmp = x.Item1[i].CompareTo(y.Item1[i]);
        if (cmp != 0)
        {
            return cmp;
        }
    }
    return x.Item1.Length.CompareTo(y.Item1.Length);
});
using (StreamWriter sw = new StreamWriter(@"C:'temp'iso-2022-jp.txt"))
{
    foreach (var tuple in lst)
    {
        sw.WriteLine(tuple.Item2);
        // This will print the full byte sequence necessary to 
        // generate the char. Note that iso-2022-jp uses escape
        // sequences to "activate" subtables and to deactivate them.
        //sw.WriteLine("{0}: {1}", tuple.Item2, string.Join(",", tuple.Item1.Select(x => x.ToString("x2"))));
    }
}

或以不同的排序顺序(长度优先):

lst.Sort((x, y) =>
{
    int cmp2 = x.Item1.Length.CompareTo(y.Item1.Length);
    if (cmp2 != 0)
    {
        return cmp2;
    }
    int min = Math.Min(x.Item1.Length, y.Item1.Length);
    for (int i = 0; i < min; i++)
    {
        int cmp = x.Item1[i].CompareTo(y.Item1[i]);
        if (cmp != 0)
        {
            return cmp;
        }
    }
    return 0;
});

请注意,在所有示例中,我只生成基本BMP平面的字符。我不认为基本BMP平面之外的字符包含在任何编码中…如果有必要,我可以修改代码来支持它。

出于好奇,第一个处理非bmp字符(iso-2022-jp中不存在)的代码版本:

Encoding enc = (Encoding)Encoding.GetEncoding("iso-2022-jp").Clone();
enc.EncoderFallback = new EncoderReplacementFallback("");
byte[] bytes = new byte[16];
using (StreamWriter sw = new StreamWriter(@"C:'temp'iso-2022-jp.txt"))
{
    int max = -1;
    for (int i = 0; i <= 0x10FFFF; i++)
    {
        if (i >= 0xD800 && i <= 0xDFFF)
        {
            continue;
        }
        string chars = char.ConvertFromUtf32(i);
        int count = enc.GetBytes(chars, 0, chars.Length, bytes, 0);
        if (count != 0)
        {
            sw.WriteLine(chars);
            max = i;
        }
    }
    Console.WriteLine("maximum codepoint: {0}", max);
}

您应该使用为您的编码配置的写入器:

Encoding encoding = Encoding.GetEncoding("iso-2022-jp");
using (var stream = new FileStream(@"C:'iso-2022-jp.txt", FileMode.Create))
{
    using (StreamWriter writer = new StreamWriter(stream, encoding))
    {
        for (int i = 0; i <= char.MaxValue; i++)
        {
            // Each char goes separate line. One will be only 1 byte, others more with
            // the leading escape seq:
            writer.WriteLine(((char) i).ToString());
        }
    }
}

这是您选择的特定编码的问题。

ISO-2022编码不能只是逐个数字单独列出-这不是Unicode。一组特定字节的含义由字节流中的转义序列决定。

来自维基百科文章(ISO/IEC 2022):

为了表示多个字符集,ISO/IEC 2022字符编码包括转义序列,该转义序列表示后面字符的字符集。