2013年12月17日火曜日

Delphiでのrecordの便利な使い方

こんばんは
大阪本社 Mです。

今日はDelphiでのrecordの便利な使用方法を紹介します。

record型変数をTListに格納しメンバー名でアクセスする方法です。
これだけだと何のこっちゃという感じなのでサンプルコードを見てください。

■サンプルコード■
-----------------------------------------------
type
   // record型定義
   TSyainRec = record
      社員番号: integer;
      氏名: string;
   end;

   //TSyainRecのポインタ型
   PSyainRec = ^TSyainRec;

   ・
   ・
   ・
   ・

var
   SyainList:TList;
   SyainRec: PSyainRec;
   i: integer;
begin
   // リストを生成
   SyainList := TList.create;

   // 社員番号と社員名をリストに格納
   new(SyainRec);
   SyainRec^.社員番号 := 1;
   SyainRec^.氏名 := 'シンプル 太郎';
   SyainList.Add(SyainRec);

   new(SyainRec);
   SyainRec^.社員番号 := 2;
   SyainRec^.氏名 := 'シンプル 次郎';
   SyainList.Add(SyainRec);

   new(SyainRec);
   SyainRec^.社員番号 := 3;
   SyainRec^.氏名 := 'シンプル 三郎';
   SyainList.Add(SyainRec);

   // リストに追加したrecord型変数のメンバー名でアクセス
   for i := 0 to (SyainList.Count -1) do
   begin
      Writeln('社員番号:' ,PSyainRec(SyainList[i]).社員番号);
      Writeln('氏名:' ,PSyainRec(SyainList[i]).氏名);
   end;

   // 不要になったらrecord型変数を解放する必要がある。
   for i:= 0 to (SyainList.Count -1) do dispose(PSyainRec(SyainList[i]));

   //リストも開放
   SyainList.free;
end;
-----------------------------------------------

■実行結果■
-----------------------------------------------
社員番号:1
氏名:シンプル 太郎
社員番号:2
氏名:シンプル 次郎
社員番号:3
氏名:シンプル 三郎
-----------------------------------------------

ポイントはPSyainRec(SyainList[i]).社員番号のようにすることで
リストに格納したrecord型変数のメンバー名でアクセスできるところです。

データベースから取得したデータを変数に入れて扱うときなどに
record型変数のメンバー名をデータベースの列名と同じにしておけば、
非常にわかりやすくなるのではないでしょうか。

ただしこの方法の場合、不要になったrecord型変数はいちいち
開放してやる必要がある、というのが欠点でしょうか。

いちいち開放するのはめんどくさいし忘れそう、と思うのは
私だけではないと思います。

同じようなことをするのにジェネリックのTListを利用することで
record型変数を開放する必要が無くなるようなので、
次回はその方法を調べて投稿したいと思います。

2013年12月16日月曜日

2つの単語によるgrep検索

大阪のUです。

某エディタでgrep検索しようとしたとき、
1つの単語であれば問題ないですが、2つの単語で検索しようと思うと、
間に半角空白を入れてもできません。

grepした結果に再検索すれば済む話ともいえますが、
なんとか1回で出来ないか、と考えたとき、
正規表現で簡単に出来ることに気づきました。

【正規表現】
文字列1.*文字列2

. ・・・・ 任意の1文字
* ・・・・ 直前の1文字の0回以上の繰り返し

今まで全然考えてませんでしたが、こんな簡単な記述で出来るとは。

これだけでも十分に有用ですが、
せっかくなのでもう一段階進めて考えました。

2行にまたがる2つの単語をgrep検索は出来ないのか?

プログラムやSQLを複数行にまたがって
書くことは多いからできれば検索がかなり捗る。


・・・できました。

【正規表現】
文字列1.*\n{0,1}.*文字列2

\n ・・・・ 改行
{0,1} ・・・・ 直前の1文字の0~1回の繰り返し


軽く調べてあっさり実現。
これはかなり便利なのでは。。

対象のエディタが複数行に対応してなければ
ダメかもしれませんが、使えるなら検索がかなり楽になりそうです。

2013年9月27日金曜日

Windows7向けIE11プレビュー版

が出たみたいですね。

なんというか、ブラウザの新しくなったり
種類が多い事はユーザー側にはいいことですが、
テストする開発側にとってはあまり嬉しい事じゃないです。

ちょうど先日ウェブページを作ってて
javascriptで以下のように書いたらIE8とFirefoxで
動きませんでした。

document.all.item("xxx").src = "aaa"

当初はこいつが犯人とは分からなかったんで、
しばらく悩みましたが、判れば早い。

以下のように書き換えてクリア。

document.getElementById("xxx").src = "aaa"

社内向けのシステムであれば、
ブラウザをある程度固定する事も可能ですが、
公開されていればそうも行かず。

というかIEでもバージョンがひとつ違えばもはや別物。
これでIE11でまた動かないとなったら・・・。

2013年9月19日木曜日

Delphi XE5

発売されちゃってますね、XE5。

2ヶ月ほど前にまさか年内にXE5か!?って
書きましたけど、年内どころか9月。

XE4から半年も経ってない。

製品サイクル早すぎですよ・・・

でもまぁ噂通りandroidに対応したみたいだし、
出来るだけ早くandroid対応版を出したかったって事なんですかね。

2013年8月27日火曜日

FTPのファイルロック

こんにちは。
大阪勤務のⅠです。

IISのFTPを使用したシステムでの出来事です。


●システム概要

・DBサーバ上で常時起動する。
・テキストファイルをデータベースへ展開する。

<動作>

①別PCからDBサーバ上の所定のフォルダへ、
 不定期に下記ファイルがFTP伝送される。

 (1)データファイル(固定長のテキストデータ)
 (2)伝送制御ファイル(データファイルの伝送完了を知らせる)

②アプリケーションは、DBサーバ上の所定のフォルダをタイマーで監視し、
 伝送制御ファイルが存在すれば、値を読み込む。

③伝送制御ファイルの値が「0」の場合、
 データファイルの伝送が完了していると判断し、
 データファイルの値を読み込みデータベースへ展開する。

④データ展開後は、データファイル、伝送制御ファイルともに削除する。


上記内容のアプリケーションで、下記のエラーが発生していました。

<エラー内容>

System.IO.IOException:別のプロセスで使用されているため、
プロセスはファイル'<伝送制御ファイル名>' にアクセスできません。


ちなみにエラー時は1秒後にリトライを行う仕組みになっていて、
その際には問題なく処理されていました。

はじめはウイルス対策ソフト、もしくは、レプリケーションソフトが
伝送ファイルをロックしているのかと思いましたが、
それらが原因ではないようでした。

調べてみると、どうやらIISのFTPは、
ファイル伝送開始から終了までの間ずっと、
そのファイルを読み書き禁止でロックしているようです。

つまり、データファイルの伝送完了を知らせる伝送制御ファイルが伝送中のため、
FTPのプロセスによってロックされているわけで、
ある意味どうしようもないエラーということでしょうか。

リトライ機能があるため、伝送完了後は問題なく処理されるようですが、
何か回避策を考える必要があるな…感じる出来事でした。

それでは。



2013年8月22日木曜日

正規表現でパスワード入力チェック

大阪のUです。
正規表現ってみんなどれぐらい使ってるんでしょう?

自分は正直あまり使ってません。。

使えば便利なのは判ってますが、
考えるのが面倒臭かったりするので、
プログラムで逃げたりして、なかなか使わない。。

たまに使う機会があっても、普段使ってないので、
すぐ忘れてしまう始末。

というわけで、プログラムで逃げてばっかりもアレなので
今回はちょっとパスワードの入力チェックを
正規表現でやる方法を考えてみました。

【条件】
・6文字以上であること。
・使用できる文字は半角数字、半角英小文字、半角英大文字、ハイフンのみであること。
・数字、英小文字、英大文字の混在であること。

【正規表現】
^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z\-]{6,}$


いきなり答えを書いてますが、
自分はこれの元になった正規表現を見つけたとき、
何が書いてあるか判りませんでした。

[a-z]とかは普通によく使う表現ですが、
(?=.*[a-z])となると意味不明です。


というわけで順番に調べました。

^ ・・・・・・文字列の先頭
$ ・・・・・・文字列の末尾(改行文字除く)
. ・・・・・・改行文字(\n)以外の任意の一文字(カギ括弧内除く)
* ・・・・・・直前の文字を0回以上繰り返し。({0,}と同じ)

{n} ・・・・・直前の文字をn回繰り返し
{n,}・・・・・直前の文字をn回以上繰返し

[0-9] ・・・・0~9のいずれか1文字が含まれてること。
[a-z] ・・・・a~zのいずれか1文字が含まれてること。
[A-Z] ・・・・A~Zのいずれか1文字が含まれてること。
[\-] ・・・・ハイフンが含まれてること。(※\マークは任意だがあった方が判りやすい)

ここまでは基本中の基本って感じでしょうか。
で、上記を組み合わせて↓みたいにして使うと。

[0-9a-zA-Z\-] ・・・・・0~9、a~z、A~Z、ハイフンのいずれか1文字が含まれてること。
^[0-9a-zA-Z\-]$ ・・・・0~9、a~z、A~Z、ハイフンのいずれか1文字。
^[0-9a-zA-Z\-]{3}$・・・0~9、a~z、A~Z、ハイフンのいずれかで構成された3文字。

で、問題はこいつ。

(?= )

「ゼロ幅の肯定的先読みアサーション」というらしいですが
言葉だけだと意味不明です。

色々用例を調べた感じからすると、

直後に書かれた内容が、カッコ内に記述したパターンを満たしている事を
チェックする表現らしい。


(?=[a-z])

と書いた場合はa~zのいずれか1文字。つまり、

^(?=[a-z])[0-9a-zA-Z\-]{3}$

と書くと、直後の1文字目だけは、
(?=[a-z])の条件を満たしている必要があり、a~z以外の文字は×となる。

例)
×1aA
○aA1

この例だと1文字目だけが条件の対象だが、
以下のように書き換えると全体に対して有効になる。

^(?=.*[a-z])[0-9a-zA-Z\-]{3}$


(?=.*[a-z])は
任意の文字が0文字以上繰り返された後にa~zのいずれか1文字、
つまり文字列のどっかにa~zのいずれかがあることを意味するので、

”a~zのいずれかを含む”、0~9、a~z、A~Z、ハイフンのいずれかで構成された3文字となる。

例)
○1aA
×12A

そして、これを応用すると、
最初の答えにたどり着く。

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z\-]{6,}$"

”0~9のいずれかを含む”かつ
”a~zのいずれかを含む”かつ
”A~Zのいずれかを含む”、
0~9、a~z、A~Z、ハイフンのいずれかで構成された6文字以上の文字列。


う~む、今まで簡単な正規表現しか使ってなかったですが、
一行でここまで出来るとは。
まだまだ色々記述方法があるようだし、なかなか奥が深いです。


ただ、問題はみんなが理解してないと、
あとから見た人が判らない事ですかね・・・
プログラムと違って、なんとなくじゃ読めないし。

2013年7月11日木曜日

Delphi XE4

大阪のUです。

なんかいつの間にかDelphiのXE4が出てます。。

Delphi XE3が出たのは去年だったような気がするんですが、
気のせいでしょうか。

今回の目玉はiOSのネイティブアプリ作成が出来るように
なったことみたいですが、機能的にはXE2からあったような。。

iPhone向けのアプリが気軽に作れるのは
いい感じですけど、結局Mac環境がいるんじゃ
まだハードルが高い。

まぁiPhone持ってないですけどね。


年末にはandroidにも対応するという噂もあるようですが、
まさか、Delphi XE5!?
ちょっと早すぎるんじゃ・・・

2013年6月26日水曜日

Delphiでの64bitアプリのデバッグ方法

大阪本社所属 Mです。

64bitの環境が普及し64bitアプリ開発の機会も増えてきた今日この頃
Delphiで64bitアプリのデバッグを行うためにはちょっとした準備が必要なので
その手順を投稿します。

Delphi自体は32bitアプリなので64bitアプリのデバッグは64bitリモートサーバと
通信して行うようです。DelphiのバージョンはXE3です。

①PAServer(プラットフォームアシスタントサーバー)のインストール

・ インストーラは setup_paserver.exe で、Delphiインストールディレクトリの
   PAServer フォルダ内にある。デフォルトでは以下の場所。

   C:\Program Files\Embarcadero\RAD Studio\バージョン番号\PAServer\setup_paserver.exe

・ setup_paserver.exe を実行してPAServerをインストール。
   UACがらみでC:\Program Files 以下ではないディレクトリにインストールすること!


②リモート プロファイルの準備

・ Delphiを起動し ツール→オプション→環境オプション→リモート プロファイルを選択
   [追加] ボタンを押してプロファイルを追加。




















・ テストプロファイル名(任意)を入力し、プラットフォームは 64ビット Windows を選択。


















・ 次の画面で接続先のホスト名またはIPアドレスを指定する
   ローカルでリモートデバッグを行う場合はループバック IP 127.0.0.1
   もしくはlocalhostと入力する。

   ポート番号はデフォルトの64211、パスワードは空白でOK。


・ 次の画面のC++情報は入力不要。


③ローカルルートディレクトリの指定

   「リモートデバッグ用のファイルが格納される場所」らしいが
   デバッグ時にも何も出力されないので何のための設定かよくわからない。
   ただ、設定しないとデバッグできないので設定する。
   ドロップダウンから選択できる。




















④リモートプロファイルの割り当て

・ プラットフォーム"64 ビット Windows "を右クリックして
   "リモート プロファイルの割り当て" を選択。




















・ 作成した 64bit Windows 用リモートプロファイルを選択。






















⑤デバッグの実行

・ PAServerの起動
  PAServerインストールディレクトリのpaserver.exe をダブルクリック、
  またはcmd.exeでPAServerインストールディレクトリに移動し「paserver」と入力してEnter。
  パスワードの入力が求められるので、そのままEnter。

















  これでアプリケーションを Debugでビルドした後、通常の32bitデバッグ時と同じように
  64bitアプリをデバッグできる。

  PAServerインストールディレクトリの"\scratch-dir" 以下に
  アプリケーションが出力され実行される。

  dllなどアプリ起動に必要なファイルがある場合は手動で実行ディレクトリに
  コピーが必要なので注意。




以上で手順の説明は終了です。

2013年2月25日月曜日

Windows7へのOracle10gインストール

Windows7へOracle10gインストールする場合、
「Oracle Database 10g Release 2 Client (10.2.0.3)」を使えばすんなりインストールできる。

・・・はずだったんですが、まったくインストールできず。

あらゆる常駐ソフトを終了させ、邪魔をしてそうなアプリをアンインストールしても
まったくできず。

最初のsetup.exeをたたいたあと、DOS窓が出たところで終わってしまう。。

まったく原因不明であきらめかけたところ、
ログファイルをよくよく見ると、dllの名前が書いてる。

ググって見るとディスプレイドライバ??
関係あるのか?と思いつつ、ドライバを最新にするも、やはり結果は一緒。

しかし、ここでふと気がつく。
まさか・・・USB接続のディスプレイアダプタのせい!?(←2面使うため)

USBを抜いてみると、、あっさりインストールできましたorz


Oracleをインストールするのに、こんなものが邪魔をするとは。。

2013年1月8日火曜日

SPOOLの罠【ORACLE】

こんにちは、大阪本社勤務のIです。

前回と同様ORACLEに関することなのですが、
今回はOracle8iとOracle10gの差による、
ちょっとした躓きがありましたので投稿します。

前回お話したとおり、現在、僕が携わっているシステムは、
メインのシステムのデータベースがOracle10g、
サブのシステムのデータベースがOracle8iです。

データの更新はサーバ上でコマンドプロンプトから
SQL Plusを起動して行うのですが、
その際に「SPOOL」コマンドを使用して、
処理内容をファイルに出力し、ログとして残す決まりになっています。

また、メインのシステムはデータ更新の機会が比較的多いのですが、
サブのシステムはデータ更新の機会はほとんどありません。

