2013年03月16日

「小説を読もう!」「小説家になろう!」一括ダウンローダ ver 2.30



ver2.30を作成しました。
・ファイル名の指定を、日付を後付けする方式から、${title}${author}のような形式に変えました。
 一度ファイル名の設定がクリアされますので、再度設定してください。
 昔の方式が良い人は、ver2.29とかを使用してください。
・無職転生がダウンロードできないということでしたので対応しました。
 インデックスページの日付がない人物紹介が想定外でした。
・一部のデフォルトを変えましたが、バージョンアップデータを使う人には関係ないです。

◆ver2.xからのバージョンアップ用(NovelDLフォルダをそのまま上書きしてください)
NovelDL_v2_30_bin_update.zip
※上書きの前に、バックアップをお勧めします。
※ver2.xの上書き以外だと、DBがないので動きません。

◆プログラム(新しく使う人 or ver1.xからの上書き)
NovelDL_v2_30_bin.zip

◆ソースコード
NovelDL_v2_30_src.zip

posted by w033 at 10:19| 東京 ☀| Comment(29) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする

2013年03月04日

BindingSourceにListかList>を突っ込みたい。 その2

その2というか、修正版。
ちょっとあほなミスをしていたり、無駄なことをやっているところを微修正。
ちなみに、このRowsCollection(よく考えたらRowCollectionだよ orz)クラスは、DataGridViewでページングをしたいときに便利。
もちろんフィルタでも可。
いままで、DataTableを1ページ分ImportRowやって、ページングの前に書き戻ししてました。。。
我ながら、なんて無駄な。
続きを読む
posted by w033 at 19:37| 東京 ☁| Comment(0) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする

2013年03月03日

DataTableのMax行件数は4,194,304件? その2

テスト環境とかは前の記事のままです。
http://w033.seesaa.net/article/341752172.html

で、よくいろんなところに、DataSetを使うよりGenericで書けば早くなるって記載が散見されたのでプログラムをちょっといじって試してみた。
DataTableをやめて、List<Dictionary<string, object>>に頑張ってもらった。
ちなみに、一度メモリを食いつくしたたら仮想メモリがガリガリうるさいので再起動済。
※テストソースは下のほう。

[テスト結果]
ミリ秒単位の経過時間の合計 = 26366ms
プロセス名   :TestDataTableCon.vshost
物理メモリ使用量:1606888KByte
仮想メモリ使用量:1883164KByte
i=3550435

えええぇぇぇぇ。
さらに件数が減って3,550,435件で落ちる(OutOfMemoryException)。
しかも、こっちは実行するごとに件数に微差がでるので、本当にメモリで落ちているっぽく。
書き方が悪いのか? とか思って下のようにインデクサでInsertしていたので、Addにしてみる。
Dictionary row = new Dictionary();
row["A"] = i;
  ↓
row.Add("A",i);

[テスト結果]
ミリ秒単位の経過時間の合計 = 24130ms
プロセス名   :TestDataTableCon.vshost
物理メモリ使用量:1614072KByte
仮想メモリ使用量:1883024KByte
i=3562390

実行速度がちょっと早くなっただけだし。。。
ま、当り前か。
でもDictionaryをつかう限り、変えるところとかないし。

DataTableと比べて、速度面からみても、件数の割合からいうと微差程度。
メモリ使用量もDictionaryとどっこい?
予想外すぎる。

あとはList<List<KeyValuePaire<String,object>>>とか?
だまって2次元配列とか。
DataTableの性能が良いというべきか、Generic周りがSTLの代わりになると思うのが失敗なのか。
C#でunsafeってのもなぁ。

※もちろん、OSとハードスペックとかに依存します。
続きを読む
posted by w033 at 21:34| 東京 ☁| Comment(0) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする

DataTableのMax行件数は4,194,304件?

うちの環境でやると、同じ件数でOutOfMemoryExceptionが発生する。
約400万件ってなんの制限?
これが40億ちょっとなら、32bit制限で納得なんだけれど。
#テストソースは下に掲載します。

[テスト環境]
・VM(WinXP 32bit) Memory:4GB
・HostOS(Win7の64bit) Memory:12GB

[コンパイル環境]
・Visual Studio 2010
・x86ビルド(Win7は64bitコンパイルも別途試した)
・.Net Framework4 CP

[実行結果(XP)]
ミリ秒単位の経過時間の合計 = 36364ms
プロセス名   :TestDataTableCon
物理メモリ使用量:1514212KByte
仮想メモリ使用量:1856132KByte
i=4194304(件数)

x86ビルドだと、XPでもWin7でも同じ件数で落ちる。
NewRow()したところで落ちている。
同じPC上とはいえ、別OS上で同じところで落ちるなら、言語仕様(正確にはフレームワークの仕様)だよね?
う〜ん、なんだこれ?

◆64bitで動作した時は?
ちなみに、Win7上で64bitコンパイルしたものを動かすと、1500万件までは確認したけど、VMとこのプログラムでメモリを食いつくしたので、そこでやめました。

