ファイルの出し入れ

ファイルを受け取って内容を表示し、ファイルを保存する画面です。

ファイルを受け取る

(node at: '.asText'  on: #change sendFileText:  #tookText:text:)
(node at: '.asBytes' on: #change sendFileBytes: #tookBytes:bytes:)

他のイベントはイベントの値をその場で読んでメッセージを送りますが、ファイルは読み込みに時間がかかるため、読み込みが終わってからメッセージを送ります。ハンドラにはファイル名と内容が届きます。ファイルを選ばずにダイアログを閉じた場合は何も起きません。

ファイル選択、貼り付け(on: #paste)、ドラッグ&ドロップ(on: #drop)は同じハンドラで受け取れます。

文字列とバイト列

sendFileText: は CSV のように文字列として読むファイルに使います。sendFileBytes: はファイルの内容をバイト列のまま受け取ります。帳票や表計算のファイルを文字列として読むと、読めない部分が置換文字に置き換わって元に戻せなくなるため、この二つを分けています。

ファイルを保存する

Screen >> saveCsv  = ( App save: 'out.csv' type: 'text/csv' text: text. self ).
Screen >> saveSame = ( App save: name type: 'application/octet-stream' bytes: held. self ).

ブラウザ本来の方法(リンク要素を作り、クリックさせ、捨て、オブジェクト URL を解放する)は四手順で、解放を忘れるとメモリが漏れます。これを一つのメッセージにしてあります。

文字コードの変換

Bytes には size asText asTextIn: asCodes があり、Bytes empty Bytes ofText: Bytes ofCodes: で生成します。

asText は UTF-8 として読みます。日本語のメールの件名は =?ISO-2022-JP?B?GyRCJDMkcyRLJEEkTxsoQg==?= のように、ヘッダで指定した文字コードのバイト列を base64 で包んだ形で届きます。これを読むには、base64 をデコードし、指定された文字コードで読みます。

b := (Base64 decode: 'GyRCJDMkcyRLJEEkTxsoQg==') orElse: [Bytes empty].
b asText printNl.                     "$B$3$s$K$A$O(B — UTF-8 として読んだ結果"
(b asTextIn: 'ISO-2022-JP') printNl.  "Some('こんにちは')"

Base64 decode: と asTextIn: は Maybe を返します。外部から来る文字列で例外を出さないためです。文字コードで読めないバイトはエラーにならず、置換文字になります。

ヘッダの Q 形式(=E9=BB=92 のような 16 進)など、他のエンコード方式のデコーダは Bytes ofCodes: と asCodes を使って LPScript で書けます。整数の配列とバイト列を相互に変換するもので、0 から 255 の範囲外の値はエラーになります。

UTF-8 以外の文字コードへの変換はありません。ブラウザの TextEncoder が UTF-8 しか出力しないためです。

Bytes は Worker へ渡せます。

テスト

ファイル選択ダイアログと保存先は、ブラウザが無ければ存在しません。この画面のテストは本物のブラウザで行い、入力欄にファイルを入れ、保存されたファイルをディスクから読み直して照合しています。