fopen(), freadstr()...

138 views
Skip to first unread message

timepro timesheet

unread,
Jan 3, 2022, 5:42:31 AMJan 3
to
existing file name: custbill.txt
lines: 104 (each line varying no. of characters).
( <cr> after end of each line )
there may be blank lines too.
-with fopen(),freadstr() how to assign the text of each line (lines 1 to 104) to each new variable.

e.g.
textline1=the full text/words of the 1st line in custbill.txt
textline2=the full text/characters of the 2nd line
...
textline26=the full text/words of the 26th line
...
textline104=the full text/words of the 104th line in custbill.txt

thank you.

poopall

unread,
Jan 4, 2022, 8:20:33 AMJan 4
to
Why would you not assign each line to an element in an array

timepro timesheet

unread,
Jan 4, 2022, 10:04:43 AMJan 4
to
poopall:

the xxxxx.txt file is created by the user. (i wouldn't know the contents of the file.)
line 1 will have the user defined/typed 'font name'
line 2 will have the user defined 'font size'
line 87 will have the 'style'
...
line 104 will...

in the bill print module of my app, i have to read each line and assign that as the cosmetics (font,size,...)
i use pagescript32 functions for my output design.
e.g.
pssetfont('fontname' will be line1 of xxx.txt, 'style' will be line 2, 'size' will be line 87...,xxx,yyy)
after getting the values, it would process as pssetfont('arial',1,11,....)
assigning to a variable or element in an array...i can code either way.

*
i just do not know the syntax on how to read each line from the filename.txt.
what is the syntax to read each line from filename.txt and assign them to a variable/array element.
*

thank you

Michael Hagl

unread,
Jan 4, 2022, 11:01:21 AMJan 4
to
Hi,

you can do:

aTextArr := TxtFile2Array("custbill.txt")

****************************************************************************************************************************
FUNCTION TxtFile2Array(cDatei,nALen,nCLen,lMax,lKommFilter,aRest,cTestLeft,bFilter,lLtrim,lAnsiTest)
LOCAL i, x
LOCAL hDatei
LOCAL lOk := .t.
DEFAULT lKommFilter TO .f.
DEFAULT lLtrim TO .t.
DEFAULT lAnsiTest TO .t.
IF !File(cDatei)
lOk := .f.
ENDIF
DEFAULT aRest TO {}
IF !(nAlen == NIL)
aRest := ARRAY(nALen)
ENDIF
IF lMax == NIL
lMax := .f.
ENDIF

IF lOk
i := 0
hDatei := FOpen(cDatei)

IF hDatei > 0
DO WHILE !FEof(hDatei)
i ++
x := FReadLine(hDatei)
IF AllTrim(x) == Chr(26)
EXIT
ENDIF
IF Right(x,1) == Chr(26)
x := Left(x,Len(x)-1)
ENDIF

IF !Empty(cTestLeft)
IF !(Left(x,Len(cTestLeft)) == cTestLeft)
LOOP
ENDIF
ENDIF

IF !Empty(bFilter)
IF !Eval(bFilter,x)
LOOP
ENDIF
ENDIF

IF lKommFilter .and. Left(x,2) == "//"
LOOP
ENDIF
IF lAnsiTest .and. IsAnsiString(x)
x := Ansi2Ascii(x)
ENDIF
IF nAlen == NIL
AAdd(aRest,Iif(lLtrim,Formkey(x,nCLen),x))
ELSE
IF i > nALen
EXIT
ENDIF
aRest[i] := Iif(lLtrim,Formkey(x,nCLen),x)
ENDIF
ENDDO
FClose(hDatei)
ENDIF
IF !(nAlen == NIL)
IF i < nALen
lOk := .f.
ENDIF
ENDIF
ENDIF
IF !lOk
IF nALen == NIL
nALen := Len(aRest)
ENDIF
FOR i := 1 TO nAlen
IF aRest[i] == NIL
aRest[i] := Space(nCLen)
ENDIF
NEXT i
ENDIF
IF lMax
nCLen := AmaxStrLen(aRest)
nALen := Len(aRest)
FOR i := 1 TO nAlen
aRest[i] := Iif(lLtrim,Formkey(aRest[i],nCLen),Left(aRest[i],nCLen))
NEXT i
ENDIF
RETURN aRest


timepro timesheet

unread,
Jan 5, 2022, 12:22:30 AMJan 5
to
looks like a 'ready-to-use' function
thank you: in...@hagl.de

:few queries please,
instead of 'DEFAULT lKommFilter TO .f. ' , if i code 'lKommFilter=.f.' , will anything differ?
also, instead of 'DEFAULT aRest TO {} ', i code 'priv arest[0]; afill(arest,''")' ...
you have not incorporated checking for the <cr>, or is it not required?

your code:
'aTextArr := TxtFile2Array("custbill.txt")
FUNCTION TxtFile2Array(cDatei,nALen,nCLen,lMax,lKommFilter,aRest,cTestLeft,bFilter,lLtrim,lAnsiTest) '
-but TxtFile2Array("custbill.txt") is sending just 1 parameter to Txtfile2array() - the filename.

regards

Michael Hagl

unread,
Jan 5, 2022, 2:58:44 AMJan 5
to
Hi,

this is a short version of function and I forgot the following functions.
********************************************
FUNCTION TxtFileToArray(cDatei)
LOCAL i, x, hDatei
LOCAL aRest := {}
IF File(cDatei)
i := 0
hDatei := FOpen(cDatei)
IF hDatei > 0
DO WHILE !FEof(hDatei)
i ++
x := FReadLine(hDatei)
IF AllTrim(x) == Chr(26)
EXIT
ENDIF
IF Right(x,1) == Chr(26)
x := Left(x,Len(x)-1)
ENDIF
AAdd(aRest,Iif(lLtrim,Formkey(x,nCLen),x))
ENDDO
FClose(hDatei)
ENDIF
ENDIF
RETURN aRest

*****************
FUNCTION FReadLine(nHandle,cEol)
LOCAL cLine
DEFAULT cEol TO Chr(10)
HB_FreadLine(nHandle,@cLine,cEol)
IF Right(cLine,1) == Chr(13)
RETURN Left(cLine,Len(cLine)-1)
ENDIF
RETURN cLine
****************************************
**********************************************************************
/* Usage: fbof(handle) -> lStatus feof(handle) -> lStatus
Params: int handle - A handle returned from a previous call to
fopen() or fcreate().
Returns:
TRUE if the file pointer is at the beginning (fbof) or at
the end (feof) of the file associated with <handle>, FALSE if not
*/
FUNCTION FEof(nHandle)
************************
LOCAL nPos := FSeek(nHandle,0,1)
LOCAL nBot := FSeek(nHandle,0,2)
LOCAL lOk := (nPos >= nBot)
FSeek(nHandle,nPos,0)
RETURN lOk
*************************************************************************
FUNCTION fBof(nHandle)
**********************
LOCAL nPos := FSeek(nHandle,0,1)
LOCAL lOk := (nPos == 0)
RETURN lOk
******************************************************************************************


But you can also use Memoread() Function:
***********************************************************************
FUNCTION TxtFile2ArrayM(cDatei,nMaxLineLen)
LOCAL cText, nLines, i
LOCAL aRest := {}
DEFAULT nMaxLineLen TO 250
IF File(cDatei)
cText := MemoRead(cDatei)
nLines := MlCount(cText,nMaxLineLen)
ASize(aRest,nLines)
FOR i := 1 TO nLines
aRest[i] := Memoline(cText,nMaxLineLen,i)
NEXT
ENDIF
RETURN aRest

timepro timesheet

unread,
Jan 5, 2022, 4:31:26 AMJan 5
to
> But you can also use Memoread() Function:
> ***********************************************************************
> FUNCTION TxtFile2ArrayM(cDatei,nMaxLineLen)
> LOCAL cText, nLines, i
> LOCAL aRest := {}
> DEFAULT nMaxLineLen TO 250
> IF File(cDatei)
> cText := MemoRead(cDatei)
> nLines := MlCount(cText,nMaxLineLen)
> ASize(aRest,nLines)
> FOR i := 1 TO nLines
> aRest[i] := Memoline(cText,nMaxLineLen,i)
> NEXT
> ENDIF
> RETURN aRest


thank you in...@hagl.de

FUNCTION TxtFile2ArrayM(cDatei,nMaxLineLen) was just what i was looking for.
tested it, works ok. only 13 lines of code (less is more).

but, how to determine the no. of lines in the/any .txt file.
(your e.g. DEFAULT nMaxLineLen TO 250 ) my users may have more/less no. of lines.
btw: i had never used Memoread,Mlcount,MemoLine till now.

regards

Michael Hagl

unread,
Jan 5, 2022, 5:19:40 AMJan 5
to
Hi,
> but, how to determine the no. of lines in the/any .txt file.
I dont undertand.
MlCount(cText,nMaxLineLen,,,iif(nMaxLineLen>254,.t.,.f.)) returns the number of lines in the text file.

nMaxLineLen is max length of a text line. You should set it higher than the length of the longest line. You can set it to 1000 or bigger, but when set higher than 254 you have to set the fifth param to .t.

Do you not have a function description for xHb?
***************************************************************************************************
MLCount( <cString> , ;
[<nLineLen>] , ;
[<nTabSize>] , ;
[<lWrap>] , ;
[<lLongLines>] ) --> nLineCount

Arguments
<cString>
A character string or memo field to be counted. It can be a formatted text string that includes Tab and Hard/Soft carriage return characters.
<nLineLen>
A numeric value specifying the number of characters per line. It is usually a value between 4 and 254. If <nLineLen> is larger than 254 characters, parameter <lLongLines> must be set to .T. (true). The default value for <nLineLen> is 79.
<nTabSize>
A numeric value specifying the number of blank spaces the Tab character should be expanded to. It defaults to 4 blank spaces.
<lWrap>
A logical value indicating if word wrapping should be applied to <cString> when lines are counted. The default value is .T. (true), resulting in text lines being counted that contain whole words only. When a word does not fit entirely to the end of a text line, it is wrapped to the next text line. Passing .F. (false) for this parameter turns word wrapping off so that only lines ending with a hard carriage return are counted.
<lLongLines>
This parameter defaults to .F. (false). It must be

Michael Hagl

Message has been deleted

timepro timesheet

unread,
Jan 5, 2022, 6:11:04 AMJan 5
to
thanks michael:
my bad. there it was in your example: nLines := MlCount(cText,nMaxLineLen)

this will now allow my users to set their own fonts/size/style... to their invoice print.
(post reading the .txt file & assigning the values to each array element)

i use pagescript32 for designing reports/outputs.
pssetfont(array[element1]as font, array[element17] as style, element2 as size...,xxx,yyy)
after getting the values, it would process then as e.g. pssetfont(arial,1,11,....)
the best part is, if the user has typed in any undecipherable font name, size,...in their .txt file,
pssetfont() will instead use as default a standard font or the previous proper assigned font...
(preventing crash or gibberish output)

appreciate your time & efforts.

FP

unread,
Jan 10, 2022, 8:01:07 AMJan 10
to
Don't you have hb_aTokens() in xHarbour?

Dan

unread,
Jan 11, 2022, 2:57:05 PMJan 11
to
Il 10/01/2022 14:01, FP ha scritto:
> Don't you have hb_aTokens() in xHarbour?
token() and related functions from ct.lib.
Dan
Reply all
Reply to author
Forward
0 new messages