【C#】テキストファイルの一部を,StreamWriter無しで書き換えたい時
関連記事
- 【#CSHARP】次の案件のスケルトン書いてgitサーバに登録するなどと 【2023年05月16日(火)】
- 生成AI「仕事で利用」2割 正確性などに懸念(23/5/7) 【2023年05月07日(日)】
- 【#RaspberryPI】ラズパイでsudo起動の.Net6アプリがデバグできない件 【2023年04月22日(土)】
- 【#PostgreSQL】テーブルから取得したレコードセットをCSVへ落とそうとすると,空ファイルが出来る...ドロドロドロ 【2023年03月08日(水)】
- 【#git】TortiseGit ver2.14のGitWCRev.exeを動かすとErrorCD:10を出力して,動かない 【2023年02月08日(水)】
バイナリデータをテキスト化して出力,処理最終段で
ヘッダとして利用している先頭部分に,このファイルのデータブロック総行数を書き込まないといけなくなったもんで
まぁ,行数が数1000行ぐらいなら,StreamReader,StreamWriterあたりを使って
再読み込み~書き換え~別ファイルとして保存,って手がお手軽じゃけど...
対象は最大数10万行に達する可能性も
たった1箇所の書き換えに,このやり方はオーバーヘッドが洒落にならん!
ってことで.ちょいと書き起こしてみたが,これがテゲ面倒じゃった
まずは,書き換え対象のファイル
aaaa
iiii
1くまさんだぁ~
マキマキらぶ
hogehoge
%TEST%
まだまだ続くヨォ~
空行も挟んだ
エヴァンゲリオン
もういいじゃろ?
これで終わり
‘%TEST%'(6文字分)って文字を置き換えます
して,ソース
FileStreamを使って,バイナリモードでテキストファイルを読み込み
改行を検出したら,バイナリを文字列化
‘%TEST%’を’CHG ‘に置き換えます.置き換え後の文字byte数は,置き換える前のバイト数と同じにしておかないと,トラブりまする
んで,先頭からのバイト数を加算しておき,置き換え処理を行うときは,
FileStream.Seek()で,ファイルポインタを戻して,バイナリモードで書き換えて,処理完了,って流れです
ちとソースが長いですが,参考にドゾー
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace filereplace
{
public partial class Form1 : Form
{
private const string REPLACESTR = “%TEST%”;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
System.IO.FileStream fs = System.IO.File.Open( “z:\\replacetest.txt”,
System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite );
byte[] readbuf = new byte[65536];
byte[] writebuf = null;
int readbufoffset = 0;
long fileoffset = 0;
bool filejobfl = true;
while (fs.Position < fs.Length)
{
if ((readbufoffset + 10) >= readbuf.Length) //改行コードを見つけられずにバッファオーバーした場合
{
//なんらかのエラー処理
break;
}
int readresult = fs.Read(readbuf, readbufoffset, 10);
if (readresult == 0)
{
break;
}
else
{
readbufoffset += readresult;
}
bool LoopFL = true;
while(LoopFL == true)
{
int cridx = 0;
bool crfl = CheckCR(readbuf, out cridx);
if ( crfl == true)
{
byte[] tmpbuf = new byte[cridx+2];
Array.Copy(readbuf, tmpbuf, cridx+2);
string st = Encoding.GetEncoding(“shift_jis”).GetString(tmpbuf);
MoveAry(readbuf, cridx+2); //前に詰める
readbufoffset -= cridx+2; //バッファの最終位置を調整
if (st.IndexOf(REPLACESTR) >= 0)
{
st.Replace(REPLACESTR, “CHG “); //%TEST%をCHG に置き換え
fs.Seek(fileoffset, System.IO.SeekOrigin.Begin);
writebuf = Encoding.GetEncoding(“shift_jis”).GetBytes(“CHG “);
fs.Write(writebuf, 0, writebuf.Length);
filejobfl = false;
LoopFL = false;
break;
}
byte[] dmybuf = Encoding.GetEncoding(“shift_jis”).GetBytes(st); //先頭からのbyte長を加算
fileoffset += dmybuf.Length;
}
else
{
LoopFL = false;
}
}
if (filejobfl == false)
{
break;
}
}
fs.Close();
}
//改行コードの発見
private bool CheckCR(byte[] buf, out int Idx)
{
Idx = -1;
for(int i = 0; i < buf.Length; i++)
{
if ((i + 1) >= buf.Length)
{
return false;
}
if ((buf[i] == ‘\r’) && (buf[i+1] == ‘\n’))
{
Idx = i;
return true;
}
}
return false;
}
//配列を前に詰める
private void MoveAry(byte[] buf, int mvCount)
{
for(int i =0; i < buf.Length; i++)
{
if ((i + mvCount) >= buf.Length)
{
break;
}
if (buf[i + mvCount] == ‘\0’)
{
for( int j = i; j < buf.Length; j++)
{
buf[j] = (byte)'\0';
}
break;
}
buf[i] = buf[i + mvCount];
}
}
}
}
[/csharp]
コメント
【体調不良】起きて早々,閃輝暗点発生中
【#あまちゃん】「あまちゃん」放送10周年記念 スペシャルコンサート 久慈
#あまちゃん 10周年スペシャルコンサートのチケットを買ってみた eplusの新会員登録画面,作りがなっとらん!
イーロン・マスク氏 「X」全利用者に少額課金求める考え示す
秋分の日 雨が降り出した しかも涼しい
【#インフルエンザ】「インフル 4週間以内に大流行の可能性 対策を」小池都知事
“吉田屋”の駅弁 1都23県295人が体調不良を訴える 八戸市保健所
【アゼルバイジャン】ナゴルノカラバフ アルメニア側“事実上敗北” 死者200人超か