如何使用多个ASCII字符来表示特殊字符?

问题描述 投票:0回答:1

我想用ASCII字符表示特殊字符,如CR, LF, NULL等。

基本上,我想写一个包含这些特殊字符的字符串变量到ASCII日志文本文件中,这样我就可以从这个文件中复制文本,然后粘贴到visual studio中,以接收同样的字符串变量。

我想最好的方法是用visual studio代码编辑器使用的格式来写特殊字符。(请赐教字符串格式是如何调用的)。

示例代码。

string mystring = "\r\n\0\0\u0001\u0018\0\0\u0001\u000fXML";
Console.WriteLine(mystring);

所以我想把... mystring 以致于 Console.WriteLine 将输出 \r\n\0\0\u0001\u0018\0\0\u0001\u000fXML 而不是。console output

Console只是一个简单的方法来描述这个问题. 我将以不同的方式打印我的字符串,所以我需要将 mystring 转换为一个字符串,以打印 \r\n\0\0\u0001\u0018\0\0\u0001\u000fXML (和所有其他特殊字符以同样的方式)。

c# parsing ascii special-characters data-representation
1个回答
1
投票

这些字符被称为 逃逸序列. 你可以咨询 文法 来查看字符串文字中哪些字符需要转义。 基本上你可以用Unicode字符转义序列转义任何字符。

\u hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit

例如:将U+000D改为 \u000d 为回车字符。

如果你想保持字符串简短,那么有一些 不要 需要逃离。 那些... 需要逃逸的是。

  • " (U+0022)
  • \ (U+005C)
  • 回车字符(U+000D)
  • 换行字符(U+000A)
  • 下一行字符(U+0085)
  • 分行符(U+2028)
  • 段落分隔符(U+2029)

其他的都可以按字面意思插入。

如果你只想对你的源文件进行ASCII编码,那么你可以对哪些字符进行更严格的限制。 你可能会想要非常严格的限制。

给自己做一个函数来决定一个字符是否应该被转义。 你可能想从这样的函数开始。

public static bool IsSafeForLiteral(char ch) =>
    ch < 127
    && ch != '\u0022' // double quote
    && ch != '\u005c' // backslash
    && ch != '\u000d' // carriage return
    && ch != '\u000a' // line feed
    && (
        Char.IsLetterOrDigit(ch)
        || Char.IsPunctuation(ch)
        || Char.IsSymbol(ch)
        || (ch == ' ')
    );

然后用这个测试来构造一个函数 把一个字符串变成C#源代码的字符串文字。

public static string ToSourceStringLiteral(string str)
{
    StringBuilder sb = new StringBuilder();
    sb.Append("\"");
    foreach (char c in str) {
        if (IsSafeForLiteral(c)) {
            sb.Append(c);
        } else {
            sb.AppendFormat(@"\u{0:X4}", (int)c);
        }
    }
    sb.Append("\"");
    return sb.ToString();
}

如果你真的很喜欢回车的想法,那么你就可以把它当作 \r 而不是 \u000d 那么你就必须进一步对所有这些转义序列进行编程。

一种方法是制作一个替换字符的字典,并应用它。

public static Dictionary<char, string> CSharpSpecialEscapes = new Dictionary<char, string>() {
    { '\u0000', @"\0" },
    { '\u0007', @"\a" },
    { '\u0008', @"\b" },
    { '\u0009', @"\t" },
    { '\u000a', @"\n" },
    { '\u000b', @"\v" },
    { '\u000c', @"\f" },
    { '\u000d', @"\r" },
    { '\u001b', @"\e" },
    { '\u005c', @"\\" }
};

public static string ToSourceStringLiteral(this string str)
{
    StringBuilder sb = new StringBuilder();
    sb.Append("\"");
    foreach (char c in str) {
        if (CSharpSpecialEscapes.TryGetValue(c, out string replacement)) {
            sb.Append(replacement);
        } else if (IsSafeForLiteral(c)) {
            sb.Append(c);
        } else {
            sb.AppendFormat(@"\u{0:X4}", (int)c);
        }
    }
    sb.Append("\"");
    return sb.ToString();
}

根据性能要求,你也可以用0...127范围内的所有替换字符预先填充一个数组,然后使用这个数组,尽管这时源码开始看起来不那么可维护了。 我推荐我上面写的东西,因为它是描述性的(与字符串转义序列的定义方式很匹配,而不是最佳效率)。

我还让这个版本在开头和结尾添加了引号。 你可以很容易地删除那些说 sb.Append("\""); 如果你不想要它们。


0
投票

您可以在引号前使用"@"符号。

string mystring = @"\r\n\0\0\u0001\u0018\0\0\u0001\u000fXML";

这可以防止用反斜杠转义 \

编辑。

或者直接用双反斜杠来逃避反斜杠本身。

string mystring = "\\r\\n\\0\\0\\u0001\\u0018\\0\\0\\u0001\\u000fXML";
© www.soinside.com 2019 - 2024. All rights reserved.