【C#】テキストファイルの一部を,StreamWriter無しで書き換えたい時
関連記事
- 【#CSHARP】ソリューション内でサービス,Winformアプリを混在で作成させ,バイナリ出力先を同じにするとサービスが起動しない 【2024年02月08日(木)】
- 【#PHP】謎な #Laravel 案件 引き渡したじ 【2024年01月11日(木)】
- 【C#】謎な改造アプリ,SIMD命令を導入して高速化しようか,思案中 【2023年11月14日(火)】
- Javaの”やらかし”でC#と人気逆転か 激変プログラミング言語人気ランキング 【2023年10月18日(水)】
- 【#CSHARP】次の案件のスケルトン書いてgitサーバに登録するなどと 【2023年05月16日(火)】
バイナリデータをテキスト化して出力,処理最終段で
ヘッダとして利用している先頭部分に,このファイルのデータブロック総行数を書き込まないといけなくなったもんで
まぁ,行数が数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]
コメント
【地震】日向灘でM4.4の地震
【#第三次世界大戦】ウクライナ空軍 “ICBM1発がロシア南部から発射された”
司法省 “グーグルはクローム売却を” 裁判所に要求へ 米報道
最近,仕事がずっと激しい...ドロドロドロ
今日は謎の宴会らしい...スーツが入るのかっ!?(GRB爆
「侍ジャパン」宮崎県入り 「プレミア12」向け きょうから合宿
【#総選挙】 衆議院選挙 きょう投票 ...ドロドロドロ(24/10/27)
【#線状降水帯】宮崎 延岡「土砂崩れで家がつぶれている」通報 1人不明(24/10/23)
【冬】お~日本海に筋雲が出ちょる!冬がキター
【#寒冷前線】13時頃30℃の気温が今は25℃無いぞー