2013-08-02 1426 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()); 
相關問題