How to read a multi-dimensional array from a text file?

General Help regarding HMG, Compilation, Linking, Samples

Moderator: Rathinagiri

HGAutomator
Posts: 202
Joined: Thu Jul 16, 2020 5:42 pm
DBs Used: DBF

How to read a multi-dimensional array from a text file?

Post by HGAutomator »

Hi,

There are lots of functions that do this, already written. But the arrays aren't defined with an array syntax, inside the file.

Let's say you have a text file with

Code: Select all

{ ;
						{"First","First Item", ;
								{{"First SubItem",     "First SubItem from First", {||qout("First SubItem from First")}},;
                {"Second SubItem", "Second SubItem from First", {||qout("Second SubItem from First")}},;
                {"Third SubItem", "Third SubItem from First", {||qout("Third SubItem from First")}} } ;
						}, ;
						{"Second","Second Item", ;
								{{"First SubItem",     "First SubItem from Second", {||qout("First SubItem from Second")}},;	
               	{"Second SubItem", "Second SubItem from Second",  {||qout("Second SubItem from Second")}},;
               	{"Third SubItem", "Third SubItem from Second",  {||qout("Third SubItem from Second")}}  } ;
						}, ;
						{"Third","Third SubItem",0}, ;
						{"Fourth","Fourth SubItem",{||qout("Fourth SubItem")} }  ;
	}
or an assignment like

Code: Select all

MainArray_a := { ;
						{"First","First Item", ;
								{{"First SubItem",     "First SubItem from First", {||qout("First SubItem from First")}},;
                {"Second SubItem", "Second SubItem from First", {||qout("Second SubItem from First")}},;
                {"Third SubItem", "Third SubItem from First", {||qout("Third SubItem from First")}} } ;
						}, ;
						{"Second","Second Item", ;
								{{"First SubItem",     "First SubItem from Second", {||qout("First SubItem from Second")}},;	
               	{"Second SubItem", "Second SubItem from Second",  {||qout("Second SubItem from Second")}},;
               	{"Third SubItem", "Third SubItem from Second",  {||qout("Third SubItem from Second")}}  } ;
						}, ;
						{"Third","Third SubItem",0}, ;
						{"Fourth","Fourth SubItem",{||qout("Fourth SubItem")} }  ;
	}
(where we have MainArray_a declared as PUBLIC inside the calling routine).

How can we read this array from a text .txt file, and populate it in an array variable inside the program?
User avatar
AUGE_OHR
Posts: 2117
Joined: Sun Aug 25, 2019 3:12 pm
DBs Used: DBF, PostgreSQL, MySQL, SQLite
Location: Hamburg, Germany

Re: How to read a multi-dimensional array from a text file?

Post by AUGE_OHR »

hi,

it "seem" like definition for a TREE ...
but as it is "one line" (?) i "see" no "Delimiter" ... hm

for TREE there was a Way with XML File ... is this what you search :?:
have fun
Jimmy
User avatar
Anand
Posts: 596
Joined: Tue May 24, 2016 4:36 pm
DBs Used: DBF

Re: How to read a multi-dimensional array from a text file?

Post by Anand »

Hi HGAutomator

Attached code (very old from Clipper time), which I use still today to save and restore an array.
See SaveArray(), RestArray()
Attachments
SAVEARR.ZIP
(1.5 KiB) Downloaded 108 times
Regards,

Anand

Image
HGAutomator
Posts: 202
Joined: Thu Jul 16, 2020 5:42 pm
DBs Used: DBF

Re: How to read a multi-dimensional array from a text file?

Post by HGAutomator »

Nope. I'd like to see if it's possible to import an array from a text file, where the array is defined the same way it would be in a .prg code file.
AUGE_OHR wrote: Sun Feb 06, 2022 5:44 pm hi,

it "seem" like definition for a TREE ...
but as it is "one line" (?) i "see" no "Delimiter" ... hm

for TREE there was a Way with XML File ... is this what you search :?:
HGAutomator
Posts: 202
Joined: Thu Jul 16, 2020 5:42 pm
DBs Used: DBF

Re: How to read a multi-dimensional array from a text file?

Post by HGAutomator »

Thanks Anand, I'll play with it a bit. So far, RestArray returns an empty string from the file with the array.

I even tried pulling the file into a string, then macro expanding the string, but that generates an error.
Anand wrote: Sun Feb 06, 2022 6:04 pm Hi HGAutomator

Attached code (very old from Clipper time), which I use still today to save and restore an array.
See SaveArray(), RestArray()
User avatar
Claudio Ricardo
Posts: 367
Joined: Tue Oct 27, 2020 3:38 am
DBs Used: DBF, MySQL, MariaDB
Location: Bs. As. - Argentina

