c#十六进制字节0x09(ascii->;制表符)到"\";一串
我需要将文本文件的字节数组转换为它的字符串表示形式 例如,如果我有一个文本文件: 你好(tab)有(newline)朋友 我想将其转换为数组: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' 我已经尝试过了,但是这里没有显示选
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());