ストリーム・プロパティの宣言
InterSystems IRIS は、バイナリ・ストリームと文字ストリームの両方をサポートします。バイナリ・ストリームは、%BinaryOpens in a new tab タイプと同種のデータを含み、写真などの非常に大規模なバイナリ・オブジェクトを想定しています。同様に、文字ストリーム は、%StringOpens in a new tab タイプと同種のデータを含み、大量のテキストの保存を目的としています。文字ストリームは、文字列と同様に、クライアント・アプリケーション内で Unicode 変換を受ける可能性があります。
ストリーム・データは、ストリーム・プロパティの定義に応じて、外部ファイルまたは InterSystems IRIS グローバルに保存できます (一切保存しないようにすることもできます)。
最初の 4 つのクラスは、オプションで LOCATION パラメータを使用して既定のストレージ場所を指定できます。
以下の例では、JournalEntry クラスに 4 つのストリーム・プロパティ (最初の 4 つのストリーム・クラスにつき 1 つずつ) が含まれ、そのうち 2 つについて既定のストレージ場所を指定しています。
Class testPkg.JournalEntry Extends %Persistent
{
Property DailyText As %Stream.FileCharacter;
Property DailyImage As %Stream.FileBinary(LOCATION = "C:/Images");
Property Text As %Stream.GlobalCharacter(LOCATION = "^MyText");
Property Picture As %Stream.GlobalBinary;
}
この例では、DailyImage のデータは C:/Images ディレクトリのファイル (ファイル名は自動的に生成されます) に保存されますが、Text プロパティのデータは ^MyText という名前のグローバルに保存されます。
ストリーム・インタフェースの使用法
すべてのストリームは、ストリームに含まれるデータの操作に使用されるメソッドおよびプロパティのセットを継承します。次のセクションでは多用するメソッドとプロパティの一覧を示し、それらの具体的な使用例をそれ以降のセクションで示します。項目は以下のとおりです。
一般的に使用されるストリーム・メソッドおよびストリーム・プロパティ
一般的に使用されるメソッドには以下のものがあります。
一般的に使用されるプロパティには以下のものがあります。
-
AtEnd — Read がデータ・ソースの末尾に到達すると true に設定されます。
-
Id — %Location で指定したエクステントの範囲でストリームのインスタンスを特定する一意の識別子。
-
Size — ストリームの現在のサイズ (ストリームのタイプに応じて、バイト数または文字数で表されます)。
個々の Stream メソッドおよびプロパティの詳細は、この章の始めに示したクラスの "インターシステムズ・クラス・リファレンス" のエントリを参照してください。
ストリームのインスタンス化
ストリーム・クラスをオブジェクト・プロパティとして使用する場合、ストリームを含むオブジェクトをインスタンス化すると、ストリームが暗黙的にインスタンス化されます。
ストリーム・クラスをスタンドアロン・オブジェクトとして使用する場合は、%New() メソッドを使用してストリームをインスタンス化します。
ストリーム・データの読み取りと書き込み
ストリーム・インタフェースの中核は、メソッド Read()、Write()、Rewind() と、プロパティ AtEnd および Size です。
以下の例では、一度に 100 文字ずつ Person.Memo ストリームのデータを読み取り、それをコンソールに書き込みます。len の値は参照によって渡され、毎回 Read の前に 100 にリセットされます。Read メソッドは len で指定された数の文字を読み取ろうとし、次に len を実際に読み取った実際の文字数に設定します。
Do person.Memo.Rewind()
While (person.Memo.AtEnd = 0) {
Set len = 100
Write person.Memo.Read(.len)
}
同様に、ストリームにデータを書き込むことができます。
Do person.Memo.Write("This is some text. ")
Do person.Memo.Write("This is some more text.")
変換テーブルの指定
タイプ %Stream.FileCharacterOpens in a new tab のストリームをロケールのネイティブ文字セット以外の文字セットで読み取ったり書き込んだりする場合は、ストリームの TranslateTable プロパティを設定する必要があります。変換テーブルの詳細は、"サーバ側プログラミングの入門ガイド" の “ローカライズのサポート” の章にある “既定の入出力テーブル” を参照してください。
ストリーム間のデータのコピー
すべてのストリームは CopyFrom() メソッドを含み、1 つのストリームが別のストリームからのデータを取り入れることができます。これを使用して、例えばストリーム・プロパティにファイルのデータをコピーできます。その場合、一方では %Library.FileOpens in a new tab クラスを使用します。これはオペレーティング・システム・コマンドのラッパであり、このクラスを使用することでファイルをストリームとして開くことができます。その場合のコードは以下のようになります。
// open a text file using a %Library.File stream
Set file = ##class(%File).%New("\data\textfile.txt")
Do file.Open("RU") // same flags as the OPEN command
// Open a Person object containing a Memo stream
// and copy the file into Memo
Set person = ##class(Person).%New()
Do person.Memo.CopyFrom(file)
Do person.%Save() // save the person object
Set person = "" // close the person object
Set file = "" // close the file
以下のように、Set コマンドを使用してデータをストリームにコピーすることもできます。
Set person2.Memo = person1.Memo
ここで、Person クラスの Memo プロパティはストリームの OREF を保持します。このコマンドは person1.Memo の内容を person2.Memo にコピーします。
Note:
このように Set を 2 つのストリームで使用しても、ストリーム間でコピーされるのはその内容のみで、OREF はコピーされません。これは、%Library の非推奨のストリーム・クラスの動作とは異なります。
ストリーム・データの挿入
一時ストリーム・クラス (そのデータは保存できない) とは別に、ストリームには一時的なストレージ場所と永続的なストレージ場所の両方があります。すべての挿入は一時的な場所に格納され、ストリームを保存する場合にのみ永続的に格納されます。ストリームへの挿入を開始した後でその挿入操作を中止すると、永続的な場所に保存されているデータは変更されません。
ストリームを作成する場合、挿入から開始し、MoveToEnd() を呼び出し、一時的なストリーム・データへの付加を継続します。ストリームを保存すると、データは永続的なストレージ場所に移動します。
以下に例を示します。
Set test = ##class(Test).%OpenId(5)
Do test.text.MoveToEnd()
Do test.text.Write("append text")
Do test.%Save()
この場合、test オブジェクトが保存されると、ストリームが永続ストレージに保存されます。
ストリームでのリテラル値の検索
ストリーム・インタフェースには、FindAt() メソッドが含まれています。このメソッドを使用すると、特定のリテラル値の場所を検索できます。このメソッドには、以下の引数があります。
method FindAt(position As %Integer, target, ByRef tmpstr, caseinsensitive As %Boolean = 0) as %Integer
以下はその説明です。
-
position は、検索を開始する位置です。
-
target は、検索するリテラル値です。
-
tmpstr は参照によって渡され、FindAt() の次回呼び出しに使用できる情報を返します。これは、同じストリームを繰り返し (最後にターゲットが見つかった位置から開始して) 検索するときに使用します。このシナリオでは、position を -1 に指定し、呼び出しのたびに tmpstr を参照で渡します。その後の継続的な FindAt() の呼び出しは、前回の呼び出しの停止位置から開始されます。
-
caseinsensitive は、大文字と小文字を区別する検索を実行するかどうかを指定します。既定では、このメソッドは大文字と小文字を区別しません。
このメソッドは、ストリームの先頭から開始したときの、この一致の位置を返します。一致する値が見つからない場合は、-1 を返します。
オブジェクト・アプリケーションでストリームを使用する
ストリーム・プロパティは、そのストリーム・プロパティを所有するオブジェクトによって作成される一時的なオブジェクトを介して操作されます。ストリームは、リテラル値 (ストリームを大きな文字列と見なす) の役割を果たします。2 つのオブジェクト・インスタンスは同じストリームを参照できません。
以下のクラス定義では、Person クラスに、ストリーム・プロパティである Memo プロパティがあります。
Class testPkg.Person Extends %Persistent
{
Property Name As %String;
Property Memo As %Stream.GlobalCharacter;
}
以下の ObjectScript コードの断片は新しい Person オブジェクトを作成し、Memo ストリームを暗黙的にインスタンス化します。その後、いくつかのテキストをストリームに書き込みます。
// create object and stream
Set p = ##class(testPkg.Person).%New()
Set p.Name = "Mo"
Do p.Memo.Write("This is part one of a long memo. ")
Do p.Memo.Write("This is part two of a long memo. ")
Do p.Memo.Write("This is part three of a long memo. ")
Do p.Memo.Write("This is part four of a long memo. ")
Do p.%Save()
Set id = p.%Id() // remember ID for later
Set p = ""
以下のコードの断片は Person オブジェクトを開いた後、ストリームの内容を書き込みます。オブジェクトを開くと、ストリーム・プロパティの現在の位置がストリームの先頭に設定されます。このコードでは、例示を目的として Rewind() メソッドを使用しています。
// read object and stream
Set p = ##class(testPkg.Person).%OpenId(id)
Do p.Memo.Rewind() // not required first time
// write contents of stream to console, 100 characters at a time
While (p.Memo.AtEnd = 0) {
Set len = 100
Write p.Memo.Read(.len)
}
Set p = ""
Note:
ストリーム・プロパティの内容を置き換える場合は、ストリームを巻き戻してから (ストリームの現在の位置が先頭になっていない場合)、Write() メソッドを使用して新しいデータをストリームに書き込みます。set p.Memo = ##class(%Stream.GlobalCharacter).%New() のように、%New() メソッドを使用して新しいストリーム・オブジェクトをインスタンス化し、それをストリーム・プロパティに割り当てないでください。この場合、古いストリーム・オブジェクトが孤立した状態でデータベース内に残ります。
SQL および ODBC へのストリーム・プロパティのプロジェクション
このドキュメントで前述したように、永続クラスは SQL テーブルとして投影されます。このようなクラスについては、文字列ストリーム・プロパティとバイナリ・ストリーム・プロパティが、BLOB (binary large objects) として SQL (および ODBC クライアント) に投影されます。
ストリーム・プロパティは、ODBC タイプの LONG VARCHAR (または LONG VARBINARY) で投影されます。ODBC ドライバ、または ODBC サーバは、BLOB を読み取りまたは書き込むための特別なプロトコルを使用します。通常は、手動で BLOB アプリケーションを記述する必要があります。標準レポート・ツールは、それらをサポートしません。
後続のサブセクションでは、SQL でストリーム・プロパティを使用する方法について説明します。ここでは、以下のトピックについて説明します。
ストリーム・フィールドは、SQL では以下のような制限があります。
ストリーム値のインデックスの詳細は、インターシステムズのサポート窓口Opens in a new tabまでお問い合わせください。
埋め込み SQL によるストリームの読み取り
埋め込み SQL を使用して、以下のようにストリームを読み取ることができます。
-
埋め込み SQL を使用して、ストリームの OID (オブジェクト ID) を選択します。
&sql(SELECT Memo INTO :memo FROM Person WHERE Person.ID = 12345)
これはストリームの OID を取得して、memo ホスト変数に代入します。
-
その後、ストリームを開き、通常どおりに処理します。
埋め込み SQL によるストリームの書き出し
埋め込み SQL を使用してストリームを書き込むには、複数のオプションがあります。挿入する値については、ストリームのオブジェクト参照 (OREF)、ストリームの OREF の文字列バージョン、または文字列リテラルを使用できます。
以下の例で、これらすべての方法を示します。これらの例では、ストリーム値が予期される、Prop1 という名前の列を持つ Test.ClassWStream という名前のテーブルがあるものとします。
以下の例では、オブジェクト参照を使用します。
///use an OREF
ClassMethod Insert1()
{
set oref=##class(%Stream.GlobalCharacter).%New()
do oref.Write("Technique 1")
//do the insert; this time use an actual OREF
&sql(INSERT INTO Test.ClassWStreams (Prop1) VALUES (:oref))
}
次の例では、オブジェクト参照の文字列バージョンを使用します。
///use a string version of an OREF
ClassMethod Insert2()
{
set oref=##class(%Stream.GlobalCharacter).%New()
do oref.Write("Technique 2")
//next line converts OREF to a string OREF
set string=oref_""
//do the insert
&sql(INSERT INTO Test.ClassWStreams (Prop1) VALUES (:string))
}
最後の例では、文字列リテラルを Prop1 ストリームに挿入します。
///insert a string literal into the stream column
ClassMethod Insert3()
{
set literal="Technique 3"
//do the insert; use a string
&sql(INSERT INTO Test.ClassWStreams (Prop1) VALUES (:literal))
}
Note:
文字列リテラルの最初の文字は数字にすることはできません。数字の場合、SQL は、これを OREF として解釈し、OREF として保存しようとします。このストリームは OREF ではないため、これは SQL -415 エラーになります。