もともとDataGrid上で動作させるプログラム(手動ページング)が一定件数で落ちるのをなんでか調べていたんだけれど、それ以前の話だった orz
意味不明だ。。。

続きを読む
posted by w033 at 20:39| 東京 ☁| Comment(2) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする

2013年03月02日

BindingSourceにListかList>を突っ込みたい。

こんなの調べるのに、ずいぶんかかった。。。

BindingSourceにDataRowかDictionaryを突っ込みたい。
突っ込むだけならできるのだけれど、それをDataGridViewに表示できない。
普段はDataTableに突っ込んでいるのだけれど、フィルタの機能が標準のものでは不満なのだけれど、DataRow[]だとDataGridViewで表示時に困る。
Dictionaryでも、配列でも、ちょっとめんどくさいクラスとかでもちょっと困る。
これの対応には2種類ある。
バインドするBindingSourceをどうにかするか、DataGridViewで表示するときに何とかする。
DataGridViewでやるなら「CellFormatting」「CellParse」イベントで対応できる。
実はこっちが簡単なのだけれど、画面のコントロールを何か所も直さないといけない。
正直だるい。。。

◆最終的にこんな風にやれるとうれしい。


private void Form1_Load(object sender, EventArgs e)
{
tbl = new DataTable("hoge");
tbl.Columns.Add(new DataColumn("A"));
tbl.Columns.Add(new DataColumn("B"));
tbl.Columns.Add(new DataColumn("C"));
for (int i = 0; i < 30; i++)
{
DataRow row = tbl.NewRow();
row["A"] = "A" + i;
row["B"] = "B" + i;
row["C"] = "C" + i;
tbl.Rows.Add(row);
}

// BindingSource bind = new BindingSource(); // これでなんとかなったら楽だったのに
RowsCollection bind = new RowsCollection(tbl);
for (int i = 0; i < tbl.Rows.Count; i++)
{
if (0 == i % 3)
{
bind.Add(tbl.Rows[i]);
}
}

dataGridView1.DataSource = bind;
dataGridView1.Refresh();
}



上のようにBindingSourceをつかうと、publicのプロパティー値が表示されてしまう(DataRowでいうとHasRowとか)。
違うんだ、やりたいのはテーブルをバインドした時と同じように動かしたいのだ。

いろいろ調べたけど、日本語のサイトはあまり見つからず。
DictionaryをDataGridViewにバインドって記事のほとんどは、KeyValuePairを縦に表示するような例。
いや、そんなの表示して何が嬉しいのさ。
デバックで見ればええやん。
とか思いつつ探すけれど、日本語の情報あんまりなくて。。。
数少ない参考になったのはこちら(本当に感謝!)
http://hongliang.seesaa.net/article/85853119.html

詳しくはリンク先を読んでもらえばわかるのだけれど、素直にインターフェイスをすべて実装するのは面倒臭すぎ。
お手軽にやりたいので、BindingSourceを継承して、そこにITypedListだけを実装した。
それでできたのが、こっち。



/// DataRowのコレクション
public class RowsCollection : BindingSource, ITypedList
{
#region
/// 行の情報を持つテーブル
DataTable Table { set; get; }
/// 初期化時にテーブルを保持する
public RowsCollection(DataTable target)
{
this.Table = target;
}
#endregion

#region ITypedList の明示的実装
PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
{
DataRow row = this[0] as DataRow;
PropertyDescriptor[] props = new PropertyDescriptor[this.Table.Columns.Count];
for (int i = 0; i < props.Length; i++)
{
props[i] = new ColumnDescriptor(this.Table.Columns[i].ColumnName);
}
return new PropertyDescriptorCollection(props);
}
string ITypedList.GetListName(PropertyDescriptor[] listAccessors)
{
return string.Empty;
}
#endregion

#region Descriptor
private class ColumnDescriptor : PropertyDescriptor
{
string columnName { set; get; }
public ColumnDescriptor(string colName) : base(colName, null)
{
this.columnName = colName;
}
public override string DisplayName
{
get { return this.columnName; }
}
public override Type ComponentType
{
get { return typeof(object); }
}
public override bool IsReadOnly { get { return false; } }
public override Type PropertyType { get { return typeof(object); } }
public override bool CanResetValue(object component)
{
return false;
}
public override object GetValue(object component)
{
DataRow row = component as DataRow;
return null == row ? Convert.DBNull : row[this.columnName];
}
public override void ResetValue(object component)
{
throw new NotSupportedException();
}
public override void SetValue(object component, object value)
{
DataRow row = component as DataRow;
row[this.columnName] = value;
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
}
#endregion
}



テストではかるく動かしただけなので、バグがあるかも。
DataViewにすきな行だけAddできないかとか、いろいろ調べたけれどこのコードが一番短くできそう。
Linq結果とか、配列をそのままバインドして編集できれば一番うれしかったのですがね。
数字にできるなら数字に変換してソート、それができないなら文字列にして、文字列だけでソートとかやりたいときに困るのですよ。
DataSetのSelectが、Accessみたいにfunctionを使えればこんなことをしないで済むのですがね。。。
posted by w033 at 23:53| 東京 ☀| Comment(0) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする