RandomAccessFile - Questions & Concerns

Housefly

Member
Licensed User
Longtime User
Hi All, this is my first post.
First off, I'm absolutely loving this development platform!! Major kudos to the development team, and all the library creators!!

I'm coming from a heavy VB6 background here, and I'm attempting to wrap my head around a few things. Any advice, support you can offer is much appreciated!

I'm a huge UDT user, and all my database work has been with Types, my first order of business was getting a fixed length string to work in the B4A type object, and so I went with char arrays:

B4X:
   Type PersonData( _   
   Name(25) As Char, _
        Description(500) As Char, _
        Age as Int)

Using the ByteConverter Library, data stored can be converted using the ToChars and FromChars functions.

so far so good (I'm thinking) but when it comes time to write the Type to file, I can't easily ascertain the length of the Type Object so that I can use that information to sequentially perform actions I would normally be used to doing in VB6. Looping through records, getting record counts, locating a single record in the midst of other records.

Not knowing how to easily get this info, I just created a simple enum or constant (of sorts) to store them PRE-CALCULATED for when I need the values later on, but the values are not adding up properly, and the records are not being read/written correctly in my attempts..

B4X:
   Type DataTypeLength(PersonDataLength As Int)
   Dim Lens As DataTypeLength 
   Lens.PersonDataLength = (((25 + 500) *2) + 4)

Extra data that I'm not EXPECTING to have been written to file is being written, and it's not allowing me to get a proper handle on the quantity of records that exist within the database file. I'm missing something... or perhaps I'm doing it improperly..

Yes, there is SQL, but I really want to try maintain the same UDT reading/writing for compatibility between older VB6 databases.

Does anyone have any good RandomAccessFile examples showing Types being used to create a sequential based database?
 

Housefly

Member
Licensed User
Longtime User
Hi Erel,

Thank you for your reply, it spurred me on.. I discovered that I made some mistakes in my calculations, I've been used to flat files, and assumed that just iterating with a fixed Type size would work for data writing and retrieval.

It turned out that I was telling it to write to an incorrect position, which was causing it to corrupt the database.

It does appear to be extremely inefficient though, as now that I have it working, the RandomAccessFile system writes a lot of extra data with each record. I was writing a 166 byte type object to file, and it was appending an extra 839 bytes, it quickly became apparent that compression would probably be needed for any reasonable use of this library's object writing/reading features. But then this effects the sequential capabilities.

Is there a chance, as a future feature request to allow for the same object writing, only without the header information tacked on to it? A flat file, with nothing but sequential object data, spaced apart only by the size of the object (as declared by the programmer, whom keeping in mind that it would have to be a fixed size to work properly) could then keep file size down, and also use simple math to get record counts and more easily jump around the file at his/her whim. This would also mean this would never occur:
Note that changing your package name may make older objects files unusable (requiring you to write them again).
making it far more stable, and powerful in my opinion.


eg:
RAF as RandomAccessFile

RAF.Initialize4(Dir as string, File as string, ReadOnly as boolean, FixedLengthUDT as object)

that once initialized, would perform operations on said file without writing any headers/footers.

And an added function like:
RAF.ObjectSize as int (object size in bytes, returns 0 if no object initialized)

if I know the object size, and my file size, I can easily determine my record count.


my BIG wish list.. I'm super thankful that you've taken the time to reply to my message, and I'd like to hear any feedback on these ideas.. perhaps it's impossible to do, but if I can I'd love to help in any way.

Thanks again!
 
Upvote 0

jfbs

New Member
Licensed User
Longtime User
Hi! This is my first post. I have just registered afnte a few weeks with the demo version convinced me of B4A's excellence. Congratulations for the product and for such a good online support.

The worse part of this is that I am virtually a newcomer to programming (I used to program in my work, but that was back in the 80's!) so I will probably annoy you with some too obvious questions. I will try not to, but if I do, please be tough with me and send me to the manual.

So my first question is... I am trying to test Random Access but it does no seem to be available in the full version (1.9.0.0) I have just installed (neither was it in the demo version). I mean, the tutorial on Random Access reads that I should "dim" the file with

Dim [filename] As RandomAccessFile

but B4A does not admit it. What am I doing wrong?

I have read of special libraries in the Beginner's Guide but according to this:

"When the IDE starts, it looks first for the available libraries in the Libraries folder of B4A and then
in the folder for the additional libraries."


these libraries should be active, shouldn't they?


Thanks for your patience!
 
Last edited:
Upvote 0

klaus

Expert
Licensed User
Longtime User
Welcome to B4A community.

The RandomAccessfile library is part of B4A.
Click at the Libs tab in the lower right corner.
Check RandomAccessFile library
And you are done.
Beginner's Guide chapter 13.7 Libraries page 182 .

Best regards.
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
Hi Housefly, I had the same difficulties and this is how I have found for manage this:

First, prepare a fixed lenght string that contains, at fixed offset, all your data. (this works only for asciii type data, not mixed)

Dim noa, buflen As Int
Dim pos As Long
Dim miobuffer As String
Dim buffer() As Byte
Dim Save_Str As String

Save_Str="Name .... Data .... etc" & Chr(13) & Chr(10)

buffer=Save_Str.GetBytes("ASCII")
buflen=Save_Str.Length ' must be fixed lenght
raf.Initialize(File.DirRootExternal & "/path","filename", False)
noa=raf.Size/buflen ' nr of records in the file
pos=recordnumber*buflen
raf.WriteBytes(buffer,0,buflen,pos)
raf.Close


To retrieve records:

raf.Initialize(File.DirRootExternal & "/path", "filename", False)
pos=recordnumber*buflen
raf.ReadBytes(buffer,0,63,pos)
raf.Close
test = BytesToString(buffer, 0, 63, "UTF-8") 'convert the bytes to string

now you can scan the string "test" and find, at the fixed positions you know, all your fields.

Sorry I have written everything not elegant and with some mistakes maybe, but it's enought to understand the concept. In this way also, I have a plain text file that I can read also when I move it to a windows machine.

Bye
Marco
 
Upvote 0
Top