趣味としてのプログラミングの楽しさ

こんにちは!
技術ブログで記事を書かせていただいている伊東です。

今回は一休みということで、趣味としてのプログラミングの楽しさについて語っていきたいと思います。


プログラミングが趣味と言うと、一握りのギーク(卓越した技術を持つコンピュータ好き)だけが楽しめる趣味なのではと思われるかもしれません(私もそう思ってました)が、そうではありません。初心者からでも楽しむことができる趣味です。
初心者でもブログ等で記事を発信することができますし、身の回りのことでちょっとしたプログラムを作ると便利になったりもします。

私の例ですが、以下のように休日もプログラミングを楽しんでいます。

1.ブログを通した情報発信

私は、このブログと、もう少し軽めの記事を扱う個人ブログの2つのブログを持っています。

個人ブログの方では、開発していてつまづいたエラーとその対処法を書くだけの簡単な記事も備忘録代わりに載せていますが、そのような記事にも他の記事と変わらないくらいのアクセス数が来ています。
エラーとその対処法を載せるだけなら初心者でもできます(むしろ初心者の方がそういった記事は書きやすいかもしれません)。
自分がつまづいた箇所は他の人もつまづく箇所なので需要はあります。
自分が書いた記事が他の人のためになると思うと、ブログを書くのが楽しくなります。

また、ある程度スキルを積むと、そのスキルをどう後進に伝えるのかが課題になりますし、自然に後進に伝えたくなる人も少なくないと思います。
スキルを伝える手段としては研修や現場での指導がありますが、研修では期間が決められていますし、現場では同じ現場に居る人にしかスキルを伝えられません。
しかし、ブログであれば、研修期間外でも、同じ現場に居なくても、それこそ社外の人にもスキルを伝えることができます。
これも他の人のためになることですし、ブログを書くモチベーションになると思います。
仮に誰も読まなかったとしても、誰かに読んでもらうことを前提に記事を書こうと思うと適当なことは書けないので、自ずと理解を深めるために勉強することになります。
これが、自分のスキルを更に伸ばす上で大事なことになります。

2.身の回りのプログラミング

身の回りのことで、ちょっとしたプログラムを作ると便利になることが少なくありません。
例えば、買い物(欲しい物や持っている物のリスト)やイベントの運営(抽選や集計)等でプログラムを作ると便利です。

私の場合は、趣味でオンラインのゲームのイベントの運営をすることがあり、そこで一緒に組む人の抽選や結果の集計をプログラム化しています。
プログラム化しているおかげで、早くてスムーズな運営ができておりますし、参加者の方々からも感謝されています。
抽選や集計をするだけなら初心者でも手が出せるのでお勧めです。

また、少しハードルは上がりますが、他の人も使うような機能であれば、ツールとして提供することもできます。
ツールとして提供すれば、自分と関わりのないゲームをしている方々に使ってもらえることもあり、広く貢献することができます。


ここまで趣味としてのプログラミングの楽しさについて語ってきましたが、一番大事なのは自分のPCに開発環境を入れることだと思います。
自宅のPCに開発環境が入ると色々試したくなると思います。
少なくとも私は、自宅に開発環境を入れてから、趣味でもプログラミングをしたいと自然に思うようになりました。

開発環境と言われると、開発業務用のすごいPCにすごい人が入れてくれるもの、という印象を持つかもしれませんが、そうではありません。
普通に量販店で売られているPCにも開発環境を入れることはできますし、開発環境を入れるための手順もWeb上に上がっています。
(初めて開発環境を入れるのであれば、Pleiades All in One の JDK(Java) の環境を入れるのがお勧めです)
プログラミングの経験や興味があるけど開発環境をまだ入れていないという方、是非とも入れてみて下さい!

C#:共有メモリで可変長データを繰り返し送受信する

共有メモリは、同一メモリ上で実行されるプロセス間でデータをやりとりする場合に使用する仕組みです。
通常、プロセスで確保しているメモリは他のプロセスから参照することができないのですが、プロセス間で予め共有メモリとして使用するメモリのアドレスを共有することで、そのメモリは他のプロセスから参照可能となります。
ファイル等を介したやりとりよりも高速なため、高速化が求められる時に使用することが多いです。

