ファイルの任意の行を読み込む方法 – プログラミング – Home

ファイルの任意の行を読み込む方法
 
通知
すべてクリア

[解決済] ファイルの任意の行を読み込む方法


こげ茶色
 こげ茶色
(@こげ茶色)
ゲスト
結合: 19年前
投稿: 2
Topic starter  

時系列データが記録されたcsv形式のファイルを読み込むという処理をしています。
readFileStreamを用いて1行ずつ、順を追って読み込むという処理は容易なのですが、
CSVデータを利用した処理結果如何によっては過去(前の行)のデータに戻るという処理
を加えたいと思っています。
全てのデータを一括して配列に読み込めば一応は解決するのですが、
データ数が数万件に及びますので、メモリの関係上、そのような処理はとりたくないと考
えています。
ReadLineした後にファイルの読み込んだ位置を保存し、場合によってはその位置を操作し
てから再び読み込み始めるというような処理をすることは可能なのでしょうか?


引用未解決
トピックタグ
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

全ての行番号と、ファイル内でのその行の開始位置を保存しておいて、Seek すればいい
んじゃないのかな。


返信引用
YuO
 YuO
(@YuO)
ゲスト
結合: 22年前
投稿: 320
 

> readFileStreamを用いて1行ずつ、順を追って読み込むという処理は容易なのですが、

readFileStream ?

> CSVデータを利用した処理結果如何によっては過去(前の行)のデータに戻るという処

> を加えたいと思っています。

基本的に出来ません。
# 出来るように自分で工夫をした場合を除く

> ReadLineした後にファイルの読み込んだ位置を保存し、場合によってはその位置を操作

> てから再び読み込み始めるというような処理をすることは可能なのでしょうか?

StreamReaderを仮定した場合,StreamReaderはバッファリングを行うので不可能です。

a.) 前処理を行って,固定長にしてSeek可能にしておく
b.) あきらめて全てメモリにため込む
c.) 毎回先頭から読み直す
といった方法を採る必要があります。
# ADO.NETでJET OLE DB経由,というのは使えるのかなぁ……。データ次第ですが。

> 全ての行番号と、ファイル内でのその行の開始位置を保存しておいて、Seek すればい

> んじゃないのかな。

「その行の開始位置」の取得が厳しいです。
PositionやSeekはBaseStreamにしかないので。
# とりあえず,こちらもStreamReaderを仮定。FileStream + BinaryReaderなら可能か
と。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

>
StreamReaderを仮定した場合,StreamReaderはバッファリングを行うので不可能です。

ReadLine が終わった時点での Position は次の行の開始位置とは限らんのか。


返信引用
YuO
 YuO
(@YuO)
ゲスト
結合: 22年前
投稿: 320
 

> ReadLine が終わった時点での Position は次の行の開始位置とは限らんのか。

とりあえず,マニュアルには記載がないので,仮定は出来ません。

現実問題としては,StreamReaderにバッファサイズを指定しなかった場合,
BaseStream.Positionは1024単位で移動しました。
# .NET Framework 2.0.50727.42で確認。


返信引用
こげ茶色
 こげ茶色
(@こげ茶色)
ゲスト
結合: 19年前
投稿: 2
Topic starter  

平日忙しく、折角ご回答いただいたのになかなか返答できませんでした、すみません。
Seek()を使うというヒントを頂きましたので、これを利用してコードを書いてみました。
初回読み込み時に行先頭の位置をArrayListに保存して、
その後、行移動はArrayListに保存した位置を手掛かりにSeekするというものです。
StreamReaderが具体的にどのような処理をしているのか理解不足ですので、
処理としては無駄な箇所があるかと思いますが、とりあえず動くには動きましたので
ご報告いたしました。
助言、ありがとうございます。

ArrayList ALColumnByte = new ArrayList();
FileStream fsCSV;
StreamReader srCSV;
string strBuff, strAll;
ALColumnByte.Add(0);
fsCSV = new FileStream(strFilePath, FileMode.Open);
srCSV = new StreamReader(fsCSV, Encoding.GetEncoding(Shift_JIS));
strAll = ";
while ((strBuff = srCSV.ReadLine()) != null){
strAll += strBuff + \r\n;
Encoding sjisEnc = Encoding.GetEncoding(Shift_JIS);
ALColumnByte.Add(sjisEnc.GetByteCount(strAll));
}
srCSV.Close();
fsCSV.Close();

fsCSV.Seek((long)(int)ALColumnByte[i], 0);
strBuff = srCSV.ReadLine().Split(',');


返信引用
YuO
 YuO
(@YuO)
ゲスト
結合: 22年前
投稿: 320
 

解決となっていますが……。

StreamReader.BaseStream.Seekを呼び出したあとは,
StreamReader.DiscardBufferedDataを呼び出した方がよいです。
もちろん,BaseStreamを介していない場合でもです。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました