Seek replacement for binary files

new BookmarkLockedFalling
tyer
New Member
*

tyer Avatar

Posts: 6

Post by tyer on Mar 25, 2023 19:57:20 GMT -5

Since it appears that the compiler recognizes the seek keyword, but doesn't know what to do about it (see this thread), I thought I'd try simulating this with a 1-character field definition, opening the file in random mode. My goal is to be able to parse and update arbitrary binary files, starting with the tags in MP3 files uploaded by a user. (I realize that this method may be massively inefficient, but it's s starting point...) So I tried this:




' print a file in reverse order, by seeking from the end

open "Test.dat" for output as #tf
print #tf, "This is a test."
close #tf

open "Test.dat" for random as #tf
field #tf, 1 as char$

build$ = ""
iter = lof(#tf) - 1
while iter > 0
get #tf,iter
build$ = build$ + char$
iter = iter - 1
wend

close #tf
print build$

When I run it, I get the following error:


Runtime Error in program 'twoStyledTables': get #tf,iter
IncompleteNextCountError


What am I doing wrong, or is there some completely different method I should be trying?

Thanks!


Last Edit: Mar 25, 2023 20:01:05 GMT -5 by tyer
~ Tyer
StefanPendl
Global Moderator
*****

StefanPendl Avatar

Run for BASIC ...
Posts: 945

Post by StefanPendl on Mar 26, 2023 3:11:41 GMT -5

You were missing the LEN statement on the open for random line.

' print a file in reverse order, by seeking from the end

open ResourcesRoot$ + "\Test.dat" for output as #tf
print #tf, "This is a test."
close #tf

open ResourcesRoot$ + "\Test.dat" for random as #tf len = 1
field #tf, 1 as char$

build$ = ""
iter = lof(#tf) - 1
while iter > 0
get #tf,iter
build$ = build$ + char$
iter = iter - 1
wend

close #tf
print build$

I also placed the file into the resources folder, so it is not created in the main folder.
[b]Stefan[/b] - [a href=http://stefanpendl.runbasichosting.com/]Homepage[/a][br][br][b]Please give credit if you use code I post, no need to ask for permission.[/b][br][br]Run BASIC 1.01, Fire-/Waterfox (IE11, Edge), Windows 10 Professional x64, Intel Core i7-4710MQ 2.5GHz, 16GB RAM
tyer
New Member
*

tyer Avatar

Posts: 6

Post by tyer on Mar 26, 2023 17:07:33 GMT -5

Ah, thank you! That works perfectly now.

So, how bad will the performance really be? The file sizes I'll be dealing with are on the order of many megabytes (at least a couple, and perhaps up to 50 or more); however, I don't have to read/write the whole file, just the relatively small parts that I'm interested in (<100 kB). Is there a lot of buffering going on behind the scene, or will the server actual do a separate read for each get statement?

Can I re-define the field layout of a random file without closing/re-opening it? I'm thinking that once I know what I want to write out (or in fact even for the get statements, once I've parsed the pointers and lengths in the file), I can re-define the field to be the full length and write it out using a single put statement. Is this re-definition possible?

As far as locating the resource folder, that's certainly a useful technique to know. In this little test case, I knew the C:\Data folder would be there. I notice that one of the demo programs (Hangman) creates a little .png file in the public\images folder every time it sketches a picture, apparently just as a result of the Render statement. Is there any sort of garbage collection, or will this collection of files just grow without bound?

Thanks again for the very helpful response!

Last Edit: Mar 26, 2023 17:07:59 GMT -5 by tyer
~ Tyer
StefanPendl
Global Moderator
*****

StefanPendl Avatar

Run for BASIC ...
Posts: 945

Post by StefanPendl on Apr 2, 2023 3:51:52 GMT -5

I would do the following:
  1. seek for the header end
  2. manipulate the header separately
  3. write the new header to a temporary file
  4. append the rest of the original file

This would make sure that the original file is not corrupted during you tests.
If the file with the new header works as expected, you can delete the original file and rename the temporary file.

To you second question, there is no garbage collection, so you have to take care of cleaning up behind yourself.
[b]Stefan[/b] - [a href=http://stefanpendl.runbasichosting.com/]Homepage[/a][br][br][b]Please give credit if you use code I post, no need to ask for permission.[/b][br][br]Run BASIC 1.01, Fire-/Waterfox (IE11, Edge), Windows 10 Professional x64, Intel Core i7-4710MQ 2.5GHz, 16GB RAM
tyer
New Member
*

tyer Avatar

Posts: 6

Post by tyer on Apr 2, 2023 12:01:21 GMT -5

(Probably should be two threads...) Your method of building a duplicate copy of a file is certainly reasonable, and I can do it that way if necessary. However, it looks like I should be able to "put" a record (a single byte, repetitively, in this case) into a file at an arbitrary place replacing the current contents, without having to move tens of megabytes of data. I haven't experimented yet, so there may be something else to trip over, but that's been true in other languages (including BASICs) that I've used.

In the Hangman example program, there's no explicit creation of the temporary files - they just seem to be created as a result of the Render instruction. How can I know which files were created by my instance of this program (since the program itself is unaware of the files) to know which ones to delete? (In other words, it's possible that there are two clients running the same program simultaneously, with each instance creating its own temporary files; therefore I can't just delete everything in the images folder.)
~ Tyer
StefanPendl
Global Moderator
*****

StefanPendl Avatar

Run for BASIC ...
Posts: 945

[b]Stefan[/b] - [a href=http://stefanpendl.runbasichosting.com/]Homepage[/a][br][br][b]Please give credit if you use code I post, no need to ask for permission.[/b][br][br]Run BASIC 1.01, Fire-/Waterfox (IE11, Edge), Windows 10 Professional x64, Intel Core i7-4710MQ 2.5GHz, 16GB RAM