Re: How to read a multi-dimensional array from a text file?

Post by Claudio Ricardo »

Hi... Maybe this:
https://www.hmgforum.com/viewtopic.php? ... ini#p67214
I do for store array in .ini file... For save in .txt:
Set Alter To &cFName
Set Alter On
? ArrayToIni (aArray)
Set Alter To
Corrige al sabio y lo harás más sabio, Corrige al necio y lo harás tu enemigo.
WhatsApp / Telegram: +54 911-63016162
HGAutomator
Posts: 202
Joined: Thu Jul 16, 2020 5:42 pm
DBs Used: DBF

Re: How to read a multi-dimensional array from a text file?

Post by HGAutomator »

Thanks Claudio,

But we already have ways of transferring arrays from and to .ini files.

But there doesn't seem to be any way of taking in a text file with any level of complexity, even something relatively simple like this:

Code: Select all

						{"First","First Item", ;
								{{"First SubItem",     "First SubItem from First", {||qout("First SubItem from First")}},;
                {"Second SubItem", "Second SubItem from First", {||qout("Second SubItem from First")}},;
                {"Third SubItem", "Third SubItem from First", {||qout("Third SubItem from First")}} } ;
						}
I've tried stripping off the first beginning and last ending bracket, so that cText is a string ; and removing the line continuations ";" ; then removing the carriage returns and line feeds ; and then converting it with { &cText }. But it just leads to an error.

I might have to specify the array in some other form, but I really wanted for it to be identical to an array expression from .prg code.

Speaking of the .ini files, I updated Timm Sodtalbers' TEXT2DB last year, and will share it after cleaning up the code a little. So here's the part that pulls definitions from an .ini file into an array:

Code: Select all

FUNCTION Process_TextFile( Source_s, Destination_s, IniFile_s, AppendYN_s )

	Local Field_s
	Local Fields_a   := {}
	Local Nth_Expression_n := 0
	Local Nth_Field_n := 1
	Local lContinue := .T.
	Local Lines_n := 0
	Local Lines_s := ""
	Local RDD_s := AllTrim( ProfileString( IniFile_s, "General", "RDD", "DBFCDX" ) )
	Local Validation_Expression_s
	Local Current_Line_n := 0
	Local Nth_Line_n := 0
	Local First_Line_s := ""
	Local Expressions_to_Evaluate_a := {}
	Local Expression_to_Evaluate_s := ""
	Local Value_to_Add_to_Table_x := ""
	Local PreParse_s := ""
	Local PostProcess_s := ""
	Local IsHeaderRow_s := ""
	Local IsFooterRow_s:= ""
	Local LineProcessDescription_s := ""
	Local IsExpressionValid_b := .F.

	Local Error_o
	Local Error_b
	Local SaveError_b


	AppendYN_s = Upper( AppendYN_s )
	PreParse_s := AllTrim( ProfileString( IniFile_s, "PreProcess", "PROC", "" ) )
	Validation_Expression_s := ProfileString( IniFile_s, "Conditions", "Valid", "" )
	IsHeaderRow_s := AllTrim( ProfileString( IniFile_s, "Headers_and_Footers", "header", "" ) )
	IsFooterRow_s := AllTrim( ProfileString( IniFile_s, "Headers_and_Footers", "footer", "" ) )

	// Loop through the list of fields.
   DO WHILE lContinue = .T.

      Field_s := ProfileString( IniFile_s, "Fields", AllTrim(STR(Nth_Field_n,4)), "" )

      IF .NOT. EMPTY( Field_s )

         AADD( Fields_a, { AllTrim( StrToken( Field_s, 1, "|" ) ), ;
                          AllTrim( StrToken( Field_s, 2, "|" ) ), ;
                          VAL( AllTrim( StrToken( Field_s, 3, "|" ) ) ), ;
                          VAL( AllTrim( StrToken( Field_s, 4, "|" ) ) ) } )
			AADD( Expressions_to_Evaluate_a, StrToken( Field_s, 5, "|" ) )
         	Nth_Field_n := Nth_Field_n + 1

      ELSE
         	lContinue := .F.
      EndIf

   ENDDO
		IF LEN( Fields_a ) = 0
		  ? "No fields defined in " + AllTrim( IniFile_s )
		  RETURN(.F.)
		ELSE
			If AppendYN_s == "YES"
				If .NOT. File( Destination_s )
		  		DBCREATE( Destination_s, Fields_a, RDD_s )
		  	Else
					// TODO: Check field specs against existing table.
		  	EndIf
		  Else	// If the table should be replaced
				DBCREATE( Destination_s, Fields_a, RDD_s )
			EndIf

		EndIf
The .ini file looks something like this, for a fixed-width file:

