Perl初心者の部屋  序章  1章  2章  3章  4章  5章  6章  7章  9章  10章
PageID:New Perl-FAQ8J
Last updated:97.07.24

Perl for Win32 Frequently Asked Questions (FAQ)


翻訳者: 木村 浩一さん <kkimura@pure.cpdc.canon.co.jp>

8. 一般的なプログラミング

8.1. Win32レジストリを変更するにはどうしたらいいのでしょうか?

Win32レジストリに関する幾つかの関数が Perl for Win32にはあります。 Perl for Win32に付属していた win32modドキュメントをチェックして ください。

もしあなたが、レジストリの働きについてよくわかっていないのであれば、 *キー*とはディレクトリのようなものであり、*value*とはファイルの ようなものであると思ってください。幾つかのトップレベルのキーが ドライブのように存在しています。

あなたが本当にレジストリを扱うのでなければ、それについて興味を 持たないことが一番かもしれません。

8.2. 名前付きパイプを読み書きするにはどうしたらいいのでしょうか?

名前つきパイプはプロセス間で通信を行うための機構で、主に (Win32プラットフォームのような)Microsoftのオペレーティングシステム で用いられます。名前つきパイプはファイルと同じように扱うことが できます。

名前つきパイプの名前はUNC(Universal Naming Convention)であり、 "\\servername\pipe\pipename" のような形をしています。 "servername"はあなたが接続しようとしているサーバーの名前で、 これが"."の場合にはカレントコンピューターを意味します。 "pipe"は定数で、"pipename"がパイプの名前です。たとえば Microsoft SQLサーバーでは"sql"が使われています。

ファイルと同じように、名前つきパイプに対して open(), close(), read(), print()といった関数を使うことができます。ただし、 sysread()やsyswrite()は名前つきパイプが実際にはファイルでない ために使うことができません。

CPANには名前付きパイプを生成できるWin32Pipeを呼んでいる プログラムがあります。

もしあなたがゼロから始めるような状態で、かつTCP/IPが使える 環境にあるならば、プロセス間通信のために名前つきパイプを使う ことよりもソケットを使うことを考慮すべきでしょう。

8.3. ソケットスクリプトを書くにはどうしたらいいのでしょうか?

Perl for Win32の一緒に配布されているソケットを使ったスクリプトの サンプルがあります。これらのサンプルはあなたがperlをインストールした ディレクトリの下のegというサブディレクトリにあります。

ソケットサーバーに関しては質問 8.5を参照のこと。

8.4. ファイルハンドルとしてソケットを使うことはできないと聞いていますが、 やはりそうなのでしょうか?

初期の Perl for Win32では、ソケットをファイルハンドルであるかのように 読み書きすることができませんでした。現在ではこれをサポートしている ので、質問にあるような心配をする必要はありません。もしあなたが 使っているバージョンが古いものでソケットをファイルハンドルとして つかうことができないのであれば、ActiveWareから最新のものを 入手すべきでしょう (質問 1.4を参照)。

反対に ActiveWareのFAQ (see 質問 3.7) では、Perl for Win32をソケットをファイルハンドルと同じように 機能させるときには USE_SOCKETS_AS_FILEHANDLES を指定する必要はないとあります。 これは害を与えるものではないが、必要というわけでもありません。

8.5. Perl for Win32でソケットサーバを書くにはどうしたらいいのでしょうか?

あなたがperlをインストールしたディレクトリの下のegという ディレクトリに、TCP-SERVERというソケットサーバーのサンプルが あります。一般的にいって、UNIXでのソケットプログラミングの情報は Perl for Win32でも有効です。 詳しくは perlipcというドキュメントを参照してください。

一度に一つのクライアントにしかサービスできないので、 Perl for Win32をサーバーを実装するために使うのは良くないやり方である ことに注意してください。 その理由は、1) perlという言語はスレッドをサポートしておらず、 2) Perl for Win32はfork()関数をサポートしていないからです。

[なにか新しい情報ない? -ESP]

8.6. FTPでファイルを送受信するにはどうしたらいいのでしょうか?

perlをインストールしたディレクトリのlibというサブディレクトリに ftp.plというファイルがありますが、alarm()やselect()の呼び出しが Perl for Win32ではできないためにこれは動作しません。 CPANにはNet::FTPというものがありますが、これも動作しません。 [だれかいい情報持ってないかい? -ESP]

さて、FTPを実行するための幾つかの手段があります。ftp.plスクリプト をなおしてPerl for Win32でも動作するように修正することもできます [もし実際にやったのなら、是非それを共有しよう! -ESP]。 また、FTPの仕様を入手して、モジュールを一から作ることもできます。

手っ取り早い(quick-and-dirty)解決策は、Windows NTに付属している [Windows 95も? -ESP] FTPプログラム用のスクリプトをコンパイルしてしまうということです。 そしてFTPプログラムにそのスクリプトを引数として渡して実行します。 詳しくはFTPプログラムのヘルプファイルを参照してください。 確かにこれが冴えない方法だと言うのはわかってるんだけど、ちゃんと 動くからね。

Aldo CalpiniはWININETライブラリを使ってFTPやHTTPを実行するPerl for Win32の エクステンションを開発しました。これはアルファレベルのもので、 彼のwebページから入手できます (質問 3.4を参照)。

8.7. HTTPでファイルを送受信するにはどうしたらいいのでしょうか?

繰り返しますが、CPANの解決策はlibwwwを必要とするでしょう。しかしこれを Perl for Win32で動作させるにはlibwwwを変更しなければ成りません。 その情報については以下のURLを参照してください。

http://www.its.unimelb.edu.au:801/hma/pub/libwww/d009/0028.html

HTTPプロトコルは実に単純で、一度限りの解決策を実に簡単に手作業で できます。HTTPプロトコルの仕様、ソケットの例については先に挙げた ものを参照してください。

Aldo CalpiniはWININETライブラリを使ってFTPやHTTPを実行するPerl for Win32の エクステンションを開発しました。これはアルファレベルのもので、 彼のwebページから入手できます (質問 3.4を参照)。

8.8. Perl for Win32でユーザアカウントを管理するには どうしたらいいのでしょうか?

Perl for Win32と一緒に Win32::NetAdminといと呼ばれるエクステンションが あります。これは非常に低レベルなインターフェースですが、このモジュールを 使ってユーザーやグループの管理をすることが可能です。

8.9. シリアルポートを読み書きするにはどうしたらいいのでしょうか?

Perl for Win32ではシリアルポートはファイルと同じようにオープンでき ます。COM1をオープンするには以下のようにします。

    open( PORT, "+>COM1" ) or die "Can't open COM1: $!";

ファイルハンドルを使って標準入出力関数(read()やprint())で読み書きを することができるでしょううが、システム関数(sysread()やsyswrite()) ではできません。[誰かこれを試した? 本当に動作するの? 警告する?]

ヘイズのコマンドセットを使っているモデムはコマンドの終端に 改行(\n)ではなく復帰(\r)を要求することに注意しています (がテストはされていません)。

8.10. -d 演算子は何故機能しないのでしょうか?

本当は正しく動いています。けれども人々は間違った使い方をしていて、 間違った結果を得ているのです。あるディレクトリにあるすべてのサブディレクトリ をチェックするのに以下に示すコードを試してみてください。

    $path = shift;
    $path = "." unless $path;

    opendir( DIR, $path )
      or die "Can't open $path: $!";

    while ( $entry = readdir( DIR ) )
    {
      $type = ( -d "$path\\$entry" ) ? "dir" : "file"; # $pathが重要だ!
  
      print "$type\t$entry\n";
    }

    closedir( DIR );

ありがちな間違いは-dでチェックする引数に$pathがないというものです。 そうしてしまった場合、perlはあなたがカレントディレクトリにあるファイルに ついてチェックしようとしているとみなします。 対象となるディレクトリはカレントディレクトリでは-eが成立しませんから、 -dは成功しません。ただし、すべてのディレクトリに必ず存在する"."と".."を除きます

8.11. ファイルを読み書きするのが何故か失敗しています。 何がおかしいのでしょうか?

Win32環境では、テキストファイルとバイナリファイルの間には大きな 違いがあります。たとえばテキストファイルでは、"\r\n" というキャラクタ がディスクから読み出されたときに"\n"に変換されますし、^Zという キャラクタはファイルの終端を示す目印として読み込まれます。 バイナリファイルではこのような変換は行われません。

テキストファイルに対するこの操作のために、あなたがバイナリファイルを 読み書きしようとしたときにはおかしなことになります。もしファイルを 読み書きしたときに中断してしまえば、それは^Zがファイルの中で見つかった からで、中断することがなくても\nから\r\nへの変換のためにファイルの大きさが おかしくなっているでしょう。

この問題は、Perl for Win32とそれが使っているCのランタイムライブラリが ファイルのオープンをデフォルトでテキストモードで行うことにあります。 Perlであなたがファイルハンドルをバイナリデータのために使うには、 そのファイルハンドルがバイナリモードであることを指定する必要があり ます。幸運にも、binmodeという関数がそれを行います。 詳しくは perlfuncというドキュメントを参照してください。

このスクリプトはあるバイナリファイルを別のファイルにコピーします。 binmodeをファイルハンドルのモードを設定するのに使っていることに 注意してください。

    open( INFILE, "<$infile" );
    open( OUTFILE, ">$outfile" );

    binmode( INFILE ); binmode( OUTFILE ); #バイナリファイルのために重要!

    while ( read( INFILE, $buffer, 1024 ) )
    {
      print OUTFILE $buffer;
    }

    close( INFILE ); close( OUTFILE );

8.12. ファイルをオープンしようとすると、"bad argument"エラーとなります。 何が原因なのでしょうか?

Win32環境では'\'というキャラクタをパスの区切りとして使っています。 しかし、一方でperlは'\'を改行("\n")やタブ("\t")のような特殊なキャラク タを表わすエスケープの目印として使っています。

このため、以下の様にしてファイルをオープンしようとすると

    open( MYFILE, "C:\temp\newfile.txt" );

これはエラーになるでしょう。解決方法の一つはそれぞれの'\' を二つの'\'に置き換えて、エスケープではなくバックスラッシュ自身を 表わすようにしてしまうということです。

    open( MYFILE, "C:\\temp\\newfile.txt" );

もう一つの解決策は、文字列をシングルクォートで囲むことによってPerlに 特殊キャラクタを処理しないようにさせるということです。

    open( MYFILE, 'C:\temp\newfile.txt' );

シングルクォート(') とダブルクォート(")の違いについての詳細は perlopというドキュメントを参照してください。

8.13. Perlの"ヒアドキュメント"構文(<<)を使うと、 "Can't find string terminator anywhere before EOF" (EOFの前のどこにも文字列終端文字が見つからない)というエラーが出るのですが、 何故なのでしょうか?

これはスクリプトの最後の行に文字列終端文字があるときに発生する 不思議なエラーです。

    print <<"END";
    The snake is old, and his skin is cold.
    END

perlは改行文字("\n")が続いている“END”という単語だけがある行を 探します。“END”がスクリプトの最後の行にあった場合、 perlがその単語を文字列終端文字であることを認識できるように、“END”という 単語の後にリターンキーを叩くことを忘れないようにしなければなりません。

ほとんどのUNIXのテキストエディターはこれを自動的に行ってくれます。 ほとんどのWindowsのテキストエディターはこれをやってくれません。 だから問題なのです。

同じことがPerlのformatでも起こりうることに注意してください。 これは“.”のみからなる行を終端として扱います。しかし、 これは上の例に比べれば頻度は非常に低いでしょう。なぜならプログラマー がフォーマット指定を行うのはファイルの末尾ではなく先頭である のがほとんどだからです。


ご意見、ご要望は、 電子メールまたは 投稿にお願い致します。

ホームページへ戻る。