目的の一つが高速化のため、データが作成され次第次々と共有する、という使い方になることが多いと思います。
今回は、そのような使い方を想定して、可変長データを繰り返し送受信するサンプルプログラムを作成しました。
書き込んだデータのサイズを伝えること、共有メモリの読み取り位置をずらしていくことがポイントとなります。

なお、今回は省略していますが、本来であれば書き込み中の読み取りを防ぐため、Mutex等の排他制御の仕組みを併用するべきです。
(参考までに、Mutexについては前回の記事で取り上げています)

【サンプルコード】

・Sender.cs

・Receiver.cs

【実行バッチ】

・test.bat

【実行結果】

・Receiverのコンソール


いかがでしたでしょうか。

今回は、共有メモリを用いたデータの受け渡しを紹介してみました。
記事ではjavaに書き方が近く理解しやすいC#で書きましたが、本当に性能が求められる場合はCやC++で書く場合が多いです。
しかし、その場合もロジックは同じなので、参考になるのではないかと思います。

C#:Mutexでの排他制御

排他制御の方法の一つとして、C#にはMutexと呼ばれる機能が用意されています。
何れか一つのスレッドがMutexによるロックを取得することができます。
他のスレッドによりロックが取得されている場合の処理を別途記述すれば、この機能を使用して排他制御が可能となります。

以下、サンプルコードです。

【サンプルコード】

【実行結果】


また、Mutexには、名前を付けることができます。
名前を付けることで、プロセス間でも排他制御が可能となります。
ただし、意図せずMutex名が被ると意図しないロックがかかってしまうため、扱いには注意が必要です。

【サンプルコード】

【実行結果】

※exeファイルを3回起動した結果。
 1つ目のプロセス…掴んで解放
 2つ目のプロセス…解放を待って掴んで解放
 3つ目のプロセス…解放を待って掴めず諦める


いかがでしたでしょうか?

C#には排他制御のための機能が色々と用意されています。
その内の一つが今回紹介したMutexであり、名前を付けることでプロセス間の排他制御も可能になります。
名前付きMutexは、プロセスをまたいだスレッドの制御だけでなく、同じ画面が複数立ち上がらないようにする、といった使われ方もします。
仕組みが単純なので使用しやすく、排他制御の機能の中では使用頻度は高いと思います。

排他制御の機能は他にも色々と用意されているので、今後も紹介していきたいと思います!

Windowsバッチが正常に動作しない場合に見直すポイント(文字コード、改行コード)

Windowsのバッチファイルは、特定の文字コードや改行コードを使用しないと正常に動作しません。
具体的には、以下の文字コードや改行コードを用いる必要があります。

・文字コードは「SJIS」を使用する(chcpコマンドで文字コードを変更しない場合)

・改行コードは「CRLF」を使用する


既存のファイルをコピーしてそれをベースにバッチファイルを作成するような時に、文字コードを誤ってしまうことが多いです。
また、FTP(FFFTP)やGitを用いてサーバ間でファイルのやりとりをする時に、意図せずに改行コードが変わってしまうことも多いです。
既存のファイルをコピーしたり、サーバからバッチファイルを落としてきたりする場合には注意する必要があります。

以下では、文字コードや改行コードを誤るとどのように挙動が変わるのかを見ていきます。
文字コードを誤ると、2バイト文字(日本語等)の部分が文字化けします。フォルダ名やファイル名に2バイト文字が含まれていたり、データに2バイト文字が含まれていたりするような場合は、正常に動作しなくなります。
また、改行コードを誤ると、改行が無視されてコマンドが実行されます。通常のバッチファイルでは改行でコマンドを区切るため、コマンドを上手く区切られなくなり、正常に動作しなくなります。

【サンプル】

【文字コード・改行コードが正しい場合の動作】

【文字コードが「UTF-8」の場合の動作】

【改行コードが「LF」の場合の動作】


いかがでしたでしょうか?

今回は、Windowsバッチが正常に動作しない理由として、ありがちな2つの理由を紹介しました。
(現在私が担当している案件でも、Gitの設定の問題でサーバから落としてきたバッチファイルが動かなくなるという問題に出くわしていました。本当によくあることです。)

今回紹介したように、文字コードや改行コードを誤るとHello Wolrdすら正常に動作しなくなるので、簡単なスクリプトすら動作しなくなることをもって原因調査であたりをつけることができます。
正常に動作しない場合は、コメントアウトやexitコマンドを入れて簡単なコードに書き変えてみて原因を探ると良いでしょう。
(ちなみに、Windowsバッチに限らず、この手の誤りはスクリプト言語全般にありがちです)

原因調査に時間を取られる人が一人でも減れば幸いです!

初めてのWindowsバッチ

Windowsバッチを作ったことが無い方向けに、Windowsバッチの用途や使い方を書いた入門的な記事です。
詳しいコマンドの使い方は記載しませんので、必要に応じて調べてみて下さい。

【Windowsバッチとは】

WindowsOSに標準で用意されている実行ファイル形式であり、拡張子は.batである。
エクスプローラ上でダブルクリックすることで、記述されたDOSコマンド(スクリプト)を自動実行することができる。
簡単な制御や実行ファイル呼び出しを記述可能で、要件に合わせて一連の処理を取りまとめたい時に使用される。

【WindowsバッチでHello World(Windowsバッチの導入)】

WindowsOSであることが前提です。

1.エクスプローラを開き、表示 > ファイル名拡張子 のチェックを入れる。

2.任意の名前でテキストドキュメントを新規作成した後、ファイルの名前を変更する。拡張子を「.txt」から「.bat」に変更する。

3.2で作成したファイルを 右クリック > 編集 で選択し、下記のように入力して保存する。

4.3で編集したファイルをダブルクリックする。コンソールが表示され、下記のように表示されればOK。

【Windowsバッチでできること】

Windowsバッチは複雑な処理を記述するには不向きですが、下記で挙げるような処理であれば記述可能です。
実行ファイルを部品として組み合わせる分には困ることは少なく、「WindowsOSであれば初期設定無しで動く」「習得が容易で、エンジニアであればメンテナンスできる人も多い」といった特徴から、気軽に導入することができます。

1.コンソールへの文字列表示(標準出力)

Hello Worldの例の通り、コンソールへの文字列表示が可能です。
“echo “の後に表示させたい文字列を記述することで、その文字列を表示することができます。
なお、Windowsバッチでは実行されるコマンドもコンソールに表示されるのですが、”@echo off”と記述すれば以降はコマンドのコンソール表示を抑止することができます。
また、Windowsバッチは全てのコマンドの実行が完了したら自動的にウインドウを閉じてしまうので、表示内容を確認したい場合は”pause”と記述して一時的に処理を中断(任意のキー押下で再開)する必要があります。

2.外部の実行ファイルの実行

実行ファイルのパスを記述することで、Windowsバッチから外部の実行ファイルを実行することができます。
実行ファイルのパスの後にスペース区切りで文字列を入力すれば、その文字列を引数として与えることもできます。

例えば、下記のように記述すれば、WindowsOS標準のプログラム言語「C#」のコンパイラを起動することができます。

C#のコンパイル済み実行ファイル(.exe)やjavaのコンパイル済み実行ファイル(.jar)があるなら、そのファイルのパスを記述することでその実行ファイルを実行することができます。
下記は、C#の実行ファイル C:\tmp\Program.exe を実行する例です。

また、Windowsバッチよりも強力な機能を持ったWindowsOS標準のスクリプト言語「Windows Power Shell」は、OSの設定によってはダブルクリックで実行できないという難点があるのですが、下記のように記述することで設定問わずダブルクリックで実行できるようになります。
(Windows Power Shell は環境変数でパスが通っているので、実行ファイルのパスの指定は不要です)

ダブルクリックするだけで引数付きで実行ファイルを実行したり、複数の実行ファイルを実行したり、Windows Power Shell のスクリプトを実行したりできるので、単純に外部の実行ファイルの実行したい時にもWindowsバッチのファイルを作る価値があります。
難しい処理はC#やWindows Power Shell等で記述し、実行はバッチファイルから行う、というスタイルがWindowsOSの場合は馴染みやすいと思います。

3.現在のパス(カレントディレクトリ)の変更

Windowsバッチでは、実行直後はWindowsバッチのファイルが存在するパスを指しています。
例えば、C:\tmp\hoge.bat を実行した場合、実行直後のパスは C:\tmp\ となります。
ファイルのパス指定は現在のパスを起点に相対パスで指定することができ、例えば C:\tmp\ にいる場合は、C:\tmp\Program.exe を

と指定して実行することが可能です。
(.\は省略することも可能です)

現在のパス(カレントディレクトリ)を変更したい場合は、cdコマンドで変更することができます。
cdコマンドのパス指定は絶対パスでも相対パスでも可能で、例えば C:\tmp\ から C:\hoge\ に移動したい場合は、

で移動できます。

他の環境でもWindowsバッチを動かしたい場合は、相対パスが便利です。

4.フォルダの作成

Windowsバッチでは、mkdirコマンドでフォルダを作成することができます。フォルダ名には絶対パス・フルパス両方指定可能です。

なお、フォルダを削除することもでき、コマンドはrmdirコマンドです。

5.ファイルの作成

Windowsバッチでは標準出力の内容をファイルに出力することが可能です。
(出力先は絶対パス・フルパス両方指定可能です)

例えば、以下のように記述することで、Hello World! と書かれたテキストが C:\tmp\hoge.txt に出力されます。
(表示の都合上、大なり記号は全角で入力しています。コピペする際はご注意下さい。)

“>”の部分はリダイレクトと呼ばれており、”>”と記述すれば上書きで出力、”>>”と記述すれば改行して追記で出力となります。

なお、空ファイルを出力するには、下記のように記述すれば良いです(空の文字を入力する、という意味です)。

6.変数の利用

Windowsバッチでは変数を利用することが可能です。

以下は、変数を利用してHello World!を出力する例です。SETで変数を定義、%%で囲むことで変数の参照(正確には展開)が可能です。

例えば、実行したWindowsバッチのフルパスの取得や、システム時刻の取得で変数を使う場合が多いです。
実行したWindowsバッチのフルパスの取得は

システム時刻(YYYYMMDDHHMMSS)の取得は

で可能です。

7.IF文の制御

WindowsバッチではIF文で簡単な制御を行うことができます。

例えば、ファイル・フォルダの存在確認は下記のような記述で実現可能です。

ここで、hoge を hoge\ とすることで、フォルダのみの存在確認が可能になります。
hoge という名前のファイルが存在していても偽とすることができます。
また、”IF”の直後に”NOT”を繋げることで、真偽判定を逆にすることができます。

文字列比較も可能で、下記のように記述します。

数値の比較も可能ですが、比較演算子として”==”の代わりに”equ”(等しい)、”neq”(等しくない)、”lss”(左辺が右辺より小さい)、”leq”(左辺が右辺以下)、”gtr”(左辺が右辺より大きい)、”geq”(左辺が右辺以上)を使うことに注意が必要です。

8.その他の制御

forループやcall・gotoによるジャンプ、exitでのバッチ終了も可能です。
この記事では例を1つ挙げるだけに留めますが、下記はworkフォルダの中の各々のファイルを、順番に C:\tmp\Program.exe の引数として与えて実行する例です。
for文で順番に従って”%%a”にファイル名を格納、”%%a”を第一引数としてmethodルーチンへ飛ばし、methodルーチンでは受け取った引数を C:\tmp\Program.exe の引数として与えて実行、for文が終了したら(全てのファイルに対して処理が終了したら)exitでバッチファイルを終了、ということをしています。


いかがでしたでしょうか?

今回は、新人にWindowsバッチを教えるために、入門的な記事を執筆してみました。
Windowsバッチは文法的にはある意味独特の世界が広がっており、意外と奥が深いのですが、今回は入門者がすぐにWindowsバッチで簡単な制御が行えるようになることを念頭に、内容を絞りました。
ここに書かれていることを使えるようになるだけでも、開発作業の効率化は十分可能ですし、実行環境配布や運用作業に向けたバッチも簡単なものなら作れるようになると思います。

また、経験者でもWindowsバッチの文法を度忘れすることがあるので、そのような時にも見返すと便利なのではないかと思います。

これからも参考になる記事を執筆していきたいと思います!