I tried to make this code as short as possible without making it too cryptic. I wrote it as part of a very simple unit testing app I’m currently using to tests classes. You can find it here.
Yeah as Mike points out the built-in Clarion SystemStringClass has many methods that work the same as StringTheory so easiest way would be…
!*** after Global Includes embed point ***
include(‘SystemString.inc’),once
!*** declare a SystemStringClass object ***
sysString SystemStringClass
CODE
!*** load the sysString object with text (many ways to do this ***
sysString.FromString('Hello World')
sysString.ToFile(path() & '\Test.TXT')
SystemStringClass was introduced with C9, but wasn’t available in my installation of C9.1PE. It was when I upgraded to C11EE. I had the idea it was EE only, but it looks like it’s now also included in PE.
Anyway, this code should work in even older versions.
Mike
It’s probably more efficient to use CreateFile/WriteFile API calls like you did in CJSON, but in this case I wanted to use only Clarion code, just a personal preference for the TestApp project.
LEN(pStr) is called 4 times every Loop. There is a cost to that so change to do it once. It’s not CLIP() so can use SIZE(pStr) to simply get the defined size while LEN() pushes a Copy of the String on the Stack then measures it.
I also moved the Slice End calculation out of the CHOOSE() in ADD() to a variable. That allows the slice assignment Buf=pStr[:] end to be shorter than LEN(pStr)
lengthStr = SIZE(pStr)
LOOP pos = 1 TO lengthStr BY bufSize
endPos = pos + bufSize - 1
IF endPos > lengthStr THEN endPos = lengthStr.
dosFile.Buf = pStr[ pos : endPos ]
ADD(dosFile, endPos - pos + 1)
END
I would change the return to (),BOOL,PROC so caller can optionally check ()= True/False for Success/Failure. Here’s the complete code. I have not tested it.
StringToFile PROCEDURE (STRING pStr,STRING pFileName) !,BOOL,PROC
bufSize EQUATE(32768)
dosFile FILE,DRIVER('DOS'),CREATE
RECORD,PRE()
buf STRING(bufSize)
END
END
pos LONG,AUTO
endPos LONG,AUTO
lengthStr LONG,AUTO !Instead of LEN(pStr) x 4
CODE
dosFile{PROP:Name} = pFileName
CREATE(dosFile)
IF ~ERRORCODE() THEN OPEN(dosFile).
IF ERRORCODE() THEN
MESSAGE('Failed to Create and Open DosFile: '& pFileName &|
'||Error: '& ERRORCODE()&' '&ERROR()&'|File: '&ERRORFILE(),'StringToFile')
RETURN FALSE
END
lengthStr = SIZE(pStr) !or =LEN(CLIP(pStr)) removes trailing spaces
LOOP pos = 1 TO lengthStr BY bufSize
endPos = pos + bufSize - 1
IF endPos > lengthStr THEN endPos = lengthStr.
dosFile.Buf = pStr[ pos : endPos ]
ADD(dosFile, endPos - pos + 1)
END
CLOSE(dosfile)
RETURN True
!This code has NOT been tested at all ... This code has NOT been tested at all
Will this run measurably faster … probably not because memory operations, like LEN(), are so fast. Plus this is likely called with small strings and not 100’s of megabytes. I just like squeezing the drop, pretty soon your glass is only half empty.