[General]
DateFormat=mm.dd.yyyy

[Conditions]
#Ignore Header and Footer. Only Detail Records
#This is for a Fix-Width file
Valid=LEFT( LINETEXT, 4 ) <> 'HDR' .AND. LEFT( LINETEXT, 4 ) <> 'FTR'

[Fields]
1=FIRSTFLD |C| 5| 0| SUBSTR( LINETEXT, 1, 5 )
2=SECONDFLD |C| 50| 0| SUBSTR( LINETEXT, 6, 50 )
3=THIRDFLD |C| 65| 0| SUBSTR( LINETEXT, 157, 65 )
4=THISDATE |D| 8| 0| STOD( SUBSTR( LINETEXT, 307, 8 ) )


For a tab-delimited file, it might be something like this:

[General]
DateFormat=mm/dd/yyyy

[Conditions]


[PreProcess]
#Tab Delimited
PROC=HB_ATOKENS( LINETEXT, Chr(9) )

#If header=YES, then Skip the Header line, line #1
#If footer=YES, then Skip the Last line
[Headers_and_Footers]
header=YES
footer=NO


#This defines how to extract each field from each line in the text file.
#Some functions that can be used, include
# Remove_Beg_End_Quotes( value ) - Remove quotes from the beginning and ending of strings
# SubString( value, StartingPosition, EndingPosition ) - Standard Substring function
# CTOD( value ) - Convert Date string "mm/dd/yyyy" to a Date
# STOD( value ) - Convert Date string "yyyymmdd" to a Date
# Val( value) - Convert a string value to a number
[Fields]
1=FIRSTFLD |C| 50| 0| Remove_Beg_End_Quotes( TOKENS_A[1] )
2=SECONDFLD |C| 15| 0| Remove_Beg_End_Quotes( TOKENS_A[2] )
3=THIRDFLD |C| 8| 0| TOKENS_A[3]
4=THISDATE |D| 8| 0| CTOD( TOKENS_A[4] )


I'll try to share this with the forum soon, as well as a version that parses and exports directly to a spreadsheet, or filters out lines to output a shortened fixed-width or delimited file.















Claudio Ricardo wrote: Sun Feb 06, 2022 8:14 pm Hi... Maybe this:
https://www.hmgforum.com/viewtopic.php? ... ini#p67214
I do for store array in .ini file... For save in .txt:
Set Alter To &cFName
Set Alter On
? ArrayToIni (aArray)
Set Alter To
User avatar
AUGE_OHR
Posts: 2117
Joined: Sun Aug 25, 2019 3:12 pm
DBs Used: DBF, PostgreSQL, MySQL, SQLite
Location: Hamburg, Germany

Re: How to read a multi-dimensional array from a text file?

Post by AUGE_OHR »

hi,

all is "one String" ( Codeblock), right :?:
but in that String ( Codeblock) there is "real" no ";" so you can not STRTRAN() or AT(";",cString)

---

neverless i guess you want some "Action" which is easy using qout()
but how with "real" Function and Parameter :?:
have fun
Jimmy
HGAutomator
Posts: 202
Joined: Thu Jul 16, 2020 5:42 pm
DBs Used: DBF

Re: How to read a multi-dimensional array from a text file?

Post by HGAutomator »

No. The string isn't a codeblock, but it contains some embedded codeblocks. Strtran wasn't a problem for the string, it did strip the semi-colons out, along with the carriage returns and line feeds. Also, the opening parent array bracket, and the closing one.

This is the first array in the original array, which of course we couldn't pull into the program. This is somewhat simpler, but we still can't import it into an array inside the app.

Maybe I'm misunderstanding what you're saying, Auge.

{"First","First Item", ;
{{"First SubItem", "First SubItem from First", {||qout("First SubItem from First")}},;
{"Second SubItem", "Second SubItem from First", {||qout("Second SubItem from First")}},;
{"Third SubItem", "Third SubItem from First", {||qout("Third SubItem from First")}} } ;
}
User avatar
Claudio Ricardo
Posts: 367
Joined: Tue Oct 27, 2020 3:38 am
DBs Used: DBF, MySQL, MariaDB
Location: Bs. As. - Argentina

Re: How to read a multi-dimensional array from a text file?

Post by Claudio Ricardo »

Hi... Two options to convert your array (as is) to .txt file
Comment and discomment lines... (need add more for/next bucles)
Compiled with HMG 3.4.4 32 bits.
Attachments
PruebaArrayToTxt.zip
(1.42 MiB) Downloaded 91 times
Corrige al sabio y lo harás más sabio, Corrige al necio y lo harás tu enemigo.
WhatsApp / Telegram: +54 911-63016162
Post Reply