Written by

Question Marlin Mixon · 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

Comments

Julius Kavay · Sep 26, 2021
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
0
Marlin Mixon  Sep 26, 2021 to Julius Kavay

Thanks! I will check that out.

0
Robert Cemper · Sep 26, 2021

@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.

0
Marlin Mixon  Sep 26, 2021 to Robert Cemper

@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
}
0
Vitaliy Serdtsev · Sep 27, 2021

Or so:

<FONT COLOR="#0000ff">set </FONT><FONT COLOR="#800000">tmp </FONT><FONT COLOR="#000000">= </FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%IO.StringStream</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">%New</FONT><FONT COLOR="#000000">()
</FONT><FONT COLOR="#0000ff">do </FONT><FONT COLOR="#800000">tmp</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Write</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"This is my text"</FONT><FONT COLOR="#000000">)

</FONT><FONT COLOR="#0000ff">do </FONT><FONT COLOR="#800000">tmp</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Seek</FONT><FONT COLOR="#000000">(11)

</FONT><FONT COLOR="#0000ff">do </FONT><FONT COLOR="#800000">tmp</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Write</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">" NEW"</FONT><FONT COLOR="#000000">)

</FONT><FONT COLOR="#0000ff">do </FONT><FONT COLOR="#800000">tmp</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Rewind</FONT><FONT COLOR="#000000">() </FONT><FONT COLOR="#0000ff">write </FONT><FONT COLOR="#800000">tmp</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Read</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">tmp</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Size</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#008000">;This is my NEW text</FONT>

0
Robert Cemper  Sep 27, 2021 to Vitaliy Serdtsev

GREAT! 
%IO* is invisible in my local Class Reference

0
Jeffrey Drumm  Sep 27, 2021 to Vitaliy Serdtsev

Is there a special trick to making %IO visible? Selecting the "Percent Classes" checkbox doesn't do it.

0
Vitaliy Serdtsev  Sep 27, 2021 to Jeffrey Drumm

Yes. By default, a strictly defined list of packages/classes is displayed in IRIS for security purposes, but you can change this behavior locally.

0
Jeffrey Drumm  Sep 27, 2021 to Vitaliy Serdtsev

Is the mechanism for doing this something you can share? laugh

0
Vitaliy Serdtsev  Sep 27, 2021 to Jeffrey Drumm

No. I couldn't find how to do this in the documentation (probably I searched badly), so I don't publish here undocumented features anymore. But you can easily determine this from the source code.

0
Jeffrey Drumm  Sep 27, 2021 to Vitaliy Serdtsev

The "easy" options indicated by the source code do some interesting things, but showing %IO* isn't among them. I'll keep looking wink

0
Julius Kavay  Sep 27, 2021 to Jeffrey Drumm

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!).

0
Vitaliy Serdtsev  Sep 28, 2021 to Julius Kavay
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..
0
Robert Cemper  Sep 27, 2021 to Jeffrey Drumm

Hi @Jeffrey Drumm . there are  2 options

#1)
From SMP > Explorer > Classes in %SYS set filter to %IO*.cls  and Documentation

#2)
In Studio in NS %SYS load the class and show Class Documentation
[CTRL + SHIFT +F1]
and see the code. I have seen more thrilling constructs before.

 

0
Michel Bruyère  Oct 6, 2021 to Jeffrey Drumm

Strange, the %IO class belongs to our production/development namespace.

We use 'Cache for Windows 2018.1.4'.

0
Robert Cemper  Oct 6, 2021 to Michel Bruyère

It's a "FEATURE" of recent IRIS to hide deprecated code  sad

0