Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

ストリームを使用した作業

ストリームは、大量のデータ (長い文字列の制限以上) を保存する方法を提供します。ストリーム・プロパティは、あらゆるオブジェクト・クラスで定義できます。スタンドアロンのストリーム・オブジェクトは、メソッドの引数や返り値として使用するなど、別の用途に定義することもできます。この章では、ストリームおよびストリーム・プロパティについて説明します。ここでは、以下のトピックについて説明します。

このドキュメントをオンラインで表示している場合は、このドキュメントの "序文" を使用すると、関連のあるトピックをすばやく見つけることができます。

ストリーム・クラスの概要

Caché には、以下のストリーム・クラスが用意されています。

これらのクラスはすべて、共通のストリーム・インタフェースを定義する %Stream.ObjectOpens in a new tab を継承します。

%Library パッケージにもストリーム・クラスが含まれていますが、こちらは非推奨です。クラス・ライブラリには追加のストリーム・クラスが含まれていますが、一般的な使用を目的としたものではありません。

ストリーム・クラスはオブジェクト・クラスです。したがって、ストリームはオブジェクトになります。

Important:

これらのクラスのメソッドの多くは、ステータス値を返します。すべての場合において、詳細はクラス・リファレンスを参照してください。メソッドがステータス値を返す場合、コードで、戻り値をチェックして適切に処理する必要があります。同様に、%Stream.FileCharacterOpens in a new tab および %Stream.FileBinaryOpens in a new tab に対して、Filename プロパティを設定した場合は、%objlasterror を調べてエラーをチェックする必要があります。

ストリーム・プロパティの宣言

Caché は、バイナリ・ストリームと文字ストリームの両方をサポートします。バイナリ・ストリームは、%BinaryOpens in a new tab タイプと同種のデータを含み、写真などの非常に大規模なバイナリ・オブジェクトを想定しています。同様に、文字ストリーム は、%StringOpens in a new tab タイプと同種のデータを含み、大量のテキストの保存を目的としています。文字ストリームは、文字列と同様に、クライアント・アプリケーション内で Unicode 変換を受ける可能性があります。

ストリーム・データは、ストリーム・プロパティの定義に応じて、外部ファイルまたは Caché グローバルのいずれかに保存できます (またはまったく保存しないこともできます)。

最初の 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 という名前のグローバルに保存されます。

ストリーム・インタフェースの使用法

すべてのストリームは、ストリームに含まれるデータの操作に使用されるメソッドおよびプロパティのセットを継承します。次のセクションでは多用するメソッドとプロパティの一覧を示し、それらの具体的な使用例をそれ以降のセクションで示します。項目は以下のとおりです。

Important:

これらのクラスのメソッドの多くは、ステータス値を返します。すべての場合において、詳細はクラス・リファレンスを参照してください。メソッドがステータス値を返す場合、コードで、戻り値をチェックして適切に処理する必要があります。同様に、%Stream.FileCharacterOpens in a new tab および %Stream.FileBinaryOpens in a new tab に対して、Filename プロパティを設定した場合は、%objlasterror を調べてエラーをチェックする必要があります。

一般的に使用されるストリーム・メソッドおよびストリーム・プロパティ

一般的に使用されるメソッドには以下のものがあります。

  • Read() — ストリームの現在の位置から、指定された数の文字を読み取ります。

  • Write() — 現在の位置から、ストリームにデータを追加します。この位置がストリームの末尾に設定されない場合は、既存のデータを上書きします。

  • Rewind() — ストリームの先頭に移動します。

  • MoveTo() — ストリーム内の特定の位置に移動します。

  • MoveToEnd() — ストリームの末尾に移動します。

  • CopyFrom() — コピー元のストリームの内容を、このストリームにコピーします。

  • NewFileName()%Stream.FileCharacterOpens in a new tab または %Stream.FileBinaryOpens in a new tab プロパティのファイル名を指定します。

一般的に使用されるプロパティには以下のものがあります。

  • AtEnd — Read がデータ・ソースの末尾に到達すると true に設定されます。

  • Id%Location で指定したエクステントの範囲でストリームのインスタンスを特定する一意の識別子。

  • Size — ストリームの現在のサイズ (ストリームのタイプに応じて、バイト数または文字数で表されます)。

個々の Stream メソッドおよびプロパティの詳細は、この章の初めに示したクラスの "インターシステムズ・クラス・リファレンス" のエントリを参照してください。

ストリーム・データの読み取りと書き込み

ストリーム・インタフェースの中核は、メソッド 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 プロパティを設定する必要があります。変換テーブルの詳細は、"Caché プログラミング入門ガイド" の “ローカライズのサポート” の章にある “既定の入出力テーブル” を参照してください。

ストリーム間のデータのコピー

すべてのストリームは 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 はコピーされません。ストリームの従来の実装 (%AbstractStreamOpens in a new tab%FileBinaryStreamOpens in a new tab%FileCharacterStreamOpens in a new tab%GlobalBinaryStreamOpens in a new tab、および %GlobalCharacterStreamOpens in a new tab を使用) ではこの動作は異なり、Set コマンドをこのコンテキストで使用すると OREF がコピーされていました。

ストリーム・データの挿入

一時的なストリーム・クラス (データは保存できません) とは別に、ストリームには一時的なストレージ場所と永続的なストレージ場所の両方があります。すべての挿入は一時的な場所に格納され、ストリームを保存する場合にのみ永続的に格納されます。ストリームへの挿入を開始した後でその挿入操作を中止すると、永続的な場所に保存されているデータは変更されません。

ストリームを作成する場合、挿入から開始し、MoveToEnd() を呼び出し、一時的なストリーム・データへの付加を継続します。ただし、ストリームの保存後は、データは永続的なストレージ場所に移動します。その後でこのストリームを再ロードして挿入を開始すると、データは一時的なストレージ領域に挿入され、永続的に格納されているデータには付加されません。

データを付加するこの動作を実行するには、一時的なストリームを作成する必要があります。以下はその例です。

    Set test = ##class(Test).%OpenId(5)
    Set tmpstream = ##class(%Stream.GlobalCharacter).%New()
    Do tmpstream.CopyFrom(test.text)
    Do tmpstream.MoveToEnd()
    Do tmpstream.Write("append text")
    Set test.text = tmpstream
    Set tmpstream = ""
    // Now do whatever you want with the test object

この例では、必要なタイプの一時的なストリームを作成して、Test オブジェクトに格納したストリームからデータをコピーし、新規ストリームの一時的な格納領域にそのデータを配置します。このストリームにデータを追加した後、Test オブジェクトにその OREF を格納し、参照カウントを正確に維持するためにストリームを閉じます。

ストリームでのリテラル値の検索

ストリーム・インタフェースには、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 を返します。

ストリームの保存

ストリーム・クラスをオブジェクト・プロパティとして使用する場合、ストリーム・データは、格納オブジェクトを保存する際に保存されます。

ストリーム・クラスをスタンドアロン・オブジェクトとして使用する場合、ストリーム・データを保存するには、%Save() メソッドを使用します。(一時的なストリーム・クラス — %Stream.TmpCharacterOpens in a new tab および %Stream.TmpBinaryOpens in a new tab — では、このメソッドは即座に制御を戻し、データを保存しないことに注意してください。)

オブジェクト・アプリケーションでストリームを使用する

ストリーム・プロパティは、そのストリーム・プロパティを所有するオブジェクトによって作成される一時的なオブジェクトを介して操作されます。ストリームは、リテラル値 (ストリームを大きな文字列と見なす) の役割を果たします。2 つのオブジェクト・インスタンスは同じストリームを参照できません。

以下の例では、長いメモが作成されて、コンソールに書き込まれます。

    // create object and stream
    Set p = ##class(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 10000 of a long memo")
    Do p.%Save()
    Set p = ""

    // read object and stream
    Set p = ##class(Person).%Open(oid)
    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 = ""

gzip ファイルに使用するストリーム・クラス

%StreamOpens in a new tab パッケージでは、特殊なストリーム・クラス %Stream.FileBinaryGzipOpens in a new tab%Stream.FileCharacterGzipOpens in a new tab も定義されています。このクラスは、gzip ファイルを対象とする読み込みと書き込みに使用できます。これらは前述の、同じインタフェースを使用します。以下の点に注意してください。

  • これらのクラスについては、圧縮されていないサイズを Size プロパティが返します。Size プロパティにアクセスすると、Caché は、ファイルのサイズを計算するためにデータを読み込みます。これは、負荷の高い操作になることがあります。

  • Size プロパティにアクセスすると、Caché はストリームを先頭の位置に巻き戻します。

SQL および ODBC へのストリーム・プロパティのプロジェクション

このドキュメントで前述したように、永続クラスは SQL テーブルとして投影されます。このようなクラスについては、文字列ストリーム・プロパティとバイナリ・ストリーム・プロパティが、BLOB (binary large objects) として SQL (および ODBC クライアント) に投影されます。

ストリーム・プロパティは、ODBC タイプの LONG VARCHAR (または LONG VARBINARY) で投影されます。ODBC ドライバ、または ODBC サーバは、BLOB を読み取りまたは書き込むための特別なプロトコルを使用します。通常は、手動で BLOB アプリケーションを記述する必要があります。標準レポート・ツールは、それらをサポートしません。

後続のサブセクションでは、SQL でストリーム・プロパティを使用する方法について説明します。ここでは、以下のトピックについて説明します。

ストリーム・フィールドは、SQL では以下のような制限があります。

  • WHERE 節の中では、いくつかの例外を除き、ストリーム値を使用できません。詳細は、"Caché SQL リファレンス" の "WHERE 節" を参照してください。

  • ストリームを含む複数の行を UPDATE (更新)、または INSERT (挿入) できません。一行ごとに操作を行う必要があります。

ストリーム値のインデックスの詳細は、インターシステムズのサポート窓口Opens in a new tabまでお問い合わせください。

埋め込み SQL によるストリームの読み取り

埋め込み SQL を使用して、以下のようにストリームを読むことができます。

  1. 埋め込み SQL を使用して、ストリームの ID を選択します。

      &sql(SELECT Memo INTO :memo FROM Person WHERE Person.ID = 12345)
    
    

    これはストリームの ID を取得して、memo ホスト変数に代入します。

  2. その後、ストリームを開き、通常どおりに処理します。

埋め込み 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 エラーになります。

FeedbackOpens in a new tab