- PR -

【C#】単一テキストファイルから重複行削除

投稿者投稿内容
今川 美保(夏椰)
ぬし
会議室デビュー日: 2004/06/10
投稿数: 363
お住まい・勤務地: 神奈川県茅ヶ崎市
投稿日時: 2006-06-13 18:26
引用:

がうしぇさんの書き込み (2006-06-13 18:04) より:
Cygwinをインストールして、uniq コマンドとか、sedとか、せめて Perl を使う方が楽なのではないかと...

"鶏を割くに焉んぞ牛刀を用いん"というか、ザク一匹にソーラーシステムのような気が...



おらのパソコンにはSFUがはいっているので
同一ファイルで実験やってみましたよ。

引用:

$ time sort -u test.txt > /dev/null
2.67s real 1.25s user 0.65s system
$


でした。

やっぱりコマンドいいっすね♪
_________________
夏椰 @ わんくま同盟
夏椰の庵
Microsoft MVP for Windows Server System - SQL Server ( Jul 2006 - Jun 2008 )
ちづる
ベテラン
会議室デビュー日: 2004/07/27
投稿数: 72
投稿日時: 2006-06-13 18:35
R・田中一郎様
・少ない件数で試してみる。
→3000件程度だと40秒?程度で処理を終了します。
・どの部分で帰ってこないのか確認する。(DBエンジン側の処理で帰ってこない?)
→ 帰ってこない、という言い方はおかしいですが、
while (dr.Read() == true)
{
strData += dr.GetValue(0);
strData += "\r\n";
}
上記のLoopで延々と処理してるので、レスポンス的に5分以上メモリも保持してる
感じです。
・書き込み処理はどうしてます?
→LoopでString変数に代入したものをStreamWriterで吐き出しています。

夏椰様
引用:
通番+30文字@aaaa.co.jp
通番+30文字@bbbb.co.jp
(通版=1〜65536)
のデータが入ったトータル件数131,072件(ファイルサイズ:7,843,840 バイト)
でサンプルとして提示したプログラムを動かしたところ
30秒足らずで表示する処理は終わりましたね。
#ちなみにプログラムはVS2005 C# Expressで実行しています。

R・田中一郎さんもおっしゃっていますが、
データの取得で返ってこないのかなどを調べる必要があると思います。

現状のプログラムはデータを取得するのみの状態でしょうか?
問題切り分けのためにも、1つずつ処理を実装して、確認してみてください。

また処理内容に不安などがあれば、出来る範囲でソースを提示してみてください。



30秒・・・う、うらやましいです。
プログラムはVS2003のC#にて作成、実行しています。
下記がソースです。
(実際は、StreamWriterの書出処理は別ロジックにあり、それを呼び出しています)
private void Sample()
{
int itime;
string strData = null;


OleDbConnection con = new OleDbConnection();
OleDbCommand oCommand = new OleDbCommand();
try{
string sql = "select distinct * from textfile.txt";
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\;Extended Properties=\"text;HDR=NO;FMT=Delimited\"";
oCommand.Connection = con;
oCommand.CommandText = sql;
OleDbCommand cmd = new OleDbCommand(sql, con);
con.Open();
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read() == true)
{
strData += dr.GetValue(0);
strData += "\r\n";
}
con.Close();

StreamWriter sw = new StreamWriter(@"c:\filedata.txt", false,System.Text.Encoding.GetEncoding(932));
sw.Write(strData);
sw.Close();


}
catch (Exception oExcept)
{
MessageBox.Show(oExcept.Message, "エラー");
}
}
今川 美保(夏椰)
ぬし
会議室デビュー日: 2004/06/10
投稿数: 363
お住まい・勤務地: 神奈川県茅ヶ崎市
投稿日時: 2006-06-13 18:43
引用:

ちづるさんの書き込み (2006-06-13 18:35) より:

strData += dr.GetValue(0);
strData += "rn";




