c#十六进制字节0x09(ascii->;制表符)到"\";一串

c#十六进制字节0x09(ascii->;制表符)到"\";一串,c#,character-encoding,C#,Character Encoding,我需要将文本文件的字节数组转换为它的字符串表示形式 例如,如果我有一个文本文件: 你好(tab)有(newline)朋友 我想将其转换为数组: my_array = {'h', 'e' ,'l','l','o', '\t', 't', 'h','e','r','e', '\r','\n', 'f', 'r' ,'i','e','n', 'd'}; 我在将控制字符转换为转义字符串时遇到问题,即: 0x09='\t' 0x0D='\r' 0x0A='\n' 我已经尝试过了,但是这里没有显示选

我需要将文本文件的字节数组转换为它的字符串表示形式

例如,如果我有一个文本文件:

你好(tab)有(newline)朋友

我想将其转换为数组:

my_array  = {'h', 'e' ,'l','l','o', '\t', 't', 'h','e','r','e', '\r','\n', 'f', 'r' ,'i','e','n', 'd'};
我在将控制字符转换为转义字符串时遇到问题,即:

  • 0x09='\t'
  • 0x0D='\r'
  • 0x0A='\n'
我已经尝试过了,但是这里没有显示选项卡和新行:

byte[] text_bytes = File.ReadAllBytes("ok.txt");
char[] y = Encoding.ASCII.GetChars(text_bytes);

我知道我可以循环遍历每个字节,并有一个条件来查找
0x09
,如果找到它,然后替换为
“\t”
,但我想知道是否有内置的内容

如果您不介意它比手摇解决方案慢一些,那么您可以使用
CodeDomProvider
(可能足够快)

我在这里找到了示例代码:

您可以通过使用
Encoding.Ascii.ReadString()
读取字符串来使用它,然后使用
.ToLiteral()
将其转换为字符串,然后使用
.tocharray()
获得最终结果

这将给出正确的结果,例如:

// You would do (using your sample code):
// string test = Encoding.ASCII.GetString(text_bytes);

string test = "hello\tthere\nfriend";

char[] result = test.ToLiteral().ToCharArray();
如果检查
结果
,您将看到它具有正确的字符


但是,我只使用一个循环和一个switch语句来转换字符。它易于编写和理解,而且效率更高。

如果要转义所有控制字符,则可以使用Regex.escape

string myText = File.ReadAllLines("ok.txt");

//to optimize, you could remove characters that you know won't be there (e.g. \a)
Regex rx = new Regex(@"[\a\e\f\n\r\t\v]", RegexOptions.Compiled); 

myText = rx.Replace(myText, m =>  { return Regex.Escape(m.Value); });

Console.WriteLine(myText);
您无法按发布的方式将其转换为
char
数组,因为转义的控制字符将计为两个字符(
\
t
)。但是如果你不介意每个角色是分开的,你可以简单地做

char[] myCharArray = myText.ToCharArray();
在“y”数组中,“转义字符”的实际值(0x09、0x0D等)将以不可打印字符作为“文本”

当您写入\t、\n、\r等时,您可能已经写入了(char)0x09、(char)0x0D,这就是数据写入的方式。换句话说,“\t”字符不存在


无论您是使用自己的库,还是使用现有库,都必须有人将0x09映射到“\t”转义序列,并将其注入字符串中。

有几种方法可以做到这一点。最简单的方法是将整个文件加载到内存中:

string theText = File.ReadAllText(filename);
然后使用
string.Replace
替换您感兴趣的项目:

// "escaping" the '\t' with '\\t' makes it write the literal characters '\' and 't'
theText = theText.Replace("\t", "\\t");

theText = theText.Replace("\r", "\\r");
theText = theText.Replace("\n", "\\n");
然后可以创建字符数组。如果您确定它都是ASCII文本,则可以使用
编码.ASCII

byte[] theChars = Encoding.ASCII.GetBytes(theText);
或者,如果需要字符数组:

char[] theChars = theText.ToCharArray();
就你的目的而言,这可能足够快了。通过对字符串进行单次遍历、逐个字符读取并复制到
StringBuilder
,您可能可以加快速度:

StringBuilder sb = new StringBuilder(theText.Length);
foreach (char c in theText)
{
    switch (c)
    {
        case '\t' : sb.Append("\\t"); break;
        case '\r' : sb.Append("\\r"); break;
        case '\n' : sb.Append("\\n"); break;
        default : sb.Append(c); break;
    }
}

byte[] theChars = Encoding.ASCII.GetBytes(sb.ToString());

他们逃出来的绳子?字符“\t”的转义字符串看起来像“\\t”。如果仅将其替换为“\t”,则表示未替换任何内容。实际上,您正试图将
0x09
替换为两个字符“\”和“t”。只是想帮你想想而已。@D.R.它很有效;我试过了。你认为什么时候不合适?我取消了否决票,因为它有效,你是对的。我仍然认为这项任务可以用更少的努力来解决,也就是说,我认为你在用雪橇敲碎坚果hammer@D.R.我同意-我只需要使用循环和switch语句来转换字符。然而,OP说,
我知道我可以循环遍历每个字节,并有一个条件来查找0x09,如果我找到它,然后用“\t”替换,但我想知道是否有内置的东西,这就是我要回答的问题。但是
Regex.Escape
也会变成“\”,它将转义所有特殊的正则表达式字符。更新后,它只转义普通的不可打印字符。我怀疑它是否会像循环字符串方法一样有效,如果它是连续执行的,但这只是OP不想迭代字符串的一个例子。在这种情况下,编译正则表达式会显著加快它的速度(如果删除
\a\e\f\v
,则更是如此)。如果要经常调用此正则表达式,则似乎值得编译。我认为您可以将正则表达式编写为
“[\a\e\f\n\r\t\v]”
,而不使用替换字符。我不知道这些交替角色在角色组中做什么。似乎这会导致“|”字符被转义。这是我的第一个想法,我想我试过了,但没有成功。事实证明我错了,你是对的,因为它可以像那样使用。
StringBuilder sb = new StringBuilder(theText.Length);
foreach (char c in theText)
{
    switch (c)
    {
        case '\t' : sb.Append("\\t"); break;
        case '\r' : sb.Append("\\r"); break;
        case '\n' : sb.Append("\\n"); break;
        default : sb.Append(c); break;
    }
}

byte[] theChars = Encoding.ASCII.GetBytes(sb.ToString());