如何(使用C#)输出unicode字符串为RTF(How to output unicode str

2019-06-21 11:11发布

我试图输出Unicode字符串转换为RTF格式。 (使用C#和WinForms)

维基百科 :

如果需要Unicode转义,控制字\使用U,接着是16位有符号十进制整数给出的Unicode代码点数量。 对于不支持Unicode的程序利益,这必须跟这个角色在指定的代码页的最近表示。 例如,\ u1576? 将给阿拉伯字母BEH,指定不具备Unicode支持旧程序应该呈现为一个问号代替。

我不知道如何Unicode字符转换成Unicode码点(“\ u1576”)。 转换为UTF-8,UTF-16和类似的很容易,但我不知道如何转换为代码点。

场景中,我用这个:

  • 我读现有的RTF文件转换成字符串(我读模板)
  • #与string.replace TOKEN#与MyUnicodeString(模板是用数据填充)
  • 结果写入到另一个RTF文件。

问题出现时,Unicode字符到达

Answer 1:

假如所有的,你迎合中存在的人物基本多文种平面 (这是不可能的,你需要什么了),那么一个简单的UTF-16编码就足够了。

维基百科:

从U + 0000的所有可能的码点通过U + 10FFFF,除了替代代码点U + D800-U + DFFF(不是字符),唯一地由UTF-16映射无论代码点的当前或将来的字符分配的或使用。

下面的示例程序说明做沿着你想要什么东西行:

static void Main(string[] args)
{
    // ë
    char[] ca = Encoding.Unicode.GetChars(new byte[] { 0xeb, 0x00 });
    var sw = new StreamWriter(@"c:/helloworld.rtf");
    sw.WriteLine(@"{\rtf
{\fonttbl {\f0 Times New Roman;}}
\f0\fs60 H" + GetRtfUnicodeEscapedString(new String(ca)) + @"llo, World!
}"); 
    sw.Close();
}

static string GetRtfUnicodeEscapedString(string s)
{
    var sb = new StringBuilder();
    foreach (var c in s)
    {
        if (c <= 0x7f)
            sb.Append(c);
        else
            sb.Append("\\u" + Convert.ToUInt32(c) + "?");
    }
    return sb.ToString();
}

最重要的一点是Convert.ToUInt32(c)基本上返回有问题的字符的代码点值。 对Unicode的RTF逃逸要求为十进制Unicode值。 所述System.Text.Encoding.Unicode编码对应于UTF-16作为每MSDN文档。



Answer 2:

从接受的答案固定码-添加特殊字符转义,如在此描述的链接

static string GetRtfUnicodeEscapedString(string s)
{
    var sb = new StringBuilder();
    foreach (var c in s)
    {
        if(c == '\\' || c == '{' || c == '}')
            sb.Append(@"\" + c);
        else if (c <= 0x7f)
            sb.Append(c);
        else
            sb.Append("\\u" + Convert.ToUInt32(c) + "?");
    }
    return sb.ToString();
}


Answer 3:

你必须将字符串转换为byte[]数组(使用Encoding.Unicode.GetBytes(string) ),然后通过数组循环,并在前面加上一个\u字符你发现所有Unicode字符。 当你那么数组转换回字符串,你必须离开Unicode字符为数字。

例如,如果你的阵列是这样的:

byte[] unicodeData = new byte[] { 0x15, 0x76 };

它会成为:

// 5c = \, 75 = u
byte[] unicodeData = new byte[] { 0x5c, 0x75, 0x15, 0x76 };


Answer 4:

根据规范,以下是一些Java中的代码被测试和工程:

  public static String escape(String s){
        if (s == null) return s;

        int len = s.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++){
            char c = s.charAt(i);
            if (c >= 0x20 && c < 0x80){
                if (c == '\\' || c == '{' || c == '}'){
                    sb.append('\\');
                }
                sb.append(c);
            }
            else if (c < 0x20 || (c >= 0x80 && c <= 0xFF)){
                sb.append("\'");
                sb.append(Integer.toHexString(c));
            }else{
                sb.append("\\u");
                sb.append((short)c);
                sb.append("??");//two bytes ignored
            }
        }
        return sb.toString();
 }

重要的是,你需要逃出后UNCODE 2个字符(接近Unicode字符或只是使用?代替)追加。 ,因为Unicode占用2个字节。

另外,规范说您应该使用负值,如果代码点大于32767,但在我的测试中,如果你不使用负值它的罚款。

这里是规格:

\ UN此关键字表示具有根据当前ANSI代码页上没有等效ANSI表示一个单一的Unicode字符。 N代表表示为十进制数的Unicode字符值。 该关键字是由ANSI表示等效字符(多个)紧跟。 这样一来,老读者会忽略\联合国关键字并妥善拿起ANSI表示。 当遇到这个关键字,读者应该忽略接下来的N个字符,其中N对应于遇到的最后一个\ UCN值。

如同所有的RTF关键字,关键字终止空间可以存在(在ANSI字符之前),其未在字符计数跳过。 虽然这是不太可能发生(或推荐),一个\ bin中的关键字,它的参数,并且随后的二进制数据被认为是一个字符用于跳过目的。 如果RTF范围分界符(即,打开或关闭括号),同时扫描可跳过数据中遇到,可跳过的数据被认为是定界符之前结束。 这使得对读者进行一些基本的错误恢复。 以包括在可跳过数据的RTF定界符,则必须使用适当的控制符号来表示(即,以反斜杠转义,),如纯文本。 任何RTF控制字或符号被认为是用于计数可跳过字符的目的,单个字符。

一个RTF编辑器,当遇到没有相应的ANSI字符Unicode字符,应该输出\联合国其次是最好的ANSI表示它可以管理。 此外,如果Unicode字符转换成与从当前Unicode字符字节计数不同的字节计数一个ANSI字符流,它应该发射之前\联合国关键字\ UCN关键字通知变化的读取器。

RTF控制字通常作为参数接受带符号的16位数字。 出于这个原因,Unicode值大于32767必须表示为负数



文章来源: How to output unicode string to RTF (using C#)