そんな中、先日サブのデータ更新を行うことになり、
いつもメインで入力しているとおり、
SPOOL "○○○○.LOG" ←と入力しENTERキーを入力すると、
「SP2-0332: スプール・ファイルを作成できません。」と表示されます。

ディレクトリに書き込み権限がないのか?
…などと、いろいろ試みてみましたが、状況は変わりません。

困って上司に尋ねたところ、Oracle8iではファイル名をダブルクォートで囲うと、
このエラーが発生するとのことでした。

その後
SPOOL ○○○○.LOG ←と入力しENTERキーを入力すると、
何事も無かったかのように、ファイルが出力されました。

知っていればどうってことない話ですが、
普段当たり前のように使っていた「SPOOL」コマンドで、
まさかこんな罠があるとは…といった感じでした。

ではまた次回。

スナップショットの罠【ORACLE】

こんにちは、大阪本社勤務のIです。

開発ブログということで、簡単ではありますが、
自分が開発時につまづいた内容などを投稿していきたいと思います。

現在、僕が携わっているシステムは、
メイン(仮にシステムAとします)のシステムがOracle10g、
サブ(仮にシステムBとします)のシステムがOracle8iで、
それぞれにデータベースが存在します。

また、システムA、システムBにて共通のテーブルがいくつかありますが、
夜間処理にて、システムAとシステムBの内容の同期をする仕組みになっています。

最近システムAで、あるテーブルのデータを日中に変更する必要があり、
システムAのデータを変更後、システムBに反映しようとしました。

手順としては、

①システムBのテーブルのデータを全件 DELETE する。

②データベースリンクを使用し、システムAのテーブルから SELECT し、
  システムBのテーブルに INSERT する。

…と考えていましたが、①を実行すると
「ORA-01732: このビューに対するデータ操作が無効です。」のエラーが出て、
データが削除できませんでした。

テーブルなのにビュー?…と思い、調べてみた結果、
システムBには、テーブル名と同名のスナップショットが存在していました。

□■□■□■□■□■ 調査メモ ■□■□■□■□■□
スナップショットとは、Oracleデータベース間で、データのバックアップを取る機能である。
スナップショットを作成すると、スナップショットと同名のテーブルが作成される。
そのテーブルに対して直接操作するには、スナップショットを作成する時に、
FOR UPDATE句を指定しないといけない。
スナップショットを同期するには下記のメソッドを使用。
DBMS_SNAPSHOT.REFRESH('スナップショット名','リフレッシュ方法')
リフレッシュ方法の内容
'F' ⇒ 高速リフレッシュ
'C' ⇒ 完全リフレッシュ
'?' ⇒ 強制リフレッシュ
'A' ⇒ 常にリフレッシュ
□■□■□■□■□■□■□■□■□■□■□■□■□

どうやらスナップショットが更新可能でなかったため、
DELETE 時にエラーが発生していたようです。

その後、当初考えていた手順ではなく、
DBMS_SNAPSHOT.REFRESH を実行することでテーブルの同期を行いました。

今回、スナップショットについて理解が乏しかったため、
このような現象に躓きましたが、良い勉強になりました。

この先、このようなことがあれば、投稿していきたいと思います。

2013年1月7日月曜日

ちょっとしたことで

こんにちは。
大阪本社勤務のMです。

今回初めてブログに記事を投稿します。
どうぞよろしくお願いします。

さて、今回はメールに関するちょっとしたテクニックを紹介します。

皆さんも仕事やプライベートでメールを送信する機会は多いと思います。
そして、メールでは返信期限を設定することがよくあります。
しかしその返信期限をメールにしっかり明記しているにもかかわらず
期限が過ぎてもちっとも返事が来ない…なんて経験ありませんか?

そんな時に役立つテクニック、それは

返信期限は日付だけではなく、具体的な時間まで指定する。

例えば
「○月×日 18:00までに返信お願いします。」
のように書くことで、期限までに返信が来る割合が3割もアップするのです。

ちょっとした工夫で、返事が来ないイライラを感じずに済むなら
やってみる価値ありですね!