2009-05-13 19 views
7

非常に大きなデータ抽出の一部として書き込まれるテキストファイルがあります。テキストファイルの最初の行は、抽出された「アカウント」の数です。C#/ .NETを使用してファイル内のテキストを置換する最も良い方法は何ですか?

この抽出の性質上、この番号はプロセスの最後まで認識されませんが、ファイルが大きくなることがあります(数百meg)。

ファイル(この場合は単純なテキストファイル)を開き、テキストの最初の "行"にあるデータを置き換えるのにC#/ .NETの最も良い方法は何ですか?

重要なお知らせ: - 「固定量のバイト」を交換する必要はありません。これは簡単です。ここでの問題は、ファイルの先頭に挿入する必要があるデータが可変であることです。

重要なお知らせ2: - いくつかの人が、データをメモリに保存して置き換えてから、それを置き換えることを尋ねてきましたが、それは完全に問題にはなりません。このプロセスが更新されている理由は、いくつかのギグをメモリにロードするとクラッシュすることがあるからです。

+0

あなたが先行ゼロを持つことができません確信している "#####の\ r \ n(パディングを意味しませんか)"? –

答えて

4

実際の番号とスペースを最後に上書きするプレースホルダを挿入する必要がある場合は、挿入してください。

これはオプションではない場合、最初にキャッシュファイルにデータを書き込んでください。実際の数値が分かったら、出力ファイルを作成し、キャッシュからデータを追加します。

+0

はい、データを2回書くことを避ける唯一の方法です。テキストベースの場合は問題はありません。最初に適切なスペースを確保してください。 –

+0

これは、私が*空きスペースを確保するために*好きなものです - 唯一の問題は、書いているファイル形式が正確な#####r \ n(パディングなし)を必要とすることです。 - 良い答え。 –

+1

@ティモシー:先行ゼロを許していますか? –

1

抽出されたファイルがわずか数百メガバイトの場合、抽出が完了するまですべてのテキストをメモリに簡単に保存できます。次に、レコード数で始まる最後の操作として出力ファイルを書き込むことができます。

+3

「わずか数百メガバイト」?真剣ですか ? – Cerebrus

+1

私のマシンには2ギグしかありません。私たちのオフィスの他のほとんどは4と8の間です。200MBとは何ですか。たぶん総メモリの10%... –

+0

ファイルが「数ギガバイト」の何年もの間に何が起こるのでしょう? –

2

私は「バイトの固定 量」を交換する必要はありません

はよろしいですか? ファイルの最初の行(UInt32.MaxValueまたはUInt64.MaxValue)に大きな数値を書き込むと、正しい実際の数が見つかると、その数のバイトを正しい数で置き換えることができますが、0で埋められます、それはまだ有効な整数です。例:

Replace 999999 - your "large number placeholder" 
With  000100 - the actual number of accounts 
+0

賢明な回避策! - しかし、私が扱っているファイル仕様はそれを受け入れません...しかし、非常に良い考え:) –

+0

あなたは私になぜ尋ねてもらえませんか? –

+0

それはファイル仕様です、それは私の質問に答えませんでした:P –

3

ベストは非常に主観的です。小さなファイルの場合は、メモリ内のファイル全体を簡単に開き、文字列を置き換えてファイルを置き換えることができます。

大量のファイルであっても、メモリにロードするのは難しくありません。マルチギグの記憶の時代には、まだ数百メガバイトがメモリで簡単に処理できると考えています。

この単純なアプローチをテストしましたか?あなたはそれに本当の問題を見たことがありますか?

これは本当に大きなファイル(ギガバイトのサイズ)の場合は、最初にすべてのデータを一時ファイルに書き込んだ後、最初にヘッダー行が挿入された正しいファイルを書き込んだり、データ。それはテキストだけなので、私はおそらくDOSにシェルするでしょう:

TYPE temp.txt >> outfile.txt 
2

私は正しく質問を理解すると私に見えますか?

ファイル(この場合は単純なテキストファイル)を開き、テキストの最初の "行"にあるデータを置き換えるのにC#/ .NETの最も良い方法は何ですか?

ファイルの最初にトークン{UserCount}を配置する方法について説明します。

次に、TextReaderを使用してファイルを1行ずつ読み込みます。最初の行が{UserCount}を検索し、値で置き換えてください。あなたがたTextWriter

例を使用して読み取った各ラインアウト書く:

int lineNumber = 1; 
    int userCount = 1234; 
    string line = null; 

    using(TextReader tr = File.OpenText("OriginalFile")) 
    using(TextWriter tw = File.CreateText("ResultFile")) 
    { 

     while((line = tr.ReadLine()) != null) 
     { 
      if(lineNumber == 1) 
      { 
       line = line.Replace("{UserCount}", userCount.ToString()); 
      } 

      tw.WriteLine(line); 
      lineNumber++; 
     } 

    } 
+0

これは本質的に私がしなければならないことでしたが、私の目標は2つのファイルを作成する必要はありませんでした。 –

+0

私はもう一度、私が見たものの、まだ検証していない、または試したことのない解決策があります。基本的には、StreamWriterストリームのようなものを使って最初のファイルを書き出し、それを開いたままにしておきます。また、プレースホルダを提案し、トークンの開始点と終了点を保持するように記述してください。だからファイルの終わりにいて、UserCountを持っていて、戻ってトークンを自分の値に置き換えるだけでよいのです。これを行うには、StreamWriter.BaseStreamにアクセスして取得できるBitStreamを使用し、ストリーム内の特定の場所にバイトを書き込むことができます。それを試してテストして投稿します。 –

1

[OK]を、以前の私は、既存のファイルを扱う場合の方が良いだろうなアプローチを示唆しました。

しかし、あなたの状況ではファイルを作成する必要があり、作成プロセス中に上部に戻り、ユーザー数を書き出します。これはちょうどそれを行います。

これは、一時ファイルを書き込まないようにする方法の1つです。

private void WriteUsers() 
    { 
     string userCountString = null; 
     ASCIIEncoding enc = new ASCIIEncoding(); 
     byte[] userCountBytes = null; 
     int userCounter = 0; 

     using(StreamWriter sw = File.CreateText("myfile.txt")) 
     { 
      // Write a blank line and return 
      // Note this line will later contain our user count. 
      sw.WriteLine(); 

      // Write out the records and keep track of the count 
      for(int i = 1; i < 100; i++) 
      { 
       sw.WriteLine("User" + i); 
       userCounter++; 
      } 

      // Get the base stream and set the position to 0 
      sw.BaseStream.Position = 0; 

      userCountString = "User Count: " + userCounter; 

      userCountBytes = enc.GetBytes(userCountString); 

      sw.BaseStream.Write(userCountBytes, 0, userCountBytes.Length); 
     } 

    } 
+0

これは、既存のファイルを編集する要求に答える唯一の答えです...ありがとうございます! – ephraim

関連する問題