データベース向けのテストデータを簡単に作るために、
必要となったので、作ってみた。

  1.  
  2. use strict;
  3. use Time::Local qw( timelocal );
  4.  
  5. #2005年から2012年の間のランダムな日時を作成
  6. #2005年1月1日 00:00:00
  7. my $start_date = timelocal( 0, 0, 0, 1, 0, 105 );
  8. #2012年12月31日 23:59:59
  9. my $end_date = timelocal( 59,59,23,31,11,112 );
  10.  
  11. #$start_dateと$end_dateにはエポック秒数が入っている
  12.  
  13. for( 1..2000 ){
  14.     #ランダムな日付を取得
  15.     my $time = $start_date + int( rand( $end_date - $start_date ) );
  16.     #日付の形式に戻す
  17.     my ( $sec, $min, $hour, $mday, $month, $year, $isdst ) = localtime( $time );
  18.    
  19.     #日付の補正
  20.     $year += 1900;
  21.     $month++;
  22.    
  23.     #文字列整形
  24.     my $date_str = spirntf( "%d-%02d-%02d %02d:%02d:%02d",
  25.                             $year, $month, $mday, $hour, $min, $sec );
  26.  
  27.     print "$date_str\n";
  28. }
  29.  

ちょっと値を書き換えれば、ランダムな日時を取得することができる

久々にMacを触ったら「objc_class_nameクラス名」というエラーに引っかかった。
OS 10.6 XCode 3.2のお話です。

開発環境のマシンが変更になっていたので、
昔のソースを引っ張ってビルドしてみたら、こんなエラーで引っかかった。

とりあえず分からなかったので、調べてみたところ
こちらのサイトを見てみた。
iPhoneメモ “.objc_class_name_クラス名”, referenced from:

なるほど、いらなくなったソースを消すと出やすいのか。
まずは、クリーニングということで、やってみたが、
事態は一向に変わらず。。。

まずはリンクが怪しいということで、
自作のFrameworkをクリーニング、再ビルド。

Frameworkを一度削除し、再度新規に登録。
クリーニングを行い、再度ビルド。

まだダメ。

これは、もうクリーニングではないなということで、
設定を再度見直し。
#そもそもソース削除してないし。。。

ターゲットのLink Binary With Librariesの中を見ると、
なんとCocoaとCarbonがないではないか。
そりゃ動かんよ。

そこにCocoaとCarbonを移し、ビルド。
うまく行ったと思いきやまた同じエラー(クラス名が違う)

再度、設定を見直すと、
ターゲットの「ソースをコンパイル」の部分に
エラーになったクラスのソースが含まれて無いじゃん!

ということで、そこに目的のファイルを入れたら、
無事動きました。

久々だったので、いろいろ対処を忘れちゃいました。

以前書いた「LWP::UserAgentを使ってHTTPアクセス」
では、Webに公開されているコンテンツにアクセスするためのもの。

今回は、そのURLが正常、転送される、存在しない、エラーなのかを
判断が必要な場合に使用するためのもの。

LWP::UserAgentで普通に書くとHTTPレスポンスが転送の場合、
自動的に転送してくれて、実際のコンテンツにありつけることができる。

ただ、転送してほしくないケースもあるかと思う。
例えば、画像ファイルが存在しない場合に、ブラウザで見ると、
画像が置き換わっているように見え、存在しないことは分かるが、
それは人の目で判断しているのであって、プログラムは判断していない。

そこで、今回はそのURLが正常なのかどうかを判断するものを
作ったので、メモ。

HTTPレスポンスコードについては、
Studying HTTPを参照させていただいた。

  1.  
  2. use LWP::UserAgent;
  3.  
  4. sub check_http_status{
  5.   my $url = shift;
  6.  
  7.   my $ret;
  8.  
  9.   my $ua = LWP::UserAgent->new;
  10.   #タイムアウトの設定
  11.   $ua->timeout(10);
  12.  
  13.   #エージェントの設定
  14.   $ua->agent();
  15.  
  16.   #リクエストの作成
  17.   my $req = HTTP::Request->new(HEAD => $url);
  18.  
  19.   #リファラーを設定
  20.   $req->referer();
  21.  
  22.   #リクエスト実行
  23.   my $res = $ua->simple_request($req);
  24.  
  25.   #結果判断
  26.   if ($res->is_success) {
  27.     $ret = 1;
  28.   }else{
  29.     $ret = 0;
  30.   }
  31.   #実際のレスポンスコードが欲しい場合は、↓
  32.   print $res->code; #レスポンスコードを表示
  33.   #で取得することができる
  34.  
  35.   return $ret;
  36. }
  37.  
  38.  