これネックになりますよね?(^^;

自分のロジックでわざと 上記処理を記述すると遅くなりますもん。


見ていると、ファイル読込→溜め込み→書き出しになっていますが、
せっかくSQL文でDISTINCTつけて重複省いているので、
読み取ったデータは即書き込んでもいいと思ったんですが、駄目ですかね?
そうすれば、変数に足しこんでいかなくても済みますよね。


-----------------
以下追記

自PCでの実験で
溜め込むとしてもStringBuilderを使えば問題なかったですよ。

_________________
夏椰 @ わんくま同盟
夏椰の庵

[ メッセージ編集済み 編集者: 夏椰 編集日時 2006-06-13 18:45 ]
ちづる
ベテラン
会議室デビュー日: 2004/07/27
投稿数: 72
投稿日時: 2006-06-13 19:00
引用:

夏椰さんの書き込み (2006-06-13 18:43) より:

これネックになりますよね?(^^;

自分のロジックでわざと 上記処理を記述すると遅くなりますもん。


見ていると、ファイル読込→溜め込み→書き出しになっていますが、
せっかくSQL文でDISTINCTつけて重複省いているので、
読み取ったデータは即書き込んでもいいと思ったんですが、駄目ですかね?
そうすれば、変数に足しこんでいかなくても済みますよね。


-----------------
以下追記

自PCでの実験で
溜め込むとしてもStringBuilderを使えば問題なかったですよ。

_________________





strData += "rn"; ←これがネックでしたか・・・。
StringBuilderを使用して試してみました。なるほど、高速です。
この状態だと、全てが一行?の状態になってるのですが、
出力ファイルの中身を行単位で改行してあるデータにしたい場合は
どのタイミングで改行を行うべきでしょうか?
R・田中一郎
ぬし
会議室デビュー日: 2005/11/03
投稿数: 979
投稿日時: 2006-06-13 19:02
文字列の連結は毎度新しい領域に全てコピーしなおすので、大量のものだと重くなるんですよ^^;
夏椰さんのいうように、StringBuilderを使うと高速に連結できます。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2006-06-13 23:53
引用:

R・田中一郎さんの書き込み (2006-06-13 19:02) より:
文字列の連結は毎度新しい領域に全てコピーしなおすので、大量のものだと重くなるんですよ^^;
夏椰さんのいうように、StringBuilderを使うと高速に連結できます。


それもそうですし、今回の場合は例えば一行ずつ処理しながら
ファイルに書き出すなどしていけばいいでしょうから、
そもそも文字列をすべて連結する必要自体ありません。
やらなくていいことはやらずに済ますのが基本です(特に負荷がかかるような処理は)。
今川 美保(夏椰)
ぬし
会議室デビュー日: 2004/06/10
投稿数: 363
お住まい・勤務地: 神奈川県茅ヶ崎市
投稿日時: 2006-06-14 09:13
引用:

ちづるさんの書き込み (2006-06-13 19:00) より:

strData += "rn"; ←これがネックでしたか・・・。
StringBuilderを使用して試してみました。なるほど、高速です。
この状態だと、全てが一行?の状態になってるのですが、
出力ファイルの中身を行単位で改行してあるデータにしたい場合は
どのタイミングで改行を行うべきでしょうか?



なんか勘違いされている気がしました・・・・。

Stringの変数を+=で連結していくことが問題であり、
改行コードを連結することが問題ではありません。
#よって
# strData += "rn";だけでなく
# strData += dr.GetValue(0); も問題なんですよ。

理由については R・田中一郎さんがフォローしてくれています。

また、なちゃさんもおっしゃっていますが、
変数にためる必要性を今一度、ご考慮くださいませ。

_________________
夏椰 @ わんくま同盟
夏椰の庵
Microsoft MVP for Windows Server System - SQL Server ( Jul 2006 - Jun 2008 )
がらす
ベテラン
会議室デビュー日: 2005/07/14
投稿数: 99
投稿日時: 2006-06-14 09:56
こんなのもあります。
http://sonic64.com/2005-11-30.html

+= で連結していく場合、string をそのまま連結すると、StringBuilderを使った時の100倍ぐらい時間がかかるという話です。
StringBuilderはあらかじめ大き目のメモリを確保しておいて、そこに文字列を継ぎ足していくのですが、stringは += が1回実行されるたびに新たにメモリを確保してコピーをするからです。メモリ確保もコピーも時間がかかるのです。

スキルアップ/キャリアアップ(JOB@IT)