それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

Rubyで巨大ファイルを読み込むときに進捗率を表示したい

Rubyを使ってバッチ処理や集合演算をするときに、ファイルをどこまで読み込んだかパーセント表示したい。表示しておかないとどこまで処理しているかが分からないので不安になる。処理状況を表示する。

File#linenoを使えばいいかと思ったが、File#linenoはFile#readやFile#readlinesなどを一度実行しないと、ファイルの行数が分からないようなので。。。ポインタの位置から進捗を見ることにする。

進捗率の表示

進捗を%表示で見せるサンプル
open filename do |f|
  size = File.size f.path
  f.each_line do |line|
    #do something...
    $stderr.print sprintf("%.3f%",f.tell.to_f/size.to_f*100)+"\r"
  end
end

解説:

  • File.sizeでファイルサイズを取得する
  • File#tellで現在の位置を取得する
  • "\r"を使うことで書き出しを固定

もちろんこれを応用すればコンソールにプログレスバーを作れるわけだが。さすがに、そこまでは不要だと思うのだが。自己満足のために作ってみた

プログレスバー(コンソール)

GUIは別スレッドで画面更新処理が必要なので、コンソールのみ。

def show_progress_bar(progress)
	print "#"*progress.to_i, "-"*(100-progress.to_i),":",sprintf("%.3f%",progress.to_f),"%\r"
end
open filename do |f|
  size = File.size f.path
  f.each_line do |line|
    #do something...
    show_progress_bar f.tell.to_f/size.to_f*100
  end
end

Perlのいいとこ取りのおかげで簡単にかける。Ruby素敵。

Synergyを自動接続。

Synergyの起動が面倒だ。

Synergyは暗号化通信をしない。暗号化はSSHのポートフォワーディングでヤレってスタンスのようです。そこでSSHポートフォワーディングをPuttyでやるのですが。コレが面倒だ。
無線LANが切断されるたびに、Synergyとポートフォワーディングを起動する。これが何度も繰り返されると面倒だ。

そこでこれを自動化した。そして無線LANの接続イベントにAttachしてやった。これで特定のAPにつないだときだけ自動で起動するようになった。

動作の概要。

無線LANに接続⇒プログラム起動⇒Synergy再接続

無線LANに接続したタイミングでsynergy起動

IntelWirelessControlerで設定できた。アクセスポイント設定がある。接続時に指定プログラムを実行させる。アクセスポイント毎に別々のプログラムが指定可能。

Synergyの起動

SynergyはノートPCで動かすため、デスクトップに接続する。ただしIPの変更対応と通信の暗号化のためポートフォワーディングを採用してLocalhostの24800番をサーバーに転送する。

意外と便利だ

synergy_restart.js:

Synergyのプロセスをすべて終了して接続し直す。WMIとWSHの傑作。

/***
*  Synergy開始
*/
/**
* synergyを開始するコマンド実行
*/
function doCmd( command ){
  var shell = WScript.CreateObject("WScript.Shell");
  shell.Run( command, 0, false);
  return void(0);
}
/**
* WMI をWSHから起動して引数に一致するなまえのプロセスを殺す。
* @argment program_name プログラム名(たいていは ***.exe)
*/
function TerminateProcess( program_name ){
  var strComputer = ".";
  var name = "winmgmts:\\\\" + strComputer + "\\root\\CIMV2";
  var oWmis = GetObject(name);
  var cols = oWmis.ExecQuery("SELECT * FROM Win32_Process WHERE Caption = '"+ program_name +"'")
  var list = new Enumerator(cols)
  for(;!list.atEnd(); list.moveNext()){
    var proc = list.item();
    //WScript.Echo( proc.Caption );
    //WScript.Echo( "\t" + proc.ProcessId);
    //WScript.Echo( "\t" + proc.terminate() );
    proc.terminate()
  }

}
/**
* 既存のsynergycを終了する。
*/
function killExistsSynergys(){
  TerminateProcess( "synergyc.exe" );
}
/**
* 既存のポートフォワーディングを終了する。
*/
function killExistsPortForwarding(){
  TerminateProcess( "pfwd.exe" );
}
function ConnectToSynergys(){
  var host_name = "localhost";
  var port = "24800";
  var screen_name = "d420";
  var synergyc_path = 'C:\\Program Files\\Synergy\\synergyc.exe'
  var synergy_cmd = '"'+synergyc_path + '"' + " --daemon --restart --name " + screen_name+" "+host_name+":"+port+' ';
  //WScript.Echo(synergy_cmd);
  return doCmd(synergy_cmd);
}
function StartPortFowarding(){
  var fwd = '"C:\\Program Files\\PuTTY\\pfwd.exe"';
  var ini = '"C:\\Program Files\\PuTTY\\pfwd.ini"';
  var cmd = fwd + " " + ini;
  //WScript.Echo(cmd);
  return doCmd(cmd);
}
function main(){
  killExistsPortForwarding();
  killExistsSynergys();
  StartPortFowarding();
  ConnectToSynergys();
}
main();

//自動的にSynergyを開始する。
//
//できれば)SSHでサーバーにログインしてSynergyを再起動。
//SSH port forwadingを実行
//実行コマンド #> '"C:\Program Files\PuTTY\pfwd.exe" "C:\Program Files\PuTTY\pfwd.ini"';
//
//Synergyを実行
//
//
//"C:\Program Files\Synergy\synergyc.exe" --daemon --restart  --name d420 localhost:24800
//
//host_name localhost
//screen_name d420
//port 24800
//interface 192.168.4.55 (ここは動的に取得したい)
//Usage: synergyc [--daemon|--no-daemon] [--debug <level>] [--display <display>] [--name <screen-name>] [--restart|--no-restart] <server-address>
//
//
//
//Start the synergy mouse/keyboard sharing server.
//  -d, --debug <level>      filter out log messages with priorty below level.
//                           level may be: FATAL, ERROR, WARNING, NOTE, INFO,
//                           DEBUG, DEBUG1, DEBUG2.
//      --display <display>  connect to the X server at <display>
//  -f, --no-daemon          run the client in the foreground.
//*     --daemon             run the client as a daemon.
//  -n, --name <screen-name> use screen-name instead the hostname to identify
//                           ourself to the server.
//  -1, --no-restart         do not try to restart the client if it fails for
//                           some reason.
//*     --restart            restart the client automatically if it fails.
//  -h, --help               display this help and exit.
//      --version            display version information and exit.
//* marks defaults.

AmazonのURL掃除するブックマークレット

AmazonのURLがアレなのです。SEOキーワードにあふれてて、チャットで貼り付けるのが面倒だった。

Amazon のURLは限界まで短縮できる

AmazonのURLには短縮機能がある。

キーワードなどを削除するとASINだけになって便利。

掃除するブックマークレット

javascript:u=location.href;t="takuya-hateblo-22";a=function(url,tag){asin=function(url){if(r=url.match(/gp\/product\/([^\/]+)/)){return r[1]}else if(r=url.match(/dp\/([^\/]+)/)){return r[1]}else{return}}(url);if(asin){return"http://amazon.jp/dp/"+asin+"/?tag="+tag}else{u=new URL(url);ret=u.search.replace("?","").split(/&/);ret.unshift("tag="+tag);u.search=ret.join("&");u.hostname="amazon.jp";return u.toString()}}(u,t);

アマゾンのページをブラウジングでたどり着いたときに使うようですね。
(注意)書籍以外でテストしてない。Amazon外部の商品リンクや、AAリンクをクレンジングすることは出来ないと思う。


2014-02-22 追記。ASINページ以外のURLにも対応した


gist9141178