2013年12月24日火曜日

コマンドプロンプト ファイルリダイレクト

バッチひとつでコンソール形式の実行ファイルを開いてそこにコマンド流し込む。

/*---------------------------------------------------------------------------*/
$ hoge.exe
hoge> command;
/*---------------------------------------------------------------------------*/

上みたいな処理をバッチファイルに書いたら、
exeを実行するとexe用のコンソールが起動してそこで止まった。
そのコンソールを終了すると続く処理は実行されるんだけども、当然のごとくエラー。
どうにかできんのか、と思って調べてみたら、
コマンドプロンプトにはファイルリダイレクトという機能があるようだ。

参考サイト

コマンド部分を別のファイルに記述して保存。ここではhoge.commandとしておく。
そしてバッチファイルには以下を記述。

/*---------------------------------------------------------------------------*/
$ hoge.exe < hoge.command
/*---------------------------------------------------------------------------*/

これでhoge.commandの中身がhoge.exeに渡されてコマンドが実行される。

2013年12月20日金曜日

C# 定数

C#をやっていると、たまにメンバの定数ってどう宣言すんだっけ? となる。ぼけか?
とにかく、もうそんなことにならないためにメモ。

参考サイト
定数(C# によるプログラミング入門) - ++C++

メンバの定数を定義するためには、constとreadonlyの2つの方法がある。

/*---------------------------------------------------------------------------*/
private const int PI = 3.14;
private static readonly int PI = 3.14;
/*---------------------------------------------------------------------------*/

2つの違いは以下の通り。参考サイトからまるっとコピー!

constreadonly
ローカル変数にも使えるクラスのメンバー変数のみ。
常に静的変数と同じ扱い。static の有無を変えられる。
宣言時にのみ初期化可能。コンストラクタ内で値を書き換え可能。
コンパイル結果はリテラルと同等。コンパイル結果は変数と同等。
インスタンスを new で生成するようなものには使えない。new 可能。

ああ、bloggerのコピペするとhtml構文もコピーする機能ってこのためなのか。いまさら知った。

constは扱いがリテラル(直接記述したデータ。コンパイル時に値が展開される)なので、
バージョニング問題というものが発生するらしい。
constなデータを外部で参照している場合、コンパイル時に参照側も再コンパイルしないと、
値が変化しない現象。
privateなメンバ、ソースコード内からしか参照されない値なら問題ない。



まとめとして、privateな定数ならconst、publicな定数ならreadonlyを使用するのが無難っぽい。

2013年12月18日水曜日

php BLOB型を使ってみる

phpってバイナリ操作するためのものないのん? と思っていたらあった。
MySQLのBLOB型というやつとphpのgmp関連のメソッドを使う。

参考サイト
BLOB型とTEXT型
PHP: GMP 関数 - Manual

使用する上でやったことをいくつかメモ的に残しておく。

MySQL:BLOB型のデータを初期化する


バイナリデータを全部初期化したり、新しい行を挿入したりするときに使った。
BLOB型はデフォルト値が設定できないようなので、多分知らないと困る。

/*---------------------------------------------------------------------------*/
INSERT INTO hoge (blob_data) VALUES ("");
UPDATE hoge SET blob_data = "";
/*---------------------------------------------------------------------------*/

空の文字列を渡してやると、空のバイナリデータとして初期化される。
NULLを渡すと中身がNULLになるので注意。

PHP:BLOB型のデータを取得する


phpでデータを取得するときは、バイナリデータを文字列に変換。
さらにそれをgmpのデータに変換して取得する。

/*---------------------------------------------------------------------------*/
$gmpData = gmp_init(bin2hex($blobData), 16)
/*---------------------------------------------------------------------------*/

16進数のデータで受け取る例。他には10進数、8進数が使用可能。
まあ、基本16進数でいいやと思って試してはいない。

PHP:ビットを操作する


/*---------------------------------------------------------------------------*/
gmp_setbit($gmpData, $index, $set);
/*---------------------------------------------------------------------------*/

indexは調べたいビット。setはオンにするならtrue。オフにするならfalseを渡す。

PHP:ビットを取得する


/*---------------------------------------------------------------------------*/
gmp_testbit($gmpData, $index);
/*---------------------------------------------------------------------------*/

MySQL:PHPで操作したデータを更新する


取得したときとは逆に、16進数のデータに変換して、さらにバイナリに変換する。

/*---------------------------------------------------------------------------*/
$hex = gmp_strval($gmpData, 16);
$data =  hex2bin($hex);
/*---------------------------------------------------------------------------*/

gmp_strvalで変換できる。
hex2binに渡すときは、文字列データの長さが偶数じゃないと起こられるので気をつけよう。

以上。思っていたより長くなった。

2013年12月13日金曜日

C# CSVファイルを読み込み

なんてこったい。C#ではCSVファイルを読み込むのが超簡単ではないですかい。

参考サイト
CSVファイルを読み込むには?[2.0のみ、C#、VB]
TextFieldParser クラス (Microsoft.VisualBasic.FileIO) - MSDN

Microsoft.VisualBasic.FileIO名前空間のTextFieldParserというクラスを使用する。

/*---------------------------------------------------------------------------*/
TextFieldParser parser = new TextFieldParser("hoge.csv");
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData) {
   string[] row = parser.ReadFields();
}
/*---------------------------------------------------------------------------*/

これだけでオーケーさ!
処理としてはコンストラクタでファイルを読んで、フィールドの分割方法をデリミタに指定。
さらにデリミタをカンマに指定してループで最後まで読み込んでいる。
今回はCSVファイルだけど、調べてみたら色々なデータ構成に対応できそう。

今まで自力で実装してきたのはなんだったのやら。

C# アプリケーションを64bitOS上で32bitモードで動かす

以前作成したアプリケーションがwindows7上だと動かないという問題が発生した。

/*---------------------------------------------------------------------------*/
間違ったフォーマットのプログラムを読み込もうとしました。
(HRESULT からの例外: 0x800xxxxx)
/*---------------------------------------------------------------------------*/

こんなエラーが出る。
どうやらアプリケーションが64bitモードで動いているのが原因らしい。
使用しているdllが32bit環境のものだったので、それを読み込めないと怒られているようだ。

参考サイト

回避方法のひとつとして64bitOS上でも32bitモードで動かすというのがあったのでやってみた。
Expressを使用していたので、上記サイトで紹介されている方法は使用できない。
探してみたら、Expressでやる方法があったのでそちらを試す。

参考サイト
  1. メニューの「ツール(T)」から「オプション(O)」を開く。
  2. 左下の方にある「すべての設定を表示(A)」にチェックを入れる。
  3. 追加された「プロジェクトおよびソリューション」項目に移動。
  4. 「全般」の中にある「ビルド構成の詳細を表示(I)」にチェックを入れる。
  5. メニューの「ビルド(B)」から「構成マネージャ(O)」を開く。
  6. 「アクティブソリューションプラットフォーム」で「新規作成」。
  7. x86の項目を作成する。
以上。これでビルドしたら64bitOS上でも動いた。
よかったよかった。

2013年12月12日木曜日

SQLite csvデータをインポートする

これといって難しいことはないけど、ちょっとだけつまずいたのでメモる。

参考サイト
sqlite3 に CSV形式のデータを突っ込む

/*---------------------------------------------------------------------------*/
$ sqlite3 -separator , hoge.db ".import hoge.csv hoge"
sqlite> .import hoge.csv hoge
/*---------------------------------------------------------------------------*/

上がコマンドラインから直接突っ込む方法。
下がSQLiteを起動してからインポートする方法。
今回つまずいたのはSQLiteを起動してからのほう。

SQLiteはデフォルトのセパレータが"|"になっている。で、CSVは","区切り。
セパレータを設定してからインポートしてやろう。

/*---------------------------------------------------------------------------*/
sqlite> .separator ,
/*---------------------------------------------------------------------------*/

2013年12月11日水曜日

android-ndk stlを使う

せっかくC++でやるので、AndroidNDKでstlを使ってみた。

参考サイト
Android NDKが標準で備えるSTLを利用する
Android NDKでJNIを使用してアプリを高速化するには (2/3)

やり方は簡単で、Application.mkにstlを使うぞ、と教えてやるだけでいい。
これはstaticライブラリとして使用する例。

/*---------------------------------------------------------------------------*/
APP_STL := stlport_static
/*---------------------------------------------------------------------------*/

Application.mkは名前そのままで、アプリケーションの定義を行うファイルらしい。
今回はjniフォルダの直下に新しいApplication.mkを作成した。

2013年12月10日火曜日

CakePHP2.x ヘルパーでコンポーネントを使用する

MVC的に正しいのかどうかは置いておいて、ヘルパーでコンポーネントを無理やり使った。
他のページを見ると、自分でnewして使用するのが一般的(?)みたいだけど、
正直コントローラがすでに生成しているオブジェクトをわざわざnewするのもどうかと思ったので、
ClassRegistryに格納した。

コントローラ側の処理
ClassRegistryにコントローラが持っているHogeコンポーネントを追加。

/*---------------------------------------------------------------------------*/
ClassRegistry::addObject( "Hoge", $this->Hoge );
/*---------------------------------------------------------------------------*/

ヘルパー側の処理
ClassRegistryからコンポーネントを取得して使用する。

/*---------------------------------------------------------------------------*/
$hogeComponent = ClassRegistry::getObject( "Hoge" );
$hogeComponent->hogeru();
/*---------------------------------------------------------------------------*/

処理として正しいのかどうかは置いておいて、これでヘルパーからコンポーネントが使える。

2013年12月9日月曜日

android-ndk jniを使う

以前書いたndkのインストール及びテストの記事で最後のほうに空のプロジェクトが動いた、
とか書いたけど、改めて見直したら自分でもさっぱりなにをどうしたのか分からなかったので、
改めて適当なプロジェクトを作ってテストしてみた。

参考サイト
Android NDKを使った開発環境の構築

空のプロジェクトを作る


まずは環境だけが整ったプロジェクトを作る。
  1. メニューからAndroidApplicationProjectを作成する。
  2. プロジェクトを右クリック。「Androidツール」から「Add Native Suport」を選択
  3. 任意の名前を付けて「完了」。
これで環境だけが整った空のプロジェクトが完成。

jniファイルとの連携用のクラスを作成する


参考サイトではMainActivityに直接書き込んでいるけど、後述のjavahを使ったときに怒られた。
可読性もろもろのためにもネイティブと連携するファイルは個別にするのがいいと思う。

/*---------------------------------------------------------------------------*/
public class HogeJNI {
statis {
System.loadLibrary("hoge");
}
public static native void fuga();
}
/*---------------------------------------------------------------------------*/

System.loadLibraryには呼び出すsoファイルの名前を指定する。
C/C++のファイルと同じ名前になると思う。

C/C++のヘッダファイルを作成する


自分で打つと失敗する可能性大なので、jdkのjavahコマンドを使う。
コマンドプロンプトでプロジェクトのルートフォルダに移動して、以下のコマンドを実行。

/*---------------------------------------------------------------------------*/
$ javah -o jni/hogejni.hpp -classpath bin/classes com.example.test.HogeJNI
/*---------------------------------------------------------------------------*/

-oに出力先、-classpathに参照するクラスパス。最後が対象クラス。
詳しいことは参考サイトを見よう。
これでファイルが作成された。しかし、手動でインポートしないといけないの?
リフレッシュしてもいつまで経っても表示されないんだけども。

C/C++のソースファイルを作成


javahコマンドで作成したヘッダファイルをインクルード&そのまま使える部分をコピーして
ソースファイルに書き込み。
そのままコピペすると変数名を忘れる。
少なくとも自分は忘れた。30分以上、それに気づかず無駄にした。
C/C++側のエラーは感知してくれないんかね?

あとは必要なところでネイティブメソッドを呼び出せば動くはず。

2013年12月7日土曜日

android 開発環境は最新に保つのがいいらしい

android-ndkを本腰入れてやろうかと思って新しいプロジェクトを作ったら、エラーが出た。

/*---------------------------------------------------------------------------*/
[2013-12-07 16:37:59 - Dex Loader] Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.
[2013-12-07 16:37:59 - hoge] Conversion to Dalvik format failed: Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.
/*---------------------------------------------------------------------------*/

なんでも、新しめの環境で古いビルドターゲットを指定すると起こるエラーらしい。

参考サイト
Android SDK をアップデートしたら BufferOverflowException が出るようになった

でも、ターゲットバージョンが古いやつならビルドバージョンも合わせようと思うのが普通では?
なんて思った。

2013年12月3日火曜日

php DateTimeなんてあったのね

phpで時間を求めるときに今まではdateとかtimeとかを使っていた。
が、php5.2だか5.3以降はDateTimeオブジェクトなるものが用意されているらしい。
2038年問題も解決されているようで、こちらを使ったほうが後々都合がよさそう。
というわけで使ってみた。

参考サイト
PHP 5.3 の DateTime オブジェクト関連の便利な新機能

現在時刻


/*---------------------------------------------------------------------------*/
$now = new DateTime();
/*---------------------------------------------------------------------------*/


文字列から時刻を求める


/*---------------------------------------------------------------------------*/
$time = new DateTime("2013-12-03 04:00:00"););
/*---------------------------------------------------------------------------*/

いくらか足した時間を求める


/*---------------------------------------------------------------------------*/
$interval = DateInterval::createFromDateString("+1 days");
$time = date_add( $updated, $interval );
/*---------------------------------------------------------------------------*/

DateIntervalオブジェクト相対的な日付を求めるために使用するオブジェクトだそうな。
コンストラクタに指定書式の文字列を渡すか、createFromDateStringを呼び出して、
strtotime見たいな使い方ができる。

date_addは読んで字のごとく。オブジェクトのメソッドにもaddがあるのでそっちを使ってもいい。

/*---------------------------------------------------------------------------*/
$time->add( $interval );
/*---------------------------------------------------------------------------*/

比較


/*---------------------------------------------------------------------------*/
$time == $now
$time < $now
$time > $now
/*---------------------------------------------------------------------------*/



他にも色々あるので、そちらは参考サイトや公式のマニュアルを参考に。
個人的には比較が楽でいい。