ポイントは、simple_requestというメソッドを使うこと。
これを使うことによって、転送レスポンスコードを取得することができる。
#LWP::UserAgentのrequestメソッドは、このsimple_requestメソッドを転送等の場合、
#何回か呼び出しを行っている模様

リクエストで「HEAD」としたのは、コンテンツではなく、URLに対するサーバ側のレスポンスコードが重要だったので、
転送量を抑えるために、HEADとした。

これで、実際のURLが正常(200番代)かどうかが分かるようになった。

新規で起こしたサイトのグーグルのサイトマップを作成したいと思い、
Perlで組んでみた。

CGIのパラーメータが入っているURLの登録を行おうとしたときの注意点があったのでメモ

まず、XMLで書く場合は、CGIのパラメータの&をエスケープする必要がある。
「&」⇒「&」としなくてはならない。
また、日本語(非ASCII文字)に関してもURLエンコードをかける必要がある。

このことに注意しながら、HTML::Templateを使って簡単にクエリを作成、
サイトマップに登録することができた。
#登録したばかりなので、どのくらいでインデックスされるかはわからないんですけど。。。

urlエンコードの掛け方

  1.  
  2. use URI::Escape;
  3.  
  4. my $str = "非ASCII文字列";
  5. my $encoded_str = uri_escape($str);
  6.  

週単位で件数やある値の合計値、平均値等を取りたい場合のやり方。

例えば、以下のようなテーブルがあった場合以下のようになる
TabelA
——————
id primary
date1 datetime
size int
——————

週単位での件数を取得する

  1.  
  2. SELECT CONCAT(YEAR(date1),"/",lpad(WEEK(date1),2,0),"w") as week,
  3.        COUNT(*)
  4. FROM TableA
  5.  

解説:
 YEAR関数:引数の日付の年の部分だけ取得 ’2012-10-30 00:11:22′だったら”2012″
 WEEK関数:引数の日付の最初の日曜日から何週目か 
 lpad関数:左埋めをしてくれる関数(値,桁数,埋める文字)
      例えば(1,3,’0′)とすると001となる
      ORDER BYでうまくソートするために使用

 GROUP BY句で連結した週単位の文字列でグルーピングすることによって
 週単位の集計が行える

合計値を出力

  1.  
  2. SELECT CONCAT(YEAR(date1),"/",lpad(WEEK(date1),2,0),"w") as week,
  3.        SUM(size)
  4. FROM TableA
  5.  

SQLが微妙だったので書き換え(2012-12-12)

いろいろ応用が利きそうな書き方ですね。

1位:C言語
  これは、最初にプログラミングを習ったときに使った言語。
  最初はポインタって???
  構造体とは???
  という感じだったのを思い出した。
  
  非常にサンプルも豊富、どこでも使えるということからまだまだ
  使用されている言語なんだなと思う。

2位:Java
  ちょろっとだけかじったことのある言語。
  最近では、めっきり見なくなったけど、
  アプレットとか作ったなぁ。

3位:Obective-C
  すごいやはりiphone効果だ。
  Objective-Cを私が触り始めたのは、2006年。
  まだTigerの時代だったからなぁ。

  最初この言語を触り始めたときは、文法に戸惑った。
  本当に戸惑った。オブジェクトを使用するときは、[]で囲まなきゃならないし、
  わけがわからなくなった。
  
  当時のInterfaceBuilderとXCodeの繋ぎ込み方もわからなかった。
  それまでは、ボタンクリックするとメソッドがかけるような環境でやっていたから
  それができないことに1ヶ月歯痒く思っていた。
  でも、その1ヶ月を過ぎると慣れちゃえば、
  書きやすい言語だし、逆にWindowsの開発環境の方が
  使いづらいとまで思うようになってしまった。
  #まぁ、あのときは、ずっとMacだったからかな。

4位:C++
  やったことないです・・・

12位:Delphi
  この言語は書き方がかなり厳密に書かなきゃだめだったから
  慣れるまで大変だった。
  
  ただ、コンパイルの速度は異常に早い。
  Delphiに関していうと、dllが内包されるので、
  当時VB6.0で作られたアプリのように
  ランタイムが必要なアプリがあったが、
  ポンと渡して動くアプリが必要だったので、
  この環境で開発したなぁっと。

  .NETに対応しているDelphiは触ったことがないけど、
  それなりに使っている人がいるんだなぁとちょっとうれしい。

また、気になったら続きを書こうっと

ファイルがエイリアスかどうかを判断する必要がある場合に、
NSFileManager経由で、attributesを取ったところで、
取得できない。
シンボリックリンクかどうかはattributeのNSFileTypeがNSFileTypeSymbolicLinkかどうかで
取得することができる。
#Finderで見ると、同じアイコンなので紛らわしい。。。

そこで、CoreServicesのCarbonCoreにあるAlias.hの
FSIsAliasFileを使って判別することにする。
NSFileManagerのカテゴリとして実装

  1.  
  2. -(BOOL)isAlias:(NSString*)path{
  3.         BOOL returnValue = NO; //返戻値
  4.         FSRef fsref;
  5.         Boolean isAlias, isFolder;
  6.        
  7.         if( [ self stringPathToFSRef:path fsRef:&fsRef ] &&
  8.                 noErr == FSIsAliasFile(&fsref, &isAlias, &isFoder ) ){
  9.                 returnValue = isAlias;
  10.         }
  11.        
  12.         return returnValue;
  13. }
  14.  
  15. -(BOOL)stringPathToFSRef:(NSString*)path fsRef:(FSRef*)outRef{
  16.         BOOL returnValue = NO;
  17.        
  18.         OSStatus err = FSPathMakeRef((const UInt8*)[ path fileSystemRepresentation ] , outRef, NULL );
  19.        
  20.         if( err == noErr ){
  21.                 returnValue = YES;
  22.         }
  23.        
  24.         return returnValue;
  25. }
  26.  

これで、パスのファイルがエイリアスかどうかわかった。

対象環境:MySQL4.1以降

テスト環境で、テーブルを作成しそのテーブルを
本番のテーブルに流し込みたいが、
本番に入っている既存のデータには手を入れたくない場合のやり方。

勿論、テスト環境で差分だけ本番に持っていって、
INSERTすればいいのだが、レコード数が多いと、
なかなかめんどーだなと思ったので、
良いやり方がないか調べてみた。

TableAにはすでにデータが入っているが、
追加で何行か追加する場合

1.一時的にテーブルを作成
–TableAの構造のみコピー
CREATE Table TmpTableA LIKE TableA;

2.TmpTableAに対して、テスト環境のデータをINSERT
— 今回は、テスト環境からmysqldumpでsqlを出力したものを使用
— dumpしたSQLから必要のない行を削除したり、テーブル名書き換えたり等行う

3.sql流し込み

4.テーブル同士の差分を取得し、それをTableAにINSERT

  1. INSERT INTO TableA
  2.   SELECT * FROM TmpTableA
  3.       SELECT * FROM TableA WHERE
  4.          TableA.id = TmpTableA.id );
  5.  

これで、TmpTableAに入っていて、TableAに入っていないものが、
TableAにINSERTされる。

SELECT句だけを再度実行して、検索件数が0件なら、
すべてINSERTされたことになる。

なにかの操作をしていて、急にかな入力になってしまう場合がある。
そして、戻し方を忘れてしまうので、メモ
ただし、BootCampでWindowsを起動しているMacが対象

Alt+かな(スペースの右隣)

「KA」と入力したいのに「のち」になったときはイラっとする。。。

覚えておこう

実データを操作するプログラムを作るときに、必ずといっていいほどパスの結合を行う。
そんなときに、使うメソッドは、System.IO.Path.Combine(path1,path2)で
path1とpath2を結合して、ファイルパスとして生成してくれる。
こんな感じ

  1.  
  2. string path1 = @"C:\test\subtest\";
  3. string path2 = "test.txt";
  4. string filePath = System.IO.Path.Combine(path1, path2 );
  5. //filePathには"C:\test\subtest\test.txt"という値が入る
  6.  

非常に便利だが、
path2の先頭が\だと、予想外の動きに。。。

  1.  
  2. string path1 = @"C:\test\subtest\";
  3. string path2 = @"\test.txt";
  4. string filePath = System.IO.Path.Combine(path1, path2 );
  5. //filePathには"\test.txt"という値が入る
  6.  

検索してみるたら、参考になる記事を発見
【C#】パスが結合できない

さらに
MSDNでしらべてみたところ、こんな記述が

“path2 にルートが含まれていない (たとえば、path2 が区切り記号またはドライブ仕様で始まらない) 場合は、間に区切り記号が入った 2 つのパスの連結が返されます。 path2 にルートが含まれている場合は、path2 が返されます。 ”

つまり、区切り文字「\」から始まると、ルートと判断されて、path2だけが帰ってきてしまうのですね。。。
ちゃんと読まないとだけど、エラーとかにして欲しいかも。。。