2013-08-02 1373 views
2

我需要将文本文件的字节数组转换为它的字符串字符表示。c#十六进制字节0x09(ascii - > tab)到“ t”字符串

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

你好(标签)有(新行)朋友

我想将其转换成一个数组:

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"替换,但我想知道是否有内置的东西。

+0

这只是空白。 – marseilles84

+0

给他们逃脱的字符串?字符'\ t'的转义字符串看起来像“\\ ​​t” –

+0

如果您只用“\ t”替换它,那么您什么也不替换。 –

回答

0

如果您不介意它比手动滚动解决方案稍慢,那么您可以使用CodeDomProvider(这可能是可能的你的速度够快)。

我发现这里的示例代码:http://code.google.com/p/nbehave-cf/source/browse/trunk/CustomTool/StringExtensions.cs?spec=svn5&r=5

using System; 
using System.CodeDom; 
using System.CodeDom.Compiler; 
using System.IO; 

namespace CustomTool 
{ 
    public static class StringExtensions 
    { 
     public static String ToLiteral(this String input) 
     { 
      using (var writer = new StringWriter()) 
      { 
       using (var provider = CodeDomProvider.CreateProvider("CSharp")) 
       { 
        provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, null); 
        return writer.ToString(); 
       } 
      } 
     } 
    } 
} 

你会通过阅读使用Encoding.Ascii.ReadString()的字符串中使用它,然后用.ToLiteral()将其转换为一个字符串,然后.ToCharArray()得到最终的结果。

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

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

string test = "hello\tthere\nfriend"; 

char[] result = test.ToLiteral().ToCharArray(); 

如果检查result,你会看到它有正确的字符。

但是,我只是使用循环和switch语句来转换字符。写作和理解很容易,而且效率会更高。

+0

我认为这完全不适合这项任务... –

+0

@ D.R。有用;我试过了。你认为这不适合吗? –

+0

我已经删除了downvote,因为它的工作原理,你是对的。我仍然认为这项任务可以用较少的努力解决,也就是说,我认为你正在用大锤砸破螺母 –

1

如果你想逃避所有的控制字符,那么你可以使用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(); 
+0

但是'Regex.Escape'也会变成“。”到“\。”等等。它将会逃避所有特殊的正则表达式字符。 –

+0

已更新,以便它只能转义常见的非打印字符。我怀疑它会像循环字符串方法那样高效,如果它连续完成的话,但仅仅是一个例子,因为OP不想迭代字符串。 – keyboardP

+0

在这种情况下,编译正则表达式会显着提高它的速度(如果删除'\ a \ e \ f \ v'则更重要)。似乎如果经常调用这个正则表达式,值得编译。 – keyboardP

0

在“Y”阵列中,以“转义字符”将有它们的实际值(0×09,0X0D等)不可打印的字符作为“文本”。当您编写\ t,\ n,\ r等时,您可能已经写入(char)0x09,(char)0x0D,这就是数据写入的内容。换句话说,“\ t”字符不存在!

无论你是自己推出还是使用现有库,某人将不得不将0x09映射到“\ t”转义序列并将其注入到字符串中。

2

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

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文本,你可以使用:

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()); 
相关问题