【C#】テキストファイルの一部を,StreamWriter無しで書き換えたい時
関連記事
- 【ChatGPT o4】祝日なのに仕事ーバテすぎー今夜こそ絶命だーモルモルモル 【2025年03月20日(木)】
- 【#CSharp】制御系が動き出したべ 【2025年02月20日(木)】
- 【#CSharp】ひっさしぶりにガッツリなC#案件をやっているぞー 【2025年02月19日(水)】
- 今週もひたすらモノ書き #JAVA 祭りがまだまだ続く そろそろC#を書かせろー 【2024年12月04日(水)】
- 【#CSHARP】ソリューション内でサービス,Winformアプリを混在で作成させ,バイナリ出力先を同じにするとサービスが起動しない 【2024年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]
コメント
今日は城主生誕記念日で日本国は祝日,らしい...
兵庫 城崎温泉 旅館で火事 ほぼ消し止められる
東海道新幹線 停電のため運転見合わせ 区間が拡大 原因調査中
【霧島山】新燃岳:活発化してた火山性地震,ピタッと止まった(25/4/26)
今日は落雷,ひょうに厳重警戒じゃげな(25/4/14)
中日本高速道路 ETCシステム障害 7都県 一部の専用レーン閉鎖(25/4/6)
iPhone米価格は相互関税で30─40%上昇か、上位機種は2300ドルも
【地震】大隅半島東方沖で地震:宮崎市などで震度4 津波の心配なし(25/4/3)