Question
· Sep 26, 2021

Modifying %Stream contents

I have a %Stream that I want to insert some text into the middle of.  I create a new stream called pNewContentStream from the original stream, then I do a MoveTo in pNewContentStream to get to the byte position I want to insert into but when I do my Write, my pNewContentStream gets obliterated with only the text that I wrote, the original content goes away and all I'm left with is my Write text.

 

Method AddContentTypeCode4(pContentStream As %Stream.GlobalCharacter, Output pNewContentStream As %Stream.GlobalCharacter) As %Status
{
Set tStatus = $$$OK
try {
Set tTemp = pContentStream.Read()
$$$HSTRACE("AddContentTypeCode4[1]","tTemp",tTemp)
Set pNewContentStream=##class(%GlobalCharacterStream).%New()
$$$HSTRACE("New Stream")
Set tStatus = pNewContentStream.CopyFrom(pContentStream)
$$$HSTRACE("AddContentTypeCode4[2]","tStatus",tStatus)
Do pNewContentStream.Rewind()
$$$HSTRACE("AddContentTypeCode4[3]","pContentStream,pNewContentStream",pContentStream,pNewContentStream)
Set tLocatorString = "<ns2:Description>"
Set tInsertPoint = pContentStream.FindAt(1,tLocatorString,.tStr,0)
Set tInsertPoint = tInsertPoint+$LENGTH(tLocatorString)
$$$HSTRACE("AddContentTypeCode4[4]","tInsertPoint,pNewContentStream",tInsertPoint,pNewContentStream)
Set tStatus = pNewContentStream.Rewind()
Set tStatus = pNewContentStream.MoveTo(tInsertPoint)
$$$HSTRACE("AddContentTypeCode4[5]","tStatus",tStatus)
Set tStatus = pNewContentStream.Write(..ContentTypeCodeInsertable)
$$$HSTRACE("AddContentTypeCode4[6]","tStatus,pContentStream,pNewContentStream",tStatus,pContentStream,pNewContentStream)
Do pContentStream.MoveTo(tInsertPoint)
Set tRemain = pContentStream.Read()
Do pNewContentStream.Write(tRemain)
    
     $$$HSTRACE("AddContentTypeCode4[n]","pContentStream,pNewContentStream",pContentStream,pNewContentStream)
     /// Set pNewContentStream.ContentType = tContentTypeCode 
catch ex {
Set tStatus = ex.AsStatus()
}

The trace labeled "AddContentTypeCode4[6]" shows tStatus = 1, pContentStream is intact and is as expected, pNewContentStream contains whatever was in  ..ContentTypeCodeInsertable

What I was hoping to happen was at least having the beginning of pContentStream, then have the contents of ..ContentTypeCodeInsertable but instead I only get the contents of ..ContentTYpeCodeInsertable.  Any suggestions?  Thanks!

Marlin

Product version: HealthShare 2020.1
Discussion (17)1
Log in or sign up to continue
set old = ##class(%Stream.TmpCharacter).%New()
do old.Write("This is my text")

So, now you have an old stream, "This is my text" but want to have a new stream as "This is my NEW text".

set new = ##class(%Stream.TmpCharacter).%New()
do old.Rewind()
set pos = 10 // This is my
do new.Write(old.Read(pos)), new.Write(" NEW"), new.Write(old.Read(old.Size-pos))

And now, check the resulty

do new.Rewind()
write new.Read(new.Size) --> This is my NEW text

@Marlin Mixon 
 It is just not possible the way you tried. Because: (from class docs)

Move to this position in the stream. If this suceeds then return true, else return false. Note this implementation is not efficient because it searches from the start of the stream,

This means it does a Rewind() and a Read(position) 

• method Write(data As %RawString) as %Status

Appends the string data to the stream and advances the current stream position by the number of characters in data.

Note that a write operation immediately following a read or rewind will clear out the existing data in the stream.

@Robert: Thanks.  I'll study this to get a better idea where I went wrong!

@Julius: That works.  Showing my revised code:

Method AddContentTypeCode5(pContentStream As %Stream.GlobalCharacter, Output pNewContentStream As %Stream.GlobalCharacter) As %Status
{
Set tStatus = $$$OK
try {
Set pNewContentStream=##class(%GlobalCharacterStream).%New()
Set tLocatorString = "<ns2:Description>"
Set tInsertPoint = pContentStream.FindAt(1,tLocatorString,.tStr,0)-1
Do pContentStream.Rewind()
Do pNewContentStream.Write(pContentStream.Read(tInsertPoint)), pNewContentStream.Write(..ContentTypeCodeInsertable), pNewContentStream.Write(pContentStream.Read(pContentStream.Size-tInsertPoint))
$$$HSTRACE("AddContentTypeCode5","pNewContentStream,tInsertPoint,pContentStream",pNewContentStream,tInsertPoint,pContentStream)
catch ex {
Set tStatus = ex.AsStatus()
}
Quit tStatus
}

If you create a class, you can it declare as a hidden class, see

https://docs.intersystems.com/iris20211/csp/docbook/DocBook.UI.Page.cls?...

Class My.Class Extends What.Ever [ Hidden ]
{
}

will be a hidden class.  

For your own classes you can adjust this class keyword as you like but for the system classes - there is no chance, they lie somwhere on ISC servers (and, but this is my very own opinion, not very wise. First, I would like to read the documentation for the version I have installed (and not always the latest version) and second, I would like to read the doc everywhere! For example, I have a 10 hour flight, and want to work. And in case, a server only has a  local LAN access, then you have no docu!).

and second, I would like to read the doc everywhere! For example, I have a 10 hour flight, and want to work. And in case, a server only has a local LAN access, then you have no docu!).

I fully support it.
But I'm afraid now, apart from reading the documentation in PDF format, you can forget about local documentation ("DOCBOOK" database) with normal search and navigation. It's a pity..