最新の更新情報

2012年8月
« 7月   9月 »
 1234
567891011
12131415161718
19202122232425
262728293031  

本ブログのURL

qrcode.png

お天気

 
このブログ「吟遊詩人の戯言」 の記事検索...

【C#】テキストファイルの一部を,StreamWriter無しで書き換えたい時


キーワード(クリックで関連記事が読めます) →

関連記事

バイナリデータをテキスト化して出力,処理最終段で
ヘッダとして利用している先頭部分に,このファイルのデータブロック総行数を書き込まないといけなくなったもんで

まぁ,行数が数1000行ぐらいなら,StreamReader,StreamWriterあたりを使って
再読み込み~書き換え~別ファイルとして保存,って手がお手軽じゃけど...

対象は最大数10万行に達する可能性も
たった1箇所の書き換えに,このやり方はオーバーヘッドが洒落にならん!

ってことで.ちょいと書き起こしてみたが,これがテゲ面倒じゃった

まずは,書き換え対象のファイル


aaaa
iiii
1くまさんだぁ~
マキマキらぶ
hogehoge


%TEST%
まだまだ続くヨォ~


空行も挟んだ
エヴァンゲリオン
もういいじゃろ?
これで終わり


'%TEST%'(6文字分)って文字を置き換えます

して,ソース
FileStreamを使って,バイナリモードでテキストファイルを読み込み
改行を検出したら,バイナリを文字列化
'%TEST%'を'CHG 'に置き換えます.置き換え後の文字byte数は,置き換える前のバイト数と同じにしておかないと,トラブりまする

んで,先頭からのバイト数を加算しておき,置き換え処理を行うときは,
FileStream.Seek()で,ファイルポインタを戻して,バイナリモードで書き換えて,処理完了,って流れです

ちとソースが長いですが,参考にドゾー

C#:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9.  
  10. namespace filereplace
  11. {
  12.     public partial class Form1 : Form
  13.     {
  14.         private const string REPLACESTR = "%TEST%";
  15.        
  16.         public Form1()
  17.         {
  18.             InitializeComponent();
  19.         }
  20.  
  21.         private void button1_Click(object sender, EventArgs e)
  22.         {
  23.             System.IO.FileStream fs = System.IO.File.Open( "z:\\replacetest.txt",
  24.                                 System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite );
  25.  
  26.  
  27.             byte[] readbuf = new byte[65536];
  28.             byte[] writebuf =  null;
  29.             int readbufoffset = 0;
  30.  
  31.             long fileoffset = 0;
  32.             bool filejobfl = true;
  33.             while (fs.Position <fs.Length)
  34.             {
  35.                 if ((readbufoffset + 10)>= readbuf.Length)             //改行コードを見つけられずにバッファオーバーした場合
  36.                 {
  37.                     //なんらかのエラー処理
  38.                     break;
  39.                 }
  40.  
  41.                 int readresult = fs.Read(readbuf, readbufoffset, 10);
  42.                 if (readresult == 0)
  43.                 {
  44.                     break;
  45.                 }
  46.                 else
  47.                 {
  48.                     readbufoffset += readresult;
  49.                 }
  50.  
  51.                 bool LoopFL = true;
  52.                 while(LoopFL == true)
  53.                 {
  54.                     int cridx = 0;
  55.                     bool crfl = CheckCR(readbuf, out cridx);
  56.  
  57.                     if ( crfl == true)
  58.                     {
  59.                         byte[] tmpbuf = new byte[cridx+2];
  60.  
  61.                         Array.Copy(readbuf, tmpbuf, cridx+2);
  62.  
  63.                         string st = Encoding.GetEncoding("shift_jis").GetString(tmpbuf);
  64.  
  65.                         MoveAry(readbuf, cridx+2);          //前に詰める
  66.                         readbufoffset -= cridx+2;           //バッファの最終位置を調整
  67.  
  68.                         if (st.IndexOf(REPLACESTR)>= 0)
  69.                         {
  70.                             st.Replace(REPLACESTR, "CHG   ");     //%TEST%をCHG   に置き換え
  71.  
  72.                             fs.Seek(fileoffset, System.IO.SeekOrigin.Begin);
  73.  
  74.                             writebuf = Encoding.GetEncoding("shift_jis").GetBytes("CHG   ");
  75.  
  76.                             fs.Write(writebuf, 0, writebuf.Length);
  77.  
  78.                             filejobfl = false;
  79.                             LoopFL = false;
  80.                             break;
  81.                         }
  82.  
  83.                         byte[] dmybuf = Encoding.GetEncoding("shift_jis").GetBytes(st);    //先頭からのbyte長を加算
  84.                         fileoffset += dmybuf.Length;
  85.                     }
  86.                     else
  87.                     {
  88.                         LoopFL = false;
  89.                     }
  90.                 }
  91.                
  92.                 if (filejobfl == false)
  93.                 {
  94.                     break;
  95.                 }
  96.             }
  97.  
  98.             fs.Close();
  99.         }
  100.  
  101.         //改行コードの発見
  102.         private bool CheckCR(byte[] buf, out int Idx)
  103.         {
  104.             Idx = -1;
  105.             for(int i = 0; i <buf.Length; i++)
  106.             {
  107.                 if ((i + 1)>= buf.Length)
  108.                 {
  109.                     return false;
  110.                 }
  111.  
  112.                 if ((buf[i] == '\r') && (buf[i+1] == '\n'))
  113.                 {
  114.                     Idx = i;
  115.                     return true;
  116.                 }
  117.             }
  118.            
  119.             return false;
  120.         }
  121.  
  122.         //配列を前に詰める
  123.         private void MoveAry(byte[] buf, int mvCount)
  124.         {
  125.             for(int i =0; i <buf.Length; i++)
  126.             {
  127.                 if ((i + mvCount)>= buf.Length)
  128.                 {
  129.                     break;
  130.                 }
  131.                 if (buf[i + mvCount] == '\0')
  132.                 {
  133.                     for( int j = i; j <buf.Length; j++)
  134.                     {
  135.                         buf[j] = (byte)'\0';
  136.                     }
  137.                     break;
  138.                 }
  139.  
  140.                 buf[i] = buf[i + mvCount];
  141.             }
  142.  
  143.         }
  144.     }
  145. }

 
 
 
 

Leave a Reply

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <img localsrc="" alt="">