Page 1 of 1
#PRIM_IOC.FileStream and StreamReader StreamWriter
Posted: Thu Jun 01, 2023 1:49 am
by Speedlime
Afternoon All.
I am reading a ZPL label document from the IFS, using the FileStream reader I am reading the data and replacing parts of it and placing the data into #Result variable. This works fine and I can pass that back from function to test form and view it in memobox and see the changed values.
I want to now write the Result data back to the ZPL file on the IFS, but I cannot find any documentation to do this. Can anyone help or have a example
This is how I am reading and changing the data
DEFINE_COM Class(#PRIM_IOC.FileStream) Name(#FileStream)
DEFINE_COM Class(#PRIM_IOC.StreamReader) Name(#Reader) Stream(#FileStream)
DEFINE_COM Class(#PRIM_DC.UnicodeString) Name(#String)
DEFINE_COM Class(#PRIM_DC.UnicodeString) Name(#InputFilePath)
DEFINE_COM Class(#PRIM_DC.UnicodeString) Name(#Result)
#InputFilePath := '/tmp/LKTEST/MyLabel.ZPL'
#FileStream.Path := #InputFilePath
DOWHILE Cond(#Reader.TryReadLine( #String ))
#Result += #String.ReplaceAll( "FO758,25" "FO758,50" ).ReplaceAll( "FO718,25" "FO718,50" ).ReplaceAll( "FO677,25" "FO677,50" ).ReplaceAll( "FO636,25" "FO636,50" ).ReplaceAll( "FO596,25" "FO596,50" ).ReplaceAll( "FO555,25" "FO555,50" ).ReplaceAll( "FO515,25" "FO515,50" ).ReplaceAll( "FO477,20" "FO477,50" ).ReplaceAll( "FO477,101" "FO477,151" ).ReplaceAll( "FO426,20" "FO426,50" ).ReplaceAll( "FO355,20" "FO355,50" ).ReplaceAll( "FO367,190" "FO367,220" ).ReplaceAll( "FO367,532" "FO367,562" )
ENDWHILE
Thanks in advance
Re: #PRIM_IOC.FileStream and StreamReader StreamWriter
Posted: Thu Jun 01, 2023 7:48 am
by Dino
I understand that this FileStream read sequentially, so you can append information but not update.
you can create a new file with the result (and delete original/rename it later), doing something like this:
Code: Select all
Function Options(*DIRECT)
Define_Com Class(#PRIM_IOC.FileStream) Name(#FileStream)
Define_Com Class(#PRIM_IOC.StreamReader) Name(#Reader) Stream(#FileStream)
Define_Com Class(#PRIM_DC.UnicodeString) Name(#String)
Define_Com Class(#PRIM_DC.UnicodeString) Name(#InputFilePath)
Define_Com Class(#PRIM_DC.UnicodeString) Name(#Result)
Define_Com Class(#prim_ioc.FileStream) Name(#OutputStream) Fileaccess(Write) Filemode(CreateNew) Fileshare(Write)
Define_Com Class(#prim_ioc.StreamWriter) Name(#Writer) Stream(#OutputStream) Encodingname('UTF-8')
#InputFilePath := '/tmp/LKTEST/MyLabel.ZPL'
#OutputStream.Path := '/tmp/MyLabeloutput.ZPL'
#FileStream.Path := #InputFilePath
Dowhile Cond(#Reader.TryReadLine( #String ))
#Result += #String.ReplaceAll( "FO758,25" "FO758,50" ).ReplaceAll( "FO718,25" "FO718,50" ).ReplaceAll( "FO677,25" "FO677,50" ).ReplaceAll( "FO636,25" "FO636,50" ).ReplaceAll( "FO596,25" "FO596,50" ).ReplaceAll( "FO555,25" "FO555,50" ).ReplaceAll( "FO515,25" "FO515,50" ).ReplaceAll( "FO477,20" "FO477,50" ).ReplaceAll( "FO477,101" "FO477,151" ).ReplaceAll( "FO426,20" "FO426,50" ).ReplaceAll( "FO355,20" "FO355,50" ).ReplaceAll( "FO367,190" "FO367,220" ).ReplaceAll( "FO367,532" "FO367,562" )
Endwhile
#Writer.WriteString Inputvalue(#Result)
Return
or :
Code: Select all
(....)
Dowhile Cond(#Reader.TryReadLine( #String ))
#Result := #String.ReplaceAll( "FO758,25" "FO758,50" ).ReplaceAll( "FO718,25" "FO718,50" ).ReplaceAll( "FO677,25" "FO677,50" ).ReplaceAll( "FO636,25" "FO636,50" ).ReplaceAll( "FO596,25" "FO596,50" ).ReplaceAll( "FO555,25" "FO555,50" ).ReplaceAll( "FO515,25" "FO515,50" ).ReplaceAll( "FO477,20" "FO477,50" ).ReplaceAll( "FO477,101" "FO477,151" ).ReplaceAll( "FO426,20" "FO426,50" ).ReplaceAll( "FO355,20" "FO355,50" ).ReplaceAll( "FO367,190" "FO367,220" ).ReplaceAll( "FO367,532" "FO367,562" )
#Writer.WriteLine Inputvalue(#Result)
Endwhile
(....)
but I must be missing something because the encoding is not producing the correct result.
I can see the original file i uploaded is in 819 encoding and the one I am producing is 37 so the result seems garbled.
Re: #PRIM_IOC.FileStream and StreamReader StreamWriter
Posted: Thu Jun 01, 2023 8:06 am
by Dino
saying so.....
this old code will do the work as well....
Code: Select all
Function Options(*DIRECT)
Define Field(#Result) Type(*NVARCHAR) Length(65535)
Def_List Name(#resultlist) Fields(#result) Type(*WORKING) Entrys(*MAX)
Use Builtin(TRANSFORM_FILE) With_Args(#resultlist '/tmp/MyLabel.ZPL' 'TU') To_Get(#IO$STS)
Selectlist Named(#resultlist)
#Result := #Result.ReplaceAll( "FO758,25" "FO758,50" ).ReplaceAll( "FO718,25" "FO718,50" ).ReplaceAll( "FO677,25" "FO677,50" ).ReplaceAll( "FO636,25" "FO636,50" ).ReplaceAll( "FO596,25" "FO596,50" ).ReplaceAll( "FO555,25" "FO555,50" ).ReplaceAll( "FO515,25" "FO515,50" ).ReplaceAll( "FO477,20" "FO477,50" ).ReplaceAll( "FO477,101" "FO477,151" ).ReplaceAll( "FO426,20" "FO426,50" ).ReplaceAll( "FO355,20" "FO355,50" ).ReplaceAll( "FO367,190" "FO367,220" ).ReplaceAll( "FO367,532" "FO367,562" )
Upd_Entry In_List(#resultlist)
Endselect
Use Builtin(TRANSFORM_LIST) With_Args(#resultlist '/tmp/MyLabelOutput.ZPL' 'TU') To_Get(#IO$STS)
Return
Re: #PRIM_IOC.FileStream and StreamReader StreamWriter
Posted: Thu Jun 01, 2023 11:02 pm
by Speedlime
Thanks for looking at this Dino,
I was going down the same path, however trying both options when using the writer my file is always blank.
I have tried taking the result (unicode string) and writing it as native string into a large nvarchar and using that in the write but no luck.
Used both WriteString and WriteLine on the writer.
Using #XPRIM_File to delete the file I am writing prior to rewriting it, if it exists in the directory. (Will need this functionality in the solution)
Function running on iSeries Server. Read one ZPL file alter and write to new ZPL file.
Code: Select all
FUNCTION Options(*DIRECT)
* File Stream to Read
DEFINE_COM Class(#PRIM_IOC.FileStream) Name(#FileStream)
DEFINE_COM Class(#PRIM_IOC.StreamReader) Name(#Reader) Stream(#FileStream)
DEFINE_COM Class(#PRIM_DC.UnicodeString) Name(#String)
* File Stream to Write
DEFINE_COM Class(#prim_ioc.FileStream) Name(#OutputStream) Fileaccess(Write) Filemode(CreateNew) Fileshare(Write)
DEFINE_COM Class(#prim_ioc.StreamWriter) Name(#Writer) Stream(#OutputStream) Encodingname('UTF-8')
* File / IFS File manipulation
DEFINE_COM Class(#XPRIM_File) Name(#IFSFILE)
DEFINE_COM Class(#PRIM_DC.UnicodeString) Name(#InputFilePath)
DEFINE_COM Class(#PRIM_DC.UnicodeString) Name(#OutputFilePath)
* Data Variables
DEFINE_COM Class(#PRIM_DC.UnicodeString) Name(#Result)
* Code here
#InputFilePath := '/tmp/LKTEST/BI2249350.ZPL'
#FileStream.Path := #InputFilePath
DOWHILE Cond(#Reader.TryReadLine( #String ))
#Result := #String.ReplaceAll( "FO758,25" "FO758,50" ).ReplaceAll( "FO718,25" "FO718,50" ).ReplaceAll( "FO677,25" "FO677,50" ).ReplaceAll( "FO636,25" "FO636,50" ).ReplaceAll( "FO596,25" "FO596,50" ).ReplaceAll( "FO555,25" "FO555,50" ).ReplaceAll( "FO515,25" "FO515,50" ).ReplaceAll( "FO477,20" "FO477,50" ).ReplaceAll( "FO477,101" "FO477,151" ).ReplaceAll( "FO426,20" "FO426,50" ).ReplaceAll( "FO355,20" "FO355,50" ).ReplaceAll( "FO367,190" "FO367,220" ).ReplaceAll( "FO367,532" "FO367,562" )
ENDWHILE
* Delete the existing file from the IFS
#IFSFILE.SetPath Directory('/tmp/lktest') Filepath('BI7777777.ZPL')
IF (#IFSFILE.Exists)
#IFSFILE.Delete
ENDIF
* Write the ammended ZPL data back to file
#OutputStream.Path := '/tmp/LKTEST/BI7777777.ZPL'
#Writer.WriteString Inputvalue(#Result)
#FP_NoteText := #Result.AsNativeString
EXCHANGE Fields(#FP_NoteText)
RETURN
Not sure if it is a encoding issue, but I thought UTF-8 should do the trick.
I am going to try the old school method now and see what results I get.
Will report back
Re: #PRIM_IOC.FileStream and StreamReader StreamWriter
Posted: Fri Jun 02, 2023 1:30 am
by Speedlime
Dino,
Old school wrote a record to the list but it was gibberish and the wrote that back gibberish to the file on the IFS. Concept worked but not how the data was handled.
Not sure the Input file format on the transform file ie 'TU' 'OU' ext are going to work for a ZPL block of data, which is essentially a block of mark-up language.
Example
Code: Select all
^XA^CF0,30^FO300,30^FDHU Label^FS^CF0,25^FO20,100^FDHU ID: 112345678000001107^FS^BY2.2,3,70^FO20,130^BCN,,N^FD112345678000001107^FS^FO20,230^FD60-Volt Cordless Electric Hedge Trimmer^FS^FO20,260^FD13^FS
^FO650,200^BQN,2,5^FDQA,^FS
^XZ
The best result was the reader picking up the file and reading and replacing the data and holding it in that unicodeString variable.
Going to keep trying things with the write /streamwriter, to get that data from the variable to the IFS in a readable format.
Thanks
LK
Re: #PRIM_IOC.FileStream and StreamReader StreamWriter
Posted: Fri Jun 09, 2023 7:43 pm
by Speedlime
Solution
As the streamwriter failed to work, I used #XPRIM_Binary
Convert string into Blob, write it as a file, pick it up and write as zpl file back to IFS.
ResultNVARCHAR hold the ammended data from the read in the above example
* Write the ammended ZPL data back to file
#Binary.FromStringUsingUTF8 String(#ResultNVARCHAR)
#STD_STRNG := #Binary.AsFile
* FROM BLOB
#BlobDocumentPath := #STD_STRNG.Trim
#Binary.FromFile Path(#BlobDocumentPath.Trim)
* Write ZPL file back to IFS using the original document Path
#Binary.AsFile Path(#ToDocumentPath.Trim) Errorinfo(#ErrorInfo)
Re: #PRIM_IOC.FileStream and StreamReader StreamWriter
Posted: Fri Jun 30, 2023 7:27 pm
by KEC
Often issues like this is because of codepage.
There are a selection of BIF's that deal with writing and appending to IFS very quicky and do have codepage handling
STM_FILE_OPEN
STM_FILE_READ
STM_FILE_WRITE
On the open, you can decide Read/Write/Append and Codepage. This way you can handle EBCDIC, where some more modern items want ASCII or even Unicode.
See:
https://docs.lansa.com/15/en/lansa015/i ... E_OPEN.htm
Re: #PRIM_IOC.FileStream and StreamReader StreamWriter
Posted: Tue Oct 31, 2023 12:32 am
by Dino
When using these primitives and similar like
Code: Select all
#XPRIM_JsonWriter
#Prim_Ioc.FileStream
#XPRIM_Binary.AsFile
#XPRIM_File
I have noticed that i was getting gibberish in the IBM, but correct information in the PC.
As the program was the same, copied the file from the PC to the IBM, and the only difference
between the text files (json data), where (unsurprisingly) the CCSID.
The one generated in the IBM by LANSA with this primitives was CCSID 37
The one generated in the PC and later copied to the IFS, was CCSID 1252
a simple:
Code: Select all
CHGATR OBJ('/tmp/aatest01.json') ATR(*CCSID) VALUE(1252)
fixed the issue for the file with problem.
So, I could do a CHGATR after using those primitives in the program to have the correct result...
If I try to do a CHGJOB CCSID(1252) ahead of running the program, or to change my JOBD, 1252 is not supported.
Wondering where you are supposed to set that default 1252 value for these files...
Kind regards