Problem with randomaccess file

marcick

Well-Known Member
Licensed User
Longtime User
I'm reading and reading but I can't find how to manage this problem:

I have a text file that is composed of lines of equal lenght, let's say 100 char plus a CrLf.

If I open the file on a PC, I see something like this:

1234 12:52:00 enter door45 ........ [crlf]
3365 17:59:12 exit door16 ........ [crlf]

Each line, that I call "record", contains some text fields at fixed position, so if I scan the line with a simple Mid$ function it's easy to capture each field.

Question number one: how to open the file and read the record nr 1765 for example ? Do I have to read each line til 1765 ?

Question number two: I have a new record, of course of the same lenght and pattern. I need to open the file and insert this record between record 852 and 853. Also I could need to just get a record, change some fields and write back to the file.

I accomplish this in VB.net creating a record structure, opening the file in openmode.random (specifying the lenght of the records) and working with FileGet and FilePut #recordnumber.

I feel it's easy to do also with B4a but I need some help ...
I have read the RandomAccessFile library and example but can't find the solution.
Thanks
Marco
 

marcick

Well-Known Member
Licensed User
Longtime User
Thanks Erel, but I have difficulties to find the correct method.

Is it correct to use Initialize2 (because the file has to be read also in Windows as common text file) and read/write the record with Readobject(position, string) and writeobject(position, string) ?

How manage the difference between insert a record at a certain position or just replace a record ?

Marco
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The bytes order doesn't matter when you write sequences of bytes like in your case.

You should use WriteBytes / ReadBytes. To convert a string named s to a bytes array you should use: s.GetBytes("UTF8").
To convert a bytes array to string you should use BytesToString keyword.

Note that a more robust approach is to use a SQLite database instead.
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
I will do experiments with your hints.
But for insert a record at a certain position, for example between 345 and 346, do I have to read the file and move the record from 346 to the end to create an empy "slot" at position 346 ?

I have no experience with SQL but I'll have a look
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
ok, I specify position, but when I say 5, the record 5 is overwritten ?
If I have a file with 10 records, from 1 to 10 and I want to insert a record in position 5 do I have first to move a block of record like this ?

read 10 and write to 11
read 9 and write to 10
read 8 and write to 9
read 7 and write to 8
read 6 and write to 7
read 5 and write to 6

now I have space to fit the new record number 5 ?
 
Upvote 0

drake64

New Member
Licensed User
Longtime User
Hi Erel..
my name is Roberto,
i'm having the same problem, trying to
move to a specific 'record' inside a file that
i read byte x byte and i know that each line can be 100 bytes
(declared in Buffer)
I want to read the record # 1765
Is there a way to force something like raf.currentposition = 1765

Maybe i must read each line, one x cicle until i reach line 1765 ?
Don't want you use sql.. for this use i think raf will be much faster than a db engine.

Thank you very much. Roberto
 
Last edited:
Upvote 0

DouglasNYoung

Active Member
Licensed User
Longtime User
Roberto,
All the raf.ReadXXXX actions allow you to set an offest, so its easy to read any specific record. Depending on the app it may be easier to use SQL - Don't underestimate the performance of SQLite even on quite lowly Android devices.

Cheers,
Douglas
 
Upvote 0

DOM85

Active Member
Licensed User
Longtime User
ok, I specify position, but when I say 5, the record 5 is overwritten ?
If I have a file with 10 records, from 1 to 10 and I want to insert a record in position 5 do I have first to move a block of record like this ?

read 10 and write to 11
read 9 and write to 10
read 8 and write to 9
read 7 and write to 8
read 6 and write to 7
read 5 and write to 6

now I have space to fit the new record number 5 ?

Otherwise you have to manage your own space management with a first record containing a pointer to the beginning of a "chain of pointers" to the first available record. But when you want to delete a record you have to update this chain....
 
Upvote 0

DouglasNYoung

Active Member
Licensed User
Longtime User
Random Access files are OK up to a point - any record number will always be at the exact same location in the file, but if you want to insert a new record then you have to shunt everything up or as DOM85 indicates manage a series of pointers to the next record.
I'd seriously think about cutting your losses and use a SQLite table - it really is much better when you have to insert/delete record and has many other benefits like extracting by any filed in any order etc. etc.

Douglas
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
Hi,
That time I had parked the project and now I'm here again to continue it:
What I need is to create (write and read) a simple text file with fixed lenght records (and fixed fields inside each record).
Also, when I connect the device with the PC, I have to copy the file in Windows and simply read it with notepad and also with another windows VB.NET application that manage this file, knowing that it has fixed lenght records and fixed fields.

This application is an Android migration of another VB.NEt application and I must keep the same identical file format of my VB.NET application.

I think SQlite, thought more efficient, would bring me on the wrong way.
RAF should be the correct method, but I have difficulties to find how to do.

This is my simple test project:

Dim raf As RandomAccessFile
Dim noa As Int
Dim buflen As Int
Dim pos As Long
Dim miobuffer As String

buflen=6
raf.Initialize(File.DirRootExternal, "prova.txt", False)
noa=raf.Size/buflen
Log("record " & noa)
For x=0 To 4
pos=x*buflen
miobuffer="ciao" & Chr(13) & Chr(10)
raf.WriteObject(miobuffer, False, pos)
Next
raf.Close

What I want to obtain is a simple prova.txt text file that I can open with Notepad and see:

ciao
ciao
ciao
ciao
ciao


But the result is much different, with a lot of extra characters.
Anybody can help me ?
MArco
 
Upvote 0

DOM85

Active Member
Licensed User
Longtime User
ok, I specify position, but when I say 5, the record 5 is overwritten ?
If I have a file with 10 records, from 1 to 10 and I want to insert a record in position 5 do I have first to move a block of record like this ?

read 10 and write to 11
read 9 and write to 10
read 8 and write to 9
read 7 and write to 8
read 6 and write to 7
read 5 and write to 6

now I have space to fit the new record number 5 ?

No, either you use sql like Erel said, either you create (and manage) an index file addressing each record. In this case you can put your record in any order because you retreive each one by reading first an index file (eq sorted table), in chich you can insert manu kinds of access keys. But there, you are recreating an Indexed Sequential acces method, not so far from a db.
 
Upvote 0
Top