3

単一バイト文字セットからすべての文字を印刷可能または不可能に出力する方法を見てみましょう。出力ファイルには、チホヤツセなどの日本語の文字が含まれます。

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();

これは、2バイト文字セットでこれを行う私の試みです。

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 文字しか含まれていないことです。各バイトは個別に評価され、そのバイトの文字が個別に返されます。出力文字列には、常に 1 文字ではなく 2 文字が含まれます。文字セットの文字は 2 バイトで表されるので、2 バイトで指定する必要がありますよね?

では、2 バイト文字セットのすべての文字を反復して出力するにはどうすればよいでしょうか。

4

3 に答える 3

1

エンコーディングに設定されたライターを使用する必要があります。

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());
        }
    }
}
于 2015-08-12T15:30:59.553 に答える
1

それらをユニコードの順序で並べても問題ない場合は、次のことができます。

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);
}
于 2015-08-12T15:16:20.267 に答える