by Henri Torgemane,
Michael Ang <mang@subcarrier.org>,
and Vladimir Livshits <val4@cornell.edu>
この文書は、JavaScript File オブジェクトについての API 案を記述している。 多くの API が、実装された (だがテストしていない)が、 また終わっていない作業がある。 mailto:nboyd@atg.comに意見を送ってください。
JavaScript で書いた多くのスクリプトは、I/O 機能、特に普通のファイルへのアクセスを必要としている。 この文書は、ホストの実装が実装することが出来る、そのような File オブジェクトを説明している。
そのインターフェースは、Server Side JS File オブジェクトと Java File オブジェクトを混ぜ合わせたもので 既にある JavaScript の暗黙のしきたり (例えば、reaLine ではなく readln) に従おうとしている。
File オブジェクトは、ファイル内のデータへのアクセス方法を二つ提供している。 文字を基にしたテキスト志向のアクセスと、バイトを基にしたバイナリ志向のアクセス。 テキストモードでは、最大文字列長は現在 256 である。 さまざまなエンコーディングが許される。ASCII、UTF8 (unicode)、と UCS2 (binary) が現在サポートされている
実装は現在ほとんど NSPR の PRFileDescを基にしている (申し訳ないがこれに対する公開リンクはまだない) が、 C の標準 FILE タイプを基にファイルを作成することを許すという裏口もある。 これは、標準ストリーム stdin、stdout、と stderr を基にした JavaScript のファイルを初期化する機能の提供に使われる。 パイプの実装もこれによって行われている。 だが、FILE式のファイルでは、操作がすべて一様にどこでもサポートされるわけではない。 結局のところ、異なったプラットフォーム間の違いを隠すのが、NSPR の目標だ。
0.0 Changelog
- 1/18/98 - volodya が、 追加あるいは修正された特徴を API に文書にするという小さな変更をたくさん追加した。 ネイティブファイルハンドリング、さまざまな場合のこのオブジェクトの作用の仕方などについて説明を追加した。 特に、現在のほとんどの情報に付いては status を見なさい。
- 12/18/98 - mangは mozilla.org の仕事を暫く休む。 暫定オーナーはNorris Boyd。
- nsFileSpec email thread を追加。 File オブジェクトは、現在のファイル名操作コードに代わって機能性として nsFileSpec を使うべき。
- 追加プロパティー、append、autoFlush、replace。 これらのプロパティーは、破棄された mode を置きかえる。 mccabe@netscape.comより。
- 未解決の問題/TODOに深い考えを更に追加。
- 12/09/98 - ファイルが親を持っていなければ、parent プロパティーに そのファイル自身を入れるのではなく、null をセットするようにした。 fur@geocast.comより。
- 12/07/98 - in と delete は予約済みの識別子。 in を inputに、out を output に、 err を error に、delete を remove に変更。 brendan@netscape.comより。
1.0 ファイル名
-
ファイル名は、実装定義のフォーマットを持つ文字列をして指定される。
標準 "file:" URL の使用が推奨される。
使用可能なプレフィックス文字列の例としては、Unix のルートディレクトリを示す "/" や、 Windows のドライブ文字を指定する "c:" や、file URL を示す "file:" がある。
ファイルが作られると、前と後ろのスペースはファイル名から取り除かれる。 だから、new File(" abc.txt ") は、 abc.txt と呼ばれるファイルを作る。 '|' で始まり終わるファイル名は Perl 風にパイプと解釈される。
次のような事が可能だろう:
-
var mail = new File("|/usr/bin/mail foo@bar.com");
mail.writeln("I love JavaScript.\nPipe support is especially good!");
mail.close();
2.0 File コンストラクターのプロパティー
| File | File コンストラクターメソッド |
| input | 標準入力を表す File オブジェクト。 |
| output | 標準出力を表す File オブジェクト。 |
| error | 標準エラー出力を表す File オブジェクト。 |
| currentDir | カレントディレクトリを参照する File オブジェクト。このプロパティーは設定されるかもしれない。 |
| separator | システムの名前区切り文字。 |
注: 最初の木のプロパティーは、特定の環境下でしか使えないようにするべきかもしれない。 例えばブラウザコンテキストでは不可能など。 例えば isFile のようなメソッドの中には、そのような環境の一つの元で呼ばれると、 エラーをかえすものがあることを留意しなさい。
2.1 File インスタンスのプロパティー
| name | ファイルの名前が入る。 |
| path | ファイルへの基準パスが入る。 |
| length | ファイル内の文字の数が入る。 |
| parent | ファイルを含むディレクトリが入る。 |
| type | データの型かファイル内に含まれているエンコーディングを指定する文字列が入る。 現在は "ascii"、"utf8" (UTF8)、 あるいは "ucs2" (UCS2)。 |
| mode | ファイルモードが入る。 |
| position | ファイル内での現在のオフセットが入る。このプロパティーは設定されるかもしれない。 |
| isFile | ファイルが通常のファイルなら true。 |
| isDirectory | ファイルがディレクトリなら true。 |
| exists | ファイルが存在するなら true。 |
| isOpen | ファイルのオープンに成功したなら true。 |
| isNative | パイプで標準ストリームに対しては true。 |
| lastModified | 最後に変更された時を表す Date オブジェクトが入る。 |
| canRead | ファイルが読み込み可能なら true。 |
| canWrite | ファイルが書きこみ可能なら true。 |
| canAppend | ファイルが追加モードか示すフラグが入る。 |
| canReplace | ファイルが置き換えモードか示すフラグが入る。 |
| hasRandomAccess | "position" プロパティーを使用可能か示すフラグが入る。 |
| hasAutoFlush | ファイルが自動フラッシュモードか示すフラグが入る。 |
2.2 インスタンスメソッド
| open(type,mode) | ファイルを開く |
| close() | ファイルを閉じる |
| flush() | ファイルへの送信を待つデータをフラッシュする |
| seek(numChars) | 次の numChars 分の文字をスキップする |
| read(numChars) | numChars 分の文字を読み、文字列に入れる |
| readln() | ファイルから一行分の文字を読む |
| readAll() | ファイル内に残っている行すべてを読み、文字列の配列をかえす |
| write(arg0,arg1,...,argn) | パラメーターを文字列としてファイルに書きこむ |
| writeln(arg0,arg1,...,argn) | writeと同じで、現在のプラットフォームの改行区切り文字を追加する |
| writeAll(Array) | オブジェクトの配列を順にファイルに書きこむ |
| remove() | ファイルかディレクトリを削除する |
| copyTo(filename) | ファイルの内容を別の場所にコピーする |
| renameTo(filename) | ファイルを移動/名前の変更をする |
| list(filter) | ディレクトリ内のファイルリストを得る。 |
| mkdir() | 新しいディレクトリを作成する |
| toString() | ファイルへの基準パスをかえす |
| toURL() | 可能ならファイル名を "file:" URL でかえす |
3.0 File コンストラクターのプロパティー
-
File
File コンストラクター。filename をただ一つの引数として期待する。 filename の前に "file://" を置くことも可能で、置いても取り除かれる。 引数を与えられなかったら、現在のワーキングディレクトリをかえすファイルオブジェクトとする。
標準入力ストリームを表す File オブジェクト。特定の環境下で初期化される。
標準出力ストリームを表す File オブジェクト。特定の環境下で初期化される。
標準エラーストリームを表す File オブジェクト。特定の環境下で初期化される。
このプロパティーには、カレントディレクトリを指す File オブジェクトが入る。 このプロパティーに代入すると、カレントディレクトリーが変更される。 次のような構文がサポートされている。
-
File.currentDir = new File("/");
これは機能上は次と同じ
File.currentDir = "/";
システムの名前区切り文字。例えば、Unixでは "/"。
3.1 File インスタンスのプロパティー
-
name
このプロパティーにはファイル名が入る。ストリームに対しては、"Standatd input(output/error) stream" と定義される。 パイプに対しては undefined。
このプロパティーにはファイルへの基準パスが入る。 ストリームに対しては、"Standard input(output/error) stream" と定義される。 パイプに対しては、パイプを作るのに使用したパスをかえす。初めとそれに続くスペースは取り除かれる。
ディレクトリに対しては、カレントディレクトリと親ディレクトリエントリーを数えないファイルの数である。 ファイルに対しては、このプロパティーはファイル内の文字の数が入る。 パイプと標準ストリームに対しては undefined。
このプロパティーには、そのファイルを含んでいるディレクトリを指す File オブジェクトが入る。 そこファイルに何にも含まれていなければ (ルートディレクトリ)、プロパティーは null である。 パイプと標準ストリームに対しては undefined。
このプロパティーには、ファイルが開かれた時使われていたデータタイプかエンコーディングを指定する文字列が入る。 指定されたテキストエンコーディングサポートは、"ascii"、"unicode"、と"binary" である。 ディレクトリと閉じてしまったファイルに対しては undefined。
このプロパティーにはファイルのモードが入っている。 属性を繰り返したり ("read,read")、無視される属性があったりすると、 オープンに失敗しなかったものと少々異なることが有り得る。 ファイルが閉じられていると undefined をかえす。
このプロパティーには、ファイル内の現在のオフセットが入る。 これだけが、設定されてもよいプロパティーだ。 ファイルがランダムアクセスモードでないか、パイプや標準ストリームだと、このプロパティーは undefined である。 閉じてしまったファイルに対しても undefined である。 このプロパティーを設定するとファイル上で seek 操作が行われる。
ファイルが世紀のデータファイルなら、このプロパティーには true が入る。 パイプと標準ストリームに対しては false。 注: いくつかのファイルタイプに対して (例えば unix の名前付きパイプ)、"isDirectory" と "isFile" の両方が false をかえすかもしれないプラットフォームもある。
ファイルがディレクトリならこのプロパティーは true が入っている。 パイプと標準ストリームに対しては false。
ファイルが存在するなら、このプロパティーは true と等しい。 パイプと標準ストリームに対しては false。
ファイルをうまく開き、開いた状態のままだと、このプロパティーには true が入る。 標準ストリームとパイプはデフォルトで開かれ、開く必要が無いことを心にとめておきなさい。
パイプと標準ストリームに対しては、このプロパティーには true が入る。
このプロパティーには、ファイルが最後に編集された時を表す Data オブジェクトが入る。 パイプと標準ストリームに対しては undefined。
ファイルが読み出し可能なら、このプロパティーには true が入る。 ファイルが開かれたモード (もし開かれたのなら) は考慮される。 File.input に対しては true で、他のストリームに対しては false。 '|' で始まるパイプに対して true で、他は false。
ファイルが書き込み可能なら、このプロパティーには true が入る。 ファイルが開かれたモード (もし開かれたのなら) は考慮される。 File.output と File.error に対しては true で、File.input に対しては false。 '|' で終わるパイプに対しては true で、他は false。
ファイルが追加書き込みように開かれたのなら、このプロパティーには true が入る。 パイプと標準ストリームに対しては false。閉じてしまったファイルに対しては undefined。
ファイルが置き換えフラグを与えられて開かれているのなら、このプロパティーには true が入る。 パイプと標準ストリームに対しては false。閉じてしまったファイルに対しては undefined。
このプロパティーには、ファイルがランダムアクセスモードで開かれているかを示すフラグが入る。 つまり、"potition" プロパティーは読み出しと設定が可能である。 パイプと標準ストリームに対しては false。閉じてしまったファイルに対しては undefined。
ファイルが自動フラッシュモードだと、このプロパティーには true が入る。 これが true と設定されると、毎度の writeln 呼び出しでストリームをフラッシュする。 パイプと標準ストリームに対しては false。閉じたファイルに対しては undefined。
3.1.1 ディレクトリのための特別なプロパティー
-
ディレクトリを表す File オブジェクトは、ディレクトリ内に含まれるファイルを表す追加プロパティーを得る。
これらのプロパティーはディレクトリ内のファイルのように同じ名前を持つ。
| 例 |
| myDir = new File("some/directory");
myFileInDir = myDir.foo; 名前付きプロパティールックアップを 通常のプロパティー名としては不正な名前を持つファイルを指すのに使うことが出来る。 mySameFileInDir = myDir["foo"];
|
3.2 インスタンスメソッド
-
open(type,mode)
- "read" と "write" の両方がセットされると、"readWrite" は自動的にセットされる。
- バイナリファイルに対して "randomAccess" は true とセットされる。
- "autoflush" はデフォルトで true。
mode が指定されなかった場合、通常のファイルに対して使われるデフォルトの mode は、
"read,append,create" である。パイプは作成時に、
パイプの形式によるが "read" か "write" をデフォルトの mode として自動的に開かれる。
type が指定されなかった場合、デフォルトの type は "text" である。
| 有効な mode (合成可能) | |
| read | 読み出しのためにファイルを開くと指定する。 |
| write | 書き込みのためにファイルを開くと指定する。 |
| readWrite | 読み出しおよび書き込みのためにファイルを開くと指定する。 |
| randomAccess | 読み出しおよび書き込みのためにファイルを開くと指定する。 |
| append | ファイルポインターの位置をファイルの最後に置く。 |
| autoflush | 改行文字が書かれたら出力に自動的にフラッシュするように頼む。 |
| replace | ファイルを開く前に内容を消去する。 |
"create=yes, append=yes" などの書式も使うことが出来る。
大文字小文字が違うのに注意してください。
-
注:
| 有効な type | |
| "text" | デフォルトのファイルエンコーディングを使ってテキストアクセス用にファイルを開く。 |
| "binary" | バイナリアクセス用にファイルを開く。 |
| "unicode" | Unicode アクセス用にファイルを開く。 |
ファイルがネイティブファイルやディレクトリだと、警告を出す。 この場合両方とも戻り値は true である。ファイルがネイティブでなく既に開かれていると、 警告が生成されファイルは再び開かれる。 ファイルの先頭に行きたい場合などで意味をなすが、 かわりに seek を使うことが出来るだろう。
このメソッドはファイルを閉じる。ファイルが開かれていなかったりネイティブファイルだと、 警告を出し、false をかえす。 開かれているファイルオブジェクトがスコープの外に出たとき、そのオブジェクト上でこのメソッドは自動的に呼ばれる。
このメソッドは、ファイルを削除するか、引数として与えられたディレクトリを削除する。 通常ディレクトリで削除が呼ばれたとき、ディレクトリが空のときしか削除されない。 ファイルを開いていると失敗する。
このメソッドは、ソースファイルのそのまま目的のファイルへコピーしようと試みる。 ソースファイルが存在しなかったり、ディレクトリだと失敗するだろう。
このメソッドは、ファイルを移動/名前の変更をする。ファイルが開かれていると失敗する。
このメソッドは、ファイルの出力バッファーのフラッシュを強制する。 ファイルが閉じられていたら失敗する。
このメソッドは、現在のファイルに対するアクセスモードによるが、次の numChars 分の文字列かバイト列をスキップする。 ファイルが閉じられていた場合、この操作を行う前に開かれる。 この関数は、正負両方のパラメーターを受け付ける。 ディレクトリで呼ばれたら、警告を報告し、undefined をかえす。 この操作が成功すると、ファイル内の現在の位置をかえす。
このメソッドは、numChars 分文字を読みこみ、文字列でかえす。 読みこむ文字列の数が numChars より少ない場合、読めるだけかえされる。 ファイルが EOF にあると、null がかえされる。
このメソッドは、行/ファイルの終わりがなるまで文字列を読み、 それらの文字列に対して文字列を (end of line 文字を一切除いて) かえす。
このメソッドは、ファイルの残りを読み込み、ファイルの各行に対してスロット付きの配列をかえす。
このメソッドは、各引数を文字列に変換し、ファイルに (セパレーターなしに) 書きこむ。
このメソッドは write と似ているが、最後の引数を出力した後プラットフォーム依存な EOF を追加する。
このメソッドは引数に配列を取り、各要素ごとに writeln() を呼ぶ。
このメソッドは配列をかえす。ファイルがディレクトリなら、 そのディレクトリ内の各ファイルに対してスロットが作成され、 そのファイル名のプロパティーも作成される。 両方ともファイルを参照する File オブジェクトを指す。
filter は、関数が正規表現でなければならないオプションの引数で、
配列のフィルターに用いられる。
引数が正規表現なら、配列にはパターンにマッチしたファイルしか入らない。
引数が関数なら、ファイル名を引数として与えたとき、関数が true をかえしたファイルしか配列には入らない。
| 例 |
| File.currentDir.list( function (name) { return name.length==3;
} );
カレントディレクトリで名前が三文字のファイルしかかえさない。 |
このメソッドは、ファイルディレクトリ内にディレクトリを作成しようと試みる。 例えば、
-
f = new File("c:\\")
f.mkdir("win95")
-
f = new File("c:\\user.txt")
f.mkdir("win95")
このメソッドは、ファイルに対する基準パスをかえす。
ファイル名を "file:" URLとしてかえす。パイプと標準ストリームに対しては undefined。
4.0 遊んでみたい
大げさな免責条項: ハードドライブが消され無茶苦茶に破壊される覚悟が出来ていなければ、File オブジェクトで遊ぶなかれ! 今は大体上手く動いているが、保証はない。
現在 File オブジェクトは、define を使ってコア JS engine 内へビルド可能である。 これはよくない。いったん XPCOM が落ち着いたら、File オブジェクトは COM 化するべきだ。
File オブジェクトで遊ぶ/をハックするには、最新で (通常は) 一番良い JavaScript を 次のように CVS を使って入手しなさい。
cvs co -rSpiderMonkeyDev_BRANCH mozilla/js/src
JavaScript の開発進行中のブランチを入手するのだが、これは安定性にほとんど保証がないと警告しておく。
File オブジェクト付きで (例えば UNIX 上のリファレンスインタプリターを) ビルドするには、 ビルド時に JS_HAS_FILE_OBJECT を define しなさい。 NSPR に対してビルドする必要もあり、JS_THREADSAFE を define することでこれは出来る。
cd mozilla/js/src
gmake -f Makefile.ref JS_THREADSAFE=1 JS_HAS_FILE_OBJECT=1
5.0 状態
-
コードの状態:
- コードはすべて jsfile.[c|h|msg] にある。とても良い状態にある。 少なくとも1999年12月半ばよりはずっとよい状態である。 まだ冗長な部分の削除、マクロの追加などをする機会がある。
- 徐々に、最重要機能は実装さてテストされている。 ファイルのオープン、クローズ、読み出し、書き込みなどを含む。 より多くの例については、テスト一式の中の nspr_files.js を見なさい。
- この提案で説明したメソッドとプロパティーは全部実装したと思う。 必ずしもどんなプラットフォームでも動くとは限らない。 特に、誰も Mac でこれをビルドしようとしていない。 注: パイプや場合によっては標準ストリームのような機能が Mac では使用できるようにならない。 NSPR の機能でさえ全部は動かないかもしれない。 Mac が含んでいるどれが必要なのかさえはっきりしない。
- コードについて言うと、File オブジェクトのメソッドの多くはとてもしっかりテストされている。 低水準のファイルアクセスを取り扱うコードにまだ予測のつかないバグがあるだろう。 そのコードはまた、最適化されていない。割と大きなファイルのコピーにしばらくかかる。 ファイル名の操作は書きなおされた。 これと John McMullen が書いたものを合体させるという話があり、 一度彼ら (NSPR な人々, Brendan) が NSPR の一部であるべきで実装言語にどれを使うか考え出したら、それほど大変な話ではないだろう。 これについては netscape.public.mozilla.xpfe で議論がある。
- 機能の多くをカバーするテスト一式がある。 だが、オブジェクトを酷使したとき潜在的なバグが多くでるだろう。 このバグは発見は難しいが簡単に修正できる。
- コードの多くは、エラー状態を捕捉しエラーメッセージか警告を生成する目的に用いられる。 エラーコードについては jsfile.msg を見なさい。
-
すべきこと:
- エラーが起きたとき、例外を生成すべき。例外の書式はどうするべきだろう? 警告を報告する関数もあるし、エラーとなるものもある。 最終的には、すべて例外となるべき。
- エラーメッセージを少し片付けるべき
- セキュリティーコールバックをコードに入れるという話がある。 この目的のために SECURITY_CHECK マクロが残っている。 それは現在空の文字列として define されており、再 define の必要がある。 このマクロは、操作の名前をパラメーターの一つとして取り、その名前は現在メソッド名と一致しているが、 分解してグループ (read、write、exist など) に分けられるはずだ。 セキュリティーチェックは、処理手順にアクセスする個々のメソッドとプロパティーのレベルで実装されており、 根本的な実行関数のレベルで実装されているのではない。 なぜなら、 実行関数はコード内で別の場所から呼ばれる可能性があり、 私たちはセキュリティーチェックの階層化を望んでいないはずだから。 これについては Norris に質問しなさい。
- RDF は JS に影響するようになる (Guha と Clayton に聞きなさい)。 現在私たちは、JavaScript ファイルコンストラクタに RDF のなんとかという物を取ってこさせて、 普通の JS File オブジェクトをかえさせたい。 それはつまり、RDF を ファイルシステムを ナビゲートする のに使い、 File オブジェクトを読み書きなどに使うだろうという事。
- js_canonicalPath(...) をどうすべきか考える。この処理手順は、 ".././blah/../../dir/file.txt" のように与えられたファイル名を解決する。 実際には必要ないと思う。ファイルシステムがこの名前を自動的に解決するから。 (最後に fopen 呼び出しの結果皆除去される) この処理手順は Mac 互換ではなく、潜在的に奇妙な問題や弱いリンクの問題があるかもしれない。 コード内で、マクロ RESOLVE_PATH を探しなさい。 この処理手順は、最初と最後のスペースを取り除いたりといった他の事もする。 js_absolutePath(...) へ移す必要があるかもしれない。
- Purify を通してコードを実行するのは良い。
- jsstr.h にある js_escape をコードで使っている。 何時の日か jsstr.h からそれは消え、クライアントへ移動するだろう。 そしてこのコードがビルド出来なくなる...
- (?) nsFileSpec の機能を NSPR に巻き込むのに NSPR グループを得る。 上の議論を見なさい。外部コードが既に大体動いているので、 これが私たちのしたかったことなのかまだ完全には明らかではないが、 調べる価値はある。
- (?) XPCOM 化 -- まただが、これにより受ける恩恵がはっきりしないが、 これは大幅な改訂が必要である。
- (?) Java での実装ははっきりしない。 何故なら、LiveConnect + java.io.File で既にこの機能はある。
- (?) api をソケットなどの使用が出来るように拡張する。(機能は既に PRFile 内にある。) 何のために必要なのかはっきりしないが、簡単に出来る。どうですか?
- (?) 低水準ファイルアクセス機能は、能率的でないだろう (js_FileRead(..) などを見なさい)。 比較的小さなファイルのコピーにはしばらくかかる。 最適化できるだろう。既にきちんとバッファリングしているが。
- サーバーの領域にいる誰かが、同様のもの (Server-side JS?) を書こうとしていて、 XPCOM なファイルオブジェクトもどこかにあるようだ。 (Clayton に聞きなさい)
とりとめもない思索:
Norris Boydに質問しなさい。
Last modified: Fri Dec 18 20:47:48 PST 1998