Reading Data From File

Find quick help here to get you started with Hollywood
Post Reply
oceanarts
Posts: 111
Joined: Mon May 27, 2024 10:42 pm

Reading Data From File

Post by oceanarts »

So, I'm having some problems understanding how to read specific data back from a simple text file previously written to. How do I know where that data is stored in the file? I understand I have to use the seek function in some capacity, but how exactly?

And also, how do I write information to a file without spaces and newlines?
Development System : Imac G5, MorphOs 3.19
Flinx
Posts: 342
Joined: Sun Feb 14, 2021 9:54 am
Location: Germany

Re: Reading Data From File

Post by Flinx »

To write and read any binary data, you only need to use the functions provided for this purpose: WriteByte(), WriteBytes(), ReadByte(), and ReadBytes(). For these functions, spaces and newlines are just bytes like any others. Depending on the application, ReadShort(), ReadInt() etc. may also be useful.

To know where data can be found in the file, you need to know the file structure. Then you can navigate to the required position in a suitable manner. Here is a practical example from the first lines of my ID3 parser up to the point where the ID3 tag begins:

Code: Select all

Function p_ReadID3Frames(f$)
	p_DisableLineHook()
	Local ID3Debug=False
	Local title$, interpr$, year$, picturedata$, picturelist = "", "", "", "", {}
	Local album$=""
	Local id3version="-"

	If ID3Debug Then DebugPrint(f$)
	Local fsize=FileSize(f$)
	If fsize<16 ; (willkürlich gewählt)
		p_PrintMessage(True, 10000,p_GetCatalogString(40, "beschädigte Datei "),f$,p_GetCatalogString(41, " Größe"),fsize)
		Return(False, interpr$, title$, year$, {})
	EndIf

	Local err= ?OpenFile(1, f$, #MODE_READ)
	If err<>#ERR_NONE
		p_PrintMessage(True, 40000,p_GetCatalogString(42, "Lesen der ID3-Tags: Die Datei"),f$, p_GetCatalogString(43, "kann nicht gelesen werden: "),GetErrorName(err))
		Return(False, interpr$, title$, year$, {})
	EndIf

	; ggf. vorhandene Nullen am Dateianfang überspringen
	; (ursprünglich nur die zweite Schleife, aber bei sehr vielen Nullen war das zu langsam)
	Local i=0
	Local fsizek=fsize-4
	While ReadInt(1) = 0
		i=i+4
		If i >= fsizek
			p_PrintMessage(True, 90000,p_GetCatalogString(44, "beschädigte Datei "),f$)
			Return(False, interpr$, title$, year$, {}) ; Abbruch, weil Datei nur Nullen enthält
		EndIf
	Wend
	Seek(1, -4, #SEEK_CURRENT)  ; vier Byte zurück
	i=FilePos(1)
	Local fsizek=fsize-1
	While ByteAsc(ReadBytes(1, 1),0) = 0
		; eigentlich "If FilePos(1) >= FileSize(f$)-1" , aber etwas beschleunigt
		i=i+1
		If i >= fsizek
			p_PrintMessage(True, 90000,p_GetCatalogString(44, "beschädigte Datei "),f$)
			Return(False, interpr$, title$, year$, {}) ; Abbruch, weil Datei nur Nullen enthält
		EndIf
	Wend
	Seek(1, -1, #SEEK_CURRENT)  ; ein Byte zurück
	Local GarbageAtBegin=0
	If FilePos(1)>0
		GarbageAtBegin=FilePos(1)
		If ID3Debug
			DebugPrint(FilePos(1),"Null-Bytes am Dateianfang übersprungen.")
			DebugPrint("Erstes Byte",HexStr(ByteAsc(ReadBytes(1, 1))))
			Seek(1, -1, #SEEK_CURRENT)
		EndIf
	EndIf

	If ID3Debug
		; die ersten 50 Bytes auf die Debugkonsole
		gTagbuffer$=ReadBytes(1, 50)
		p_PrintHex(MidStr(gTagbuffer$,0,50,#ENCODING_RAW))
		Seek(1, -50, #SEEK_CURRENT)
		gTagbuffer$=Nil
	EndIf
	/*
	 Der ID3v2-Tag-Header besteht aus 10 Bytes:
	     ID3v2/Datei-Bezeichner    "ID3"
	     ID3v2-Version             $03 00
	     ID3v2-Flags               %abc00000
	     ID3v2-Größe           4 * %0xxxxxxx
	*/	
	If ReadBytes(1, 3) = "ID3"
		; wenn die (von Null verschiedenen) Daten mit ID3 beginnen, sollte das ein
		; Tag-Header sein, und es sollte ID3-v2-Frames geben

		; restlicher Header
		header=ReadBytes(1, 3) ; Version, Flags
		id3version="2."..ByteAsc(header,0).."."..ByteAsc(header,1)
		If ID3Debug Then DebugPrint("ID3v"..id3version)
		If gRndmzFramesReadFinished Then p_PrintMessage(False, 9000,p_GetCatalogString(45, "Tagversion ID3v")..id3version)
		;DebugPrint("Flags",BinStr(ByteAsc(header,2), #BYTE))
oceanarts
Posts: 111
Joined: Mon May 27, 2024 10:42 pm

Re: Reading Data From File

Post by oceanarts »

Thank you.
Unfortunately it's waaaaay too complicated for me. :lol: Must be a way to learn this stuff incrementally.

Trying to adapt some code from the docs:

Code: Select all

@DISPLAY{WIDTH = 960, HEIGHT = 540, MODE = "WINDOWED", TITLE = "FileStuff", COLOR = #BLACK}

SetFont(#MONOSPACE, 24)
SetFontStyle(#ANTIALIAS)
SetFontColor(#WHITE)

Global teststring = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

Global testvalues = {2, 4, 8, 16, 32, 64, 128}

Global returnvalues = {}

;Write To File
OpenFile(1, "Text.txt", #MODE_WRITE)
NPrint(FileLength(1)); Print initial file length
WriteLine(1, "")
WriteLine(1, "This file belongs to the OpenFile Hollywood script.")
WriteLine(1, "")
for k = 0 to 6
    WriteLine(1, testvalues[k])
Next
WriteLine(1, "")
WriteLine(1, teststring)
NPrint(FileLength(1)); Print file length after write
CloseFile(1)

;Read From File And Print To Screen
OpenFile(1, "Text.txt", #MODE_READ)  
While Not Eof(1) Do NPrint(ReadLine(1))
;Here I'd like to read the values back from the text file add 1 to them and write the new value to the empty 'returnvalues' table
;And also print them to the screen:
for k = 0 to 6
    returnvalues[k] = ReadLine(1, ToNumber(testvalues[k] + 1)); placeholder non-sense
    NPrint(returnvalues[k])
Next

CloseFile(1)

Repeat
        WaitEvent
Forever
Development System : Imac G5, MorphOs 3.19
Bugala
Posts: 1390
Joined: Sun Feb 14, 2010 7:11 pm

Re: Reading Data From File

Post by Bugala »

I am wondering what you are trying to achieve with this, and if instead of using textfile, you could use a Table file.

In Hollywood, when you have a table,you could do for example:

Code: Select all

ExampleTable={ 
         ["line1"] = {eng = "Attention!", deu="achtung!"}
                      }
                      
OpenFile(1, "myfile.tbl")
WriteTable(1, ExampleTable)
CloseFile(1)
then you could have another program:

Code: Select all

OpenFile(1, "MyFile.Tbl")
TableToUse = ReadTable(1)
CloseFile(1)

Language = "eng"

Debugprint(TableToUse["line1"][Language]
and it would debugprint "Attention!"

Change Language to "deu" and it will debugprint "Achtung!"



Or to give simpler example:

Code: Select all

MyTable = {name="Hollywood"}
OpenFile(1, "MyFile.Tbl")
WriteTable(1, MyTable)
CloseFile(1)

OpenFile(1, "MyFile.Tbl)
MyTable2 = ReadFile(1)
CloseFile(1)

Debugprint(MyTable2.Name)
this will print "Hollywood".

The previous, slightly more complex example was to show you how that table can be more useful in some cases than text files, since if you for example want to make multiple languages, then you can just make one table entry for each, instead of having to figure out how to get that info from text-file, which would be much more complex.
oceanarts
Posts: 111
Joined: Mon May 27, 2024 10:42 pm

Re: Reading Data From File

Post by oceanarts »

Well, I'm not really trying to achieve anything but learning. It's not a serious project. Eventually I hope to able to store some settings in a file and read them back when needed. Which would probably have been a better approach from the get go. But there you go. :roll:

Thanks for the additional information, I'll read through it very soon. :)
Development System : Imac G5, MorphOs 3.19
Flinx
Posts: 342
Joined: Sun Feb 14, 2021 9:54 am
Location: Germany

Re: Reading Data From File

Post by Flinx »

oceanarts wrote: Sat Sep 27, 2025 9:13 pm Unfortunately it's waaaaay too complicated for me.
Actually, it's not that complicated. If you want to take a look at it sometime, I just skip the zeros at the beginning of the file and then check to see if the characters “ID3” appear. (Nowadays, I would probably do it differently and first read in a larger data block and then continue working in the memory, but never mind. At least here you can see what Seek() is used for.)
oceanarts wrote: Sat Sep 27, 2025 10:58 pm Eventually I hope to able to store some settings in a file and read them back when needed.
That's really not difficult. Write your data into a table and save it with WriteTable(). You can read it back with ReadTable(). There's a working example in the WriteTable description.
Addendum: I see that Bugala has already said the same thing. After some time, we end up coming to the same solutions.
Bugala
Posts: 1390
Joined: Sun Feb 14, 2010 7:11 pm

Re: Reading Data From File

Post by Bugala »

Yep, Settings sounds like ideal for WriteTable - ReadTable case:

Code: Select all


Function SaveSettings(SettingsTbl, FileName)
OpenFile(1, Filename)
WriteTable(1, SettingsTbl)
CloseFile(1)
EndFunction

Function LoadSettings(Filename)
OpenFile(1, Filename)
Local TempSettingsTbl = ReadTable(1)
CloseFile(1)
Return(TempSettingsTbl)
EndFunction

Settings = {Volume = 64, SoundFX = 32, Speech=32}

SaveSettings(Settings, "Settings.tbl")

Settings2 = LoadSettings("Settings.tbl")

Debugprint(Settings2.Volume)
Post Reply