2

テキスト ファイルのバイト配列を文字列の文字表現に変換する必要があります。

たとえば、次のようなテキスト ファイルがあるとします。

こんにちは (タブ) そこに (改行) 友達

それを配列に変換したいと思います:

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"が、何かが組み込まれているのではないかと思っています。

4

4 に答える 4

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テキストであることが確実な場合は、次を使用できますEncoding.ASCII

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

または、文字配列が必要な場合:

char[] theChars = theText.ToCharArray();

それはおそらくあなたの目的には十分速いでしょう。文字列を1回通過し、文字ごとに読み取り、にコピーすることで、速度を上げることができる場合があります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());
于 2013-08-02T16:58:46.807 に答える
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エスケープされた制御文字は 2 文字 (\と) としてカウントされるため、投稿した方法で配列に変換することはできませんt。ただし、各キャラクターが別々であることを気にしない場合は、簡単に行うことができます

char[] myCharArray = myText.ToCharArray();
于 2013-08-02T16:53:28.773 に答える
0

「y」配列では、「エスケープされた文字」は実際の値 (0x09、0x0D など) になり、「テキスト」として印刷できない文字が含まれます。

\t、\n、\r などと書くと、(char)0x09、(char)0x0D と書くことができ、これがデータとして書き込まれるものです。つまり、「\t」文字は存在しません!

独自のロールを作成する場合でも、既存のライブラリを使用する場合でも、誰かが 0x09 を "\t" エスケープ シーケンスにマップし、それを文字列に挿入する必要があります。

于 2013-08-02T16:53:49.133 に答える
0

手巻きのソリューションよりも多少遅いことを気にしない場合は、 a を使用できます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 ステートメントを使用して文字を変換するだけです。書いて理解するのは簡単で、はるかに効率的です。

于 2013-08-02T16:49:53.790 に答える