看一下如何输出单字节字符集中可打印的所有字符。输出文件将包含日语字符,例如チホヤツセ。
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个字符。每个字节都单独计算,并分别为该字节返回字符。输出字符串始终包含两个字符而不是一个字符。由于字符集中的字符用两个字节表示,您必须用两个字节指定它们吗?
那么如何迭代并打印双字节字符集中的所有字符?
答案 0 :(得分:1)
如果可以以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);
}
答案 1 :(得分: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());
}
}
}
答案 2 :(得分:0)
这是您选择的特定编码的问题。
ISO-2022编码不能单独列出数字 - 这不是Unicode。特定字节集的含义由字节流中的转义序列决定。
来自维基百科的文章(ISO / IEC 2022):
为表示多个字符集,ISO / IEC 2022字符编码包括转义序列,表示后面字符的字符集。