SharpZipLib・DotNetZipを使ったアーカイブの解凍でプログレスバーを表示する
SharpZipLibを使ったアーカイブの解凍でプログレスバーを表示します。なにしろ、ターゲットユーザは3秒以上の処理では状況表示しないと待っていてくれませんから... :-( プログレスバーを表示するのは以前書いたエントリC#でサブスレッドからプログレスバーにアクセスする(デリゲート・ラムダ式は快適!)とやり方は一緒です。
解凍の手順は簡単です。アーカイブのタイプに合わせたストリームクラスを作成してReadするだけ。gzipの場合は2回同じ手続きが必要なので注意します。
if (source.EndsWith(".tgz") == true || source.EndsWith(".tar.gz") == true)
{
GZipInputStream tgz =
new GZipInputStream(new FileStream(source, FileMode.Open,FileAccess.Read);
TarInputStream tar = new TarInputStream(tgz);
:
}ストリームを作成したら、アーカイブ内のエントリ毎に読みながらプログレスバーを更新していくだけ。
delegateProgressBar increment_bar = new delegateProgressBar((int v) =>
{ Cursor.Current = Cursors.WaitCursor; progressBar1.Value = v; });
ICSharpCode.SharpZipLib.Tar.TarEntry entry = tar.GetNextEntry();
while (entry != null)
{
Invoke(new delegateProgressBar((Int32 v) =>
{ progressBar1.Value = 0; progressBar1.Minimum = 0; progressBar1.Maximum = v; }),
new Object[] { (Int32.MaxValue < entry.Size) ?
(Int32)(entry.Size / 65536) : (Int32)entry.Size });
using (FileStream dest = new FileStream(
desitination + "¥¥" + entry.Name, FileMode.Create, FileAccess.Write))
{
Int32 count = 0;
Int32 write_total = 0;
byte[] buffer = new byte[32768];
using (BinaryWriter br = new BinaryWriter(dest))
{
while ((count = tar.Read(buffer, 0, 32768)) > 0)
{
br.Write(buffer, 0, count);
write_total += count;
if (Int32.MaxValue < entry.Size)
{
Object[] inc_arg = { (Int32)write_total / 65536 };
Invoke(increment_bar, inc_arg);
}
else
{
Object[] inc_arg = { write_total };
Invoke(increment_bar, inc_arg);
}
}
br.Flush();
br.Close();
}
dest.Close();
}
}プログレスバーのMaximumはInt32なので、巨大なファイルだとパンクするので適当に切り捨てた単位で回さないといけないのが面倒です。まー、プログレスバーなんて出さなくてもヘーキというユーザがターゲットの場合
using (ICSharpCode.SharpZipLib.Tar.TarArchive ta = TarArchive.CreateInputTarArchive(
new TarInputStream(new FileStream(source, FileMode.Open, FileAccess.Read))))
{
ta.ProgressMessageEvent +=
new ProgressMessageHandler(tar_ProgressMessageEvent);
ta.ExtractContents(desitination);
}で一発解凍できます。ProgressMessageHandlerを指定しておけばエントリ毎にイベントが上がってきますので取り出し中のエントリ名を表示したりとかくらいはできそうです。(エントリ単位で解凍するってのはやり方がわかりませんでした。)
ところで、このSharpZipLibですが*nix系システムで作成したzipをうまく解凍できないという問題があります。回避方法がハッキリしなかったのでzipに関してはIconic.Zipを使うようにしました。
using (Ionic.Zip.ZipFile zip = Ionic.Zip.ZipFile.Read(source))
{
zip.ExtractProgress +=
new EventHandler(extract_zip);
foreach (Ionic.Zip.ZipEntry entry in zip)
{
Invoke(new delegateUpdateLabel((string s) =>{ this.label1.Text = s; }),
new Object[] { entry.FileName + " extracting ..." });
entry.Extract(desitination, ExtractExistingFileAction.OverwriteSilently);
}
} こちらは逆にエントリ毎に解凍したバイト数がイベントで上がってきますのでそこでプログレスバーを更新してやればOKです。
500M近いアーカイブを毎日DLするので進捗具合を表示してやるのが必須の要件なんですが、それにしてもみんなセッカチですよ。これで少しは気も収まるかな?
ソースはhttps://github.com/hippos/extract_sampleにあります。
収束の判定法
で与えられる数列の収束性を調べる。
これを、として、
との大小を比べるやり方。二項定理により展開する式の途中が省略されていたので迷った時の補完メモ。
から、いきなり
に変形されている。迷ったのはここです。いきなり、ここまで展開されるとついていけない...
と、
まで、補ってようやく理解できた(気がする)。ってか、読めばなんとか理解できるものの、自力で
かつ、
まで、導くのムリ。
テストでも使ってはいけないアカウント名を抽出
いろんな実験用にServersman@vpsを借りてますが、logwatchから毎日毎日嫌になるくらい不正なアクセスがありますね−。特に、この数週間Dovecotへの不正アクセスが急増してます。まぁ、誰もユーザ作ってないんでログインできないんですけど、もうサービス止めておこうかなと思いますね。で、メールサーバ構築時に止めといた方がいいアカウント名のリストです。ログから抜き出して、sort | uniq -c | sort -rの結果です。
はやぶさ 不死身の探査機と宇宙研の物語 - 久しぶり、感動したよぉ
遅ればせながら「はやぶさ」本。感動しました。「はやぶさ」の物語というよりサブタイトルにあるとおり、不屈の挑戦を続けた「宇宙研」の物語のがメインか。こんな日本だって見捨てたものじゃないんだって思えるくらいに元気が出る。あとがききにもあるけど、著者も目指す「理工一体」の世界観に僕も強く惹かれた。
理学は、真理の探究であり、工学は善の実現である。そして、藝術は美の表現である-これで所謂「真善美」が揃う。理学と工学が常にペアを組んで、事に当たるという宇宙研の伝統手法は「真理の探究に最善を尽くす」という意味で、非常に意義深く、しかも効率的であり、故に美しい(p180)
僕は冴えないけれどプログラマなので、こんな世界観を、例えば「数学は、真理の探究であり、アルゴリズムは善の実現である。そして、コードは美の表現である」と置き換えて事に当たるよう心がけたいものだ。(カッコつけすぎだけど)
| はやぶさ―不死身の探査機と宇宙研の物語 (幻冬舎新書) | |
![]() |
吉田 武
幻冬舎 2006-11 |
後から知ったのですが、著者の吉田武氏は、「オイラーの贈り物」の著者でもあったんですね。というわけで再度読み直し中です。
| オイラーの贈物―人類の至宝eiπ=-1を学ぶ | |
![]() |
吉田 武
東海大学出版会 2010-01 |
マルチキーのソートでおバカした
vectorに突っ込んでいるオブジェクトを2つのキーでソート(要するにselect name,age,height from persons order by age,height)したくて、まぁ、operator<をごにょごにょすればなんとかなるかとか思っていたらなんか調子悪くてぜんぜんできない。カッとしてつい、いったんageでソートして、部分的にheightでソートするという暴挙をしでかしてしまった。
struct order_by_height : public binary_function<person,person,bool>
{
bool operator()(const person& lp,const person& rp) {
return lp.height() < rp.height();
}
};
bool person::operator<(const person& p) const
{ // order by age
return this->_age < p.age();
}としといて、
boost::xpressive 静的正規表現で書いてみた
VS2008以後は削除されてしまったCAtlRegExpのかわりにwindowsアプリの時はboost::xpressiveを使ってきましたが、はじめて静的正規表現を使ってみました。また、xpressiveはマルチバイト文字列非対応なんで_Unicodeプリプロセッサ付きです。(普段は国際化なんて意識していないのでTCHAR.h系の関数に慣れてなくて結構イライラしました...)
boost::xpressiveのイテレータ型の対応は、boost.Xpressive(日本語訳)(すばらしい!感謝)にあります。
| string::const_iterator | char* const | wstring::const_iterator | wchar_t* const | |
|---|---|---|---|---|
| basic_regex<> | sregex | cregex | wsregex | wcregex |
| match_results<> | smatch | cmatch | wsmatch | wcmatch |
| regex_compiler<> | sregex_compiler | cregex_compiler | wsregex_compiler | wcregex_compiler |
| regex_iterator<> | sregex_iterator | cregex_iterator | wsregex_iterator | wcregex_iterator |
| regex_token_iterator<> | sregex_token_iterator | cregex_token_iterator | wsregex_token_iterator | wcregex_token_iterato |
今回はワイド文字列対応なんで、wsregexとwsmatchを使います。先にも書きましたがこれまでは(仕様さえ決まってしまえば)特に動的である必要はないのに動的正規表現を使っていた怠慢を反省し静的正規表現で書いてみました。とりあえず、現状決まっているのは、文字列を「最後の空白」空白がなければ、「最初の数字」で区切るです。
pair<wstring,wstring> split_wstr(const wstring& wstr)
{
boost::xpressive::wsmatch matched;
//最後の空白で分割
#ifdef _DYNAMIC_REGEX_
boost::xpressive::wsregex regex_lastw =
boost::xpressive::wsregex::compile(_T("^(\\S.+)\\s(.+)$"));
#else
boost::xpressive::wsregex regex_lastw =
bos >> (s1=~_s >> +_) >> _s >> (s2=+_) >> eos;
#endif
if (boost::xpressive::regex_match(zname,matched,regex_lastw))
{
return pair<wstring,wstring>(matched.str(1),matched.str(2));
}
//最初の数字で分割
#ifdef _DYNAMIC_REGEX_
boost::xpressive::wsregex regex_firstn =
boost::xpressive::wsregex::compile(_T("^(\\D+)(\\d.+)$"));
#else
boost::xpressive::wsregex regex_firstn =
bos >> (s1=+~_d) >> (s2=_d >> +_) >> eos;
#endif
if (boost::xpressive::regex_match(zname,matched,regex_firstn))
{
return pair<wstring,wstring>(matched.str(1),matched.str(2));
}
// 以下仕様に応じていろんな分割が続く
:
}ご覧の通り、普段perlやrubyなんかで正規表現書いている人にとっては一見わかりにくいのが弱点でしょうか?特にドットをアンダースコアにするとか*や+が前に来るなどなかなか習慣からは抜け出せないと思うので、コメントとデバグの意味を込めて動的正規表現も併記したほうが後々のためかもしれません。
エンジニアのための時間管理術
久しぶりに読書メモ。読書メーターでも何人かの方が書いていますがエンジニアに特化した内容じゃないです。エンジニアには13章の「自動化」のあたりが面白いかもしれませんが、まぁ、大抵のギーク連中はこんなこととっくにやっているだろうから今更感があるかもしれません。それよりも、エンジニアやSA(原題もfor System Administrators)にだけあてはまることじゃない部分、2章「集中と割り込み」あたりが面白く、ネガティブな意味じゃなくて「悪印象を与えずに追い払う」とかは僕にとっては意外と盲点だったりして、うまく実践に取り入れてみたい。PDAやオーガナイザを使おうとかちょっと古い香りのするところもありますが、逆にこの手の本にありがちなガジェットの宣伝(今ならiPhoneやアプリの紹介)っぽいのがほとんどないのも好印象。
僕自身はプログラマでありながら、社内のシステムのお守り役も兼ねているわけで大好きなプログラミングのための時間をすこしでも多く捻出するため、本書の内容をいろいろ試してみようと思う次第です。
![]() |
エンジニアのための時間管理術 Thomas A. Limoncelli 株式会社クイープ オライリー・ジャパン 2006-10-19 |
redmineのインストール
記事書くのホント久しぶりです。最近はひたすら本読んだりしてあまりプログラムも書いてないし書くネタがなくて。昨日、久しぶりCentOS6にredmineをインストールしたんでそのことを。
といっても、ほとんどRedmine 1.3をCentOS 6にインストールする手順 | Redmine.JP Blogにある手順どおりにやっただけなのですが、いくつか手順どおりでうまくいかなかったところがあるので後の人のためのメモ。ほぼCentOS6をインストールした直後からスタートしてます。
まず、単純なタイポから。『必要なパッケージのインストール』のところと『RMagickのインストール』のところ。
yum install imagemagick imagemagick-devel
gem install RMagick --no-rdoc --no-riは、
yum install ImageMagick ImageMagick-devel
gem install rmagick --no-rdoc --no-ri大文字もしくは小文字でした。
『Ruby EnterPrise Editionの展開とインストーラの実行』では、「ファイルタイムスタンプがおかしいからシステム日付をチェックしろ!」みたいなエラーがでました。で、確認したらなぜかロケーションがボストンになってた!インストール時には東京にしたはずなのに...これを直したらふつうにできました。それにしても、Ruby Enterprise Editionなんてもの初めて知りました。もう、ずっとRuby周りを追いかけてなかったので衝撃的。でも、個人的にはあるプロダクトに、XXX-Editionみたいなのがあるのはあんまり好きじゃないかなぁ。
『Redmine用データベースとユーザの作成』の権限付与の部分は
grant all on db_redmine.* to user_redmine@loalhost identified by '*****';としておかないと初期化の時に蹴られます。
『Redmineの初期設定とデータベーステーブルの作成』の前にrailsとrdocがないと叱られます。これは、大前提なのかもしれませんが、OSセットアップ直後に手順通りにやったので... :-)
gem install -v=2.3.14 rails
gem install rdocこれだけ。後は100%Redmine 1.3をCentOS 6にインストールする手順 | Redmine.JP Blogのとおりでバッチリ。良記事をありがとうございます。
たくさんのチェックボックスを一度にON/OFFする方法
makePasswordの中で31個のチェックボックスを使うのですが、例えばすべてのチェックボックスをONにしたりOFFにしたりするにはCocoaではどうやるのか悩みました。オーソドックスにはOutletで接続して
[myCheckBox setState:YES]とかするのだろうけど、31個のOutletはさすがに面倒。似たような場合MFCなら、コントロールのIDを連続的に定義しておいて
int firstControl = IDC_XXXXX;
for(int controll = IDC_FIRST_XXX; controll < IDC_LAST_XXX; ++controll)
{
CButton* myButton = (CButton*)GetDlgItem(controll);
myButton->SetCheck(1);
}みたいなカンジでいちいちコントロール変数を定義しておかなくとも一気にセットできるのに。
結局、巧いテが見つからず今回はNSButtonのサブクラスを作成しコントロールクラスからtag値の配列をブロードキャスト
[[NSNotificationCenter defaultCenter]
postNotificationName:@"ChangeSpecialCharacterNotify" object:arrayContolsTag]; 各コントロールクラスでは通知に自分のtag値が含まれていたらON、含まれていなければOFFにする
- (void)awakeFromNib
{
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(handleSetState:)
name:@"SpecialCharacterNotify" object:nil];
}
-(void)handleSetState:(NSNotification*)aNotification
{
NSArray* characters = [aNotification object];
if (characters != nil &&
[characters containsObject:[NSNumber numberWithInteger:[self tag]]])
{
[self setState:YES];
}
else
{
[self setState:NO];
}
}っていう実装にしたんですが、もっと巧いやり方はないものか...なんかモヤモヤがとれません。ダイレクトに送る方法はないのかな?
mkpasswd作りました
ランダムなパスワードを生成するツールが欲しくて作りました。時間がなかったのでLinux等に付属のmkpasswdを流用しようと思ったのですが、ソースをみているうちに単なるrandom()を少しアレンジしただけのものでもいいかという気になったので、一気に作成しました。本当は、ANSI X9.17で乱数生成するつもりだったんですけど面倒なのでヤメました。
ソースはGitHub::makePasswordにあります。
サイモン・ペイントン・ジョーンズの9冊
Coders At Worksの7章はサイモン・ペイントン・ジョーンズさんの章ですが、面白そうな本や論文がいくつか出てきたのでメモ。インタビューは『無人島にもっていくべきプログラマのための本リストは?』に答えて6冊。他に話の流れの中で出てきたなんかも含めています。切りよく10冊ってしたかったけど1つ足りず9冊です。まぁ、ネタっぽくてすいません。(^^ゞ
珠玉のプログラミング(ジョン・ベントリー)
有名な本だし翻訳も手に入れやすいのに何故か読んでない本のひとつ。。なんでだろ?プログラミング本は好きなのに何故か触手が伸びません。これを機会に読んでみよう。
Writing Programs for The Book(ブライアン・ヘイズ)
「ビューティフル・コード」の33章に収録されてます。「ビューティフル・コード」は持っているのですがまだこの章は読んでませんでした。(^^ゞ原文はhttp://bit-player.org/bph-publications/BeautifulCode-2007-Hayes.pdfにありす。
The Art of Computer Programming(ドナルド・クヌース)
これは説明不要ですね。僕もプログラマの一人として本棚に飾りたい(いや熟読したい)シリーズ。チト高価ですがいつか買います。(いや、読みます)同書のクヌース先生自身の章でも触れていますが通読するような本でもないのでいつも傍らにおいてチラ見して楽しむのがよいのかも。
Purely Functional Data Structures(クリス・オカサキ)
あちこちで見かける評判の高い本です。が、ずっとアマゾンのカートに入ったまま。
計算機プログラムの構造と解釈(エイブルソン&サスマン)
これも説明不要ですかね。一部には熱狂的なファンもいるようですがこれも未読。っつーか最後まで読み通せる気がしないので敬遠している一冊。
Compilimg With Continuations(アンドリュー・アペル)
amazon.jpでは入手困難な感じ。中古でバカ高い値がついてます。海外のサイトならふつうの値段で買えそう。google ブックスでかなりの部分が立ち読みできます。後、似たような論文はたくさんあるみたいです。これを読むほどCSPを理解していないし親しんでもいません。
プログラミング原論(E.W.ダイクストラ)
ステパノフの同名(邦訳)がありますが、こちらは残念ながら絶版。とりあえず復刊リクエストしましたが望み薄そう。
The computer scientist as toolsmith(フレデリック・ブルックス)
http://www.cs.unc.edu/~brooks/Toolsmith-CACM.pdfで読めます。長い文章ではないしテーマも面白そうだからまずこれから読んでみようかと。
Why Functional Programming Matters(ジョン・ヒューズ)
原文とWhy Functional Programming Matters、邦訳なぜ関数プログラミングは重要か(山下さん訳)が読めます。
なんだ、結局僕にとっての未読リストというオチ。あれもこれもと手を広げすぎても仕方がないのでとりあえず邦訳があるものやPDFが公開されているものから読んでいこうかと思ってます。後、この章で一番グッときたのは、サイモンがカレッジで講師の仕事をしている時に受けたアドバイス
どんなにつまらなく見えることでもいいから、何かを始めなさい
ですね。サイモンはそれがすごく重要なアドバイスだったと語っています。
PhotorecでSDカードの復元。助かった!
まさか、使う日が来るとは。奥さんがやってしまいました、SDカードの初期化。最近のは容量があるのでなかなかマックに取り込まず撮りっぱなしで子どもの入学式の写真とかが逝っちゃいました。で、PhotoRecの出番。いまどきににはめずらしくCUIです。
なのでまず、SDカードをマウントして、ターミナルからphotorecを起動。ブートディスクは表示されないようで(sudo すれば対象にできるみたいです。)僕の環境ではSDカードのみが表示されてますので選択してリターン
.netでSFTPをしてみる 2
案件ではパスワードを使わず鍵だけでログインする仕様になりそうなので引き続き調べたところ、addIdentity()で鍵ファイル指定を追加してやるだけであっさりできました。(StrictHostKeyCheckingの設定はC# - SSH / SFTP connection issue using Tamir.SharpSshを参考にしました。)
private void sftp_pubkey_j
(string host, string user, string identify,string passphrase,Int32 port)
{
Tamir.SharpSsh.jsch.JSch jsch =
new Tamir.SharpSsh.jsch.JSch();
jsch.addIdentity(identify,passphrase);
System.Collections.Hashtable hashConfig =
new System.Collections.Hashtable();
hashConfig.Add("StrictHostKeyChecking", "no");
Tamir.SharpSsh.jsch.Session session = jsch.getSession(user, host, port);
session.setConfig(hashConfig);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp c = (ChannelSftp)channel;
Tamir.SharpSsh.java.io.FileInputStream source =
new Tamir.SharpSsh.java.io.FileInputStream("a.txt");
c.cd("temp");
c.put(source, "a.txt");
c.exit();
session.disconnect();
}ラッパークラスを使えばもう少しスッキリしたコードになるし、JavaXXXなんてのを目にしなくても良いです。
.netでSFTPをしてみる
FTP/SSLか、SFTPの実装が必要になりそうなので準備。C#でやろうと思っているので、FTP/SSLのほうは.net標準のFtpWebRequestにまかせてSFTPのほうをググってみたら
この2つが見つかりました。サンプルをザッとながめてみたらSharpSSHがのほうが簡単そうだったのでとりあえずサンプルコードを書いてみました。
private void runUpload()
{
Tamir.SharpSsh.jsch.JSch jsch = new Tamir.SharpSsh.jsch.JSch();
Tamir.SharpSsh.jsch.Session session = jsch.getSession("foo", "example.com", 22);
UserInfo uinfo = new MyUserInfo();
session.setUserInfo(uinfo);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp c = (ChannelSftp)channel;
Tamir.SharpSsh.java.io.FileInputStream source =
new Tamir.SharpSsh.java.io.FileInputStream("xyz.txt");
c.cd("temp/data");
c.put(source, "abc.txt");
c.exit();
session.disconnect();
}
public class MyUserInfo : UserInfo
{
public String getPassphrase() { return null; }
public String getPassword() { return "foovar"; }
public bool promptPassword(String message) { return true; }
public bool promptPassphrase(String message) { return true; }
public bool promptYesNo(String message) { return true; }
public void showMessage(String message)
{
MessageBox.Show
(message, "SSH", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
}これ、Javaで実装されたjschのAPIを利用していてそこここにJavaの名前が見えるところが面白いっちゅうか世界は広い。暗号化関連はMentalis.org Crypto Libraryを使ってます。
サンプルではMyUserInfoのところをUI実装してごにょごにょしていましたが、僕の場合はそこらへんは不要なのでそのまま値を返すように変更。とりあえずテストはできたのでこれで検討してみます。後はパスワードじゃなくて鍵を使う場合のほうも調べなきゃいけないし、週明けもう少し詳しく調べてみる予定。
コンボボックスの高さと幅を計算してみる
MFCでコンボボックスを使うときはフォームにコントロールを貼り付けてマウスでうにょ〜んって調整していたのですが、プログラムから動的に作成する場合それができないので、意味のあるウィンドウサイズを指定する必要があります。特に項目を追加したり削除したりといったことを頻繁におこなうときは結構面倒です。といっても所詮コンボボックスのウィンドウrectを指定するだけなんで何を指定するのかはある程度想像がつくのですが明示的に「こうしなさい」っていうドキュメントが見当たらなかったのでメモ。






最近のコメント
14 weeks 4 days ago
49 weeks 2 days ago
1年 14 weeks ago
1年 14 weeks ago
1年 31 weeks ago
1年 31 weeks ago
1年 31 weeks ago
1年 43 weeks ago
1年 43 weeks ago
2 years 23 weeks ago