前の関連記事:LibreOffice5(109)子要素にフォルダしか持たないドキュメント内フォルダ
インプットストリームから取得できるバイト数が0になっている
LibreOffice5(103)ファイルシステムストレージのサービスとインターフェイスの一覧
これをみるとファイルシステムストレージからインプットストリームを取得できるのは、XStorageインターフェイスのcloneStreamElement()メソッドかopenStreamElement()メソッドかXNameAccessインターフェイスのgetByName()メソッドになります。
filesystemstoragefactory = smgr.createInstanceWithContext('com.sun.star.embed.FileSystemStorageFactory', ctx) filesystemstorage = filesystemstoragefactory.createInstanceWithArguments((sourcedir, ElementModes.READ)) # ファイルシステムストレージを取得。 for name in filesystemstorage: if filesystemstorage.isStreamElement(name): xstream = filesystemstorage.cloneStreamElement(name) inputstream = xstream.getInputStream() print(inputstream.available()) # 0 xstream = filesystemstorage.openStreamElement(name, ElementModes.READ) inputstream = xstream.getInputStream() print(inputstream.available()) # 0 xstream = filesystemstorage[name] inputstream = xstream.getInputStream() print(inputstream.available()) # 0sourcedirはpyファイルが入ったフォルダへのfileurlです。
ElementModesは定数です。
データの入っているファイルに対しても、これを実行するといずれもavailable()では0が返ってきてしまいます。
XHierarchicalStorageAccessインターフェイスのメソッドでもインプットストリームを取得できそうでしたが、openStreamElementByHierarchicalName()メソッドに渡すストリームのパスの方法がわかりませんでした。
XStorageインターフェイスのcloneStreamElement()メソッドの戻り値のインプットストリームからデータを取得可能
XStorageインターフェイスのopenStreamElement()メソッドとXNameAccessインターフェイスのgetByName()メソッドはXStreamインターフェイスしか実装していないオブジェクトが返ってこないのに対して、XStorageインターフェイスcloneStreamElement()メソッドでは一時ファイルが返ってくることがわかりました。
一時ファイルはXSeekableインターフェイスをもっています。
filesystemstoragefactory = smgr.createInstanceWithContext('com.sun.star.embed.FileSystemStorageFactory', ctx) filesystemstorage = filesystemstoragefactory.createInstanceWithArguments((sourcedir, ElementModes.READ)) # ファイルシステムストレージを取得。 for name in filesystemstorage: if filesystemstorage.isStreamElement(name): xstream = filesystemstorage.cloneStreamElement(name) inputstream = xstream.getInputStream() print(inputstream.available()) # 0 print(inputstream.getLength()) # 263 print(inputstream.getPosition()) # 263getLength()メソッドでインプットストリームの長さがわかります。
getPosition()メソッドでシークポインタの位置が取得できます。
今回の場合はいずれも263が返ってきているのに、available()メソッドでは0なので、0バイトしか読み込めていないのがわかります。
これをseek()メソッドでシークポインタをストリームの先端に移動させます。
inputstream.seek(0) # シークポインタをストリームの先頭に移動させる。 print(inputstream.getPosition()) # 0 print(inputstream.available()) # 263これでストリームの先頭から全部取得できました。
しかし一時ファイルを利用するこの方法はディスクにあるファイルをまたディスクにコピーする無駄が生じるので、SimpleFileAccessのopenFileRead()メソッドでインプットストリームを取得する方法を思いつきましたが、結局それはうまくいきませんでした。
SimpleFileAccessのopenFileRead()メソッドの戻り値のインプットストリーム
fileurlを取得できるのならSimpleFileAccessのopenFileRead()メソッドでインプットストリームが取得できます。
def macro(): ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 tcu = smgr.createInstanceWithContext("pq.Tcu", ctx) # サービス名か実装名でインスタンス化。 simplefileaccess = smgr.createInstanceWithContext("com.sun.star.ucb.SimpleFileAccess", ctx) # SimpleFileAccess doc = XSCRIPTCONTEXT.getDocument() # ドキュメント。 inputstream = simplefileaccess.openFileRead(doc.getURL()) tcu.wtree(inputstream)このopenFileRead()メソッドの戻り値のサービスとインターフェイスの一覧を取得してみました。
doc.getURL()はディスク上に保存したドキュメントのときしか戻り値が返ってこないので、保存していないドキュメントに対して実行すると7行目でInteractiveAugmentedIOExceptionになります。
├─.io.XInputStream
│ long available()
│ void closeInput()
│ long readBytes( [out] [byte] aData,
│ [in] long nBytesToRead
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
│ long readSomeBytes( [out] [byte] aData,
│ [in] long nMaxBytesToRead
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
│ void skipBytes( [in] long nBytesToSkip
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
└─.io.XSeekable
hyper getLength()
hyper getPosition()
void seek( [in] hyper location
) raises ( .io.IOException,
.lang.IllegalArgumentException)
│ long available()
│ void closeInput()
│ long readBytes( [out] [byte] aData,
│ [in] long nBytesToRead
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
│ long readSomeBytes( [out] [byte] aData,
│ [in] long nMaxBytesToRead
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
│ void skipBytes( [in] long nBytesToSkip
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
└─.io.XSeekable
hyper getLength()
hyper getPosition()
void seek( [in] hyper location
) raises ( .io.IOException,
.lang.IllegalArgumentException)
XSeekableインターフェイスをもっているのでインプットストリームの長さとシークポインタの位置を確認できます。
inputstream = simplefileaccess.openFileRead("/".join((sourcedir, name))) print(inputstream.getLength()) # 263 print(inputstream.getPosition()) # 0 print(inputstream.available()) # 0sourcedirはフォルダへのfileurl、nameはpyファイル名です。
これは想定外の結果になりました。
ストリームの長さが263バイトで、シークポインタの位置が0バイト目なのに読み込めるバイト数が0になっていて理解できません。
openFileReadWrite()メソッドで取得したインプットストリームでも同じ結果でした。
SimpleFileAccessのopenFileReadWrite()とopenFileWrite()の戻り値のサービスとインターフェイスの一覧
def macro(): ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 tcu = smgr.createInstanceWithContext("pq.Tcu", ctx) # サービス名か実装名でインスタンス化。 simplefileaccess = smgr.createInstanceWithContext("com.sun.star.ucb.SimpleFileAccess", ctx) # SimpleFileAccess doc = XSCRIPTCONTEXT.getDocument() # ドキュメント。 xstream = simplefileaccess.openFileWrite(doc.getURL()) tcu.wtree(xstream)SimpleFileAccessのopenFileReadWrite()とopenFileWrite()の戻り値のサービスとインターフェイスは同一でした。
object
├─.io.XAsyncOutputMonitor
│ void waitForCompletion()
├─.io.XInputStream
│ long available()
│ void closeInput()
│ long readBytes( [out] [byte] aData,
│ [in] long nBytesToRead
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
│ long readSomeBytes( [out] [byte] aData,
│ [in] long nMaxBytesToRead
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
│ void skipBytes( [in] long nBytesToSkip
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
├─.io.XOutputStream
│ void closeOutput()
│ void flush()
│ void writeBytes( [in] [byte] aData
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
├─.io.XSeekable
│ hyper getLength()
│ hyper getPosition()
│ void seek( [in] hyper location
│ ) raises ( .io.IOException,
│ .lang.IllegalArgumentException)
├─.io.XStream
│ .io.XInputStream getInputStream()
│ .io.XOutputStream getOutputStream()
└─.io.XTruncate
void truncate()
├─.io.XAsyncOutputMonitor
│ void waitForCompletion()
├─.io.XInputStream
│ long available()
│ void closeInput()
│ long readBytes( [out] [byte] aData,
│ [in] long nBytesToRead
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
│ long readSomeBytes( [out] [byte] aData,
│ [in] long nMaxBytesToRead
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
│ void skipBytes( [in] long nBytesToSkip
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
├─.io.XOutputStream
│ void closeOutput()
│ void flush()
│ void writeBytes( [in] [byte] aData
│ ) raises ( .io.IOException,
│ .io.BufferSizeExceededException,
│ .io.NotConnectedException)
├─.io.XSeekable
│ hyper getLength()
│ hyper getPosition()
│ void seek( [in] hyper location
│ ) raises ( .io.IOException,
│ .lang.IllegalArgumentException)
├─.io.XStream
│ .io.XInputStream getInputStream()
│ .io.XOutputStream getOutputStream()
└─.io.XTruncate
void truncate()
0 件のコメント:
コメントを投稿