Author Topic: find last record in a random file  (Read 7083 times)

0 Members and 1 Guest are viewing this topic.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: find last record in a random file
« Reply #15 on: October 01, 2020, 08:06:06 am »
Hi. You can write variable-length text to the file. It can then be read, of course. It's all about organizing the data in a file. For this purpose, I personally prefer to use files in binary mode. The following program shows how to do this. Basically, the first record is 4 bytes long and tells you how many records you have in the file. The following are two fields that have a size of 4 * number of records (because they are of type LONG). These contain information on how many bytes a particular text record collects. The first field is for name and the second for text.

Of course, with this solution, if you want to jump to record number 5 immediately, you would first have to add the lengths of the previous 4 strings, so it would be appropriate to add another field to the record in the file, which indicate the start byte position of the record in the file. This can be get with the SEEK function)

Code: QB64: [Select]
  1. 'example how write to file strings using variable lenght
  2.  
  3. file$ = "example.dat"
  4. 'first record in file is header:  First 4 bytes = total records in file, next record: 4 bytes * total records is records offsets.
  5.  
  6. OPEN file$ FOR BINARY AS ff
  7. GET ff, , TotalRecords& '       read how much records file contains
  8. IF TotalRecords& THEN
  9.     PRINT "Total records in file:"; TotalRecords&
  10.     DIM LenghtsName(TotalRecords&) AS LONG
  11.     DIM LenghtText(TotalRecords&) AS LONG
  12.     GET ff, , LenghtsName()
  13.     GET ff, , LenghtText()
  14.  
  15.  
  16.     FOR viewit = 1 TO TotalRecords&
  17.         nam$ = SPACE$(LenghtsName(viewit))
  18.         text$ = SPACE$(LenghtText(viewit))
  19.         GET ff, , nam$
  20.         GET ff, , text$
  21.  
  22.  
  23.         PRINT "Record: "; viewit
  24.         PRINT "Name: "; nam$
  25.         PRINT "Text: "; text$
  26.     NEXT
  27.     END
  28.  
  29.     n$ = " "
  30.     DO UNTIL n$ = ""
  31.         INPUT "Insert name: (empty string for writing file and exit)"; n$
  32.         INPUT "Insert text:"; t$
  33.  
  34.         IF LEN(n$) THEN
  35.             record& = record& + 1
  36.  
  37.             REDIM _PRESERVE TextLenghtA(record&) AS LONG
  38.             REDIM _PRESERVE TextLenghtB(record&) AS LONG
  39.             REDIM _PRESERVE names(record&) AS STRING
  40.             REDIM _PRESERVE textes(record&) AS STRING
  41.  
  42.             TextLenghtA(record&) = LEN(n$)
  43.             TextLenghtB(record&) = LEN(t$)
  44.             names(record&) = n$
  45.             textes(record&) = t$
  46.         END IF
  47.     LOOP
  48.  
  49. writeit:
  50. 'first record is total records in file:       (& = LONG type, 4 byte value)
  51. PUT ff, 1, record&
  52. 'next record are string lenghts for name$:    (all lenghts for all name$)
  53. PUT ff, , TextLenghtA()
  54. 'next record are string lenght for text$:     (all lenghts for all text$)
  55. PUT ff, , TextLenghtB()
  56. 'next records are: Name$ and then Text$
  57. FOR R = 0 TO record&
  58.     PUT ff, , names(R)
  59.     PUT ff, , textes(R)
  60.  
  61. PRINT "File is saved. Run program again for view file content."
  62.  

Offline JohnUKresults

  • Newbie
  • Posts: 40
    • View Profile
Re: find last record in a random file
« Reply #16 on: October 01, 2020, 01:26:57 pm »
ok thanks Petr. Looks like I'd have my work cut out and have to think a bit differently!

I don't think I'll be able to change what I already have as the program is about 8000 lines long, and here's a lot of file access throughout it, but it's certainly worth bearing in mind for some later stuff.

Cheers

Offline badger

  • Forum Regular
  • Posts: 148
    • View Profile
Re: find last record in a random file
« Reply #17 on: October 01, 2020, 01:55:03 pm »
hello

will the following check for a dup value in a record
anything that starts with a z is integer64 l is long and i is integer s is string. sr is my general input variable
TYPE customer
        id AS STRING * 10
        sfirst_name AS STRING * 25
        slast_name AS STRING * 25
        saddress AS STRING * 30
        scity AS STRING * 25
        sstate AS STRING * 2
        szip AS STRING * 5
        sphone AS STRING * 10
        sfiller AS STRING * 130
END TYPE
dem custinforec as customer
 lcustinforeclen =len(cusinforec)

FOR ux = 1 TO LOF(1) / lcustinforeclen
        GET #1, zx * lcusinforeclen, custinforec
        if custinforec.id =sr then iflag2 = 1
NEXT ux

Offline badger

  • Forum Regular
  • Posts: 148
    • View Profile
Re: find last record in a random file
« Reply #18 on: October 01, 2020, 02:07:14 pm »
hello

will this check for a dup in a file.

z is integer64 s is string l is long custinfored type customer

Code: QB64: [Select]
  1. dupidsearch:
  2. WHILE NOT LOF(1) / lcustinforeclen
  3.         GET #1, zcustinforecnum * lcusinforeclen, custinforec
  4.         IF custinforec.id = sr THEN BEEP

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: find last record in a random file
« Reply #19 on: October 01, 2020, 02:16:32 pm »
@badger

before you GET # you have to specify if you are opening for Random Access or Binary, Random is looking for a record position and Binary is looking for a byte position.

Offline badger

  • Forum Regular
  • Posts: 148
    • View Profile
Re: find last record in a random file
« Reply #20 on: October 01, 2020, 02:33:36 pm »
Hello

sorry for the double post


the binary files are open at the start of the program then closed at the programs close
i just need to know if my logic here is sound. instead of beep that will be handled in program elsware.

Badger

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: find last record in a random file
« Reply #21 on: October 01, 2020, 03:09:42 pm »
Phil, here's a fun one you might want to try. It finds if any of the records are duplicated, by loading the entire binary file in one chunk, and parsing it. Thanks to the Amazing Steve for this one chunk file load approach, and thank to the more amazing me for finding cool ways to use it. :D

Code: QB64: [Select]
  1. OPEN "mytemp.tmp" FOR OUTPUT AS #1: CLOSE #1
  2. CONST fieldsize = 20
  3. DIM a AS STRING * FIELDSIZE
  4. OPEN "mytemp.tmp" FOR BINARY AS #1
  5.     READ a
  6.     IF MID$(a, 1, 3) = "EOD" THEN EXIT DO
  7.     PUT #1, , a
  8.  
  9. OPEN "mytemp.tmp" FOR BINARY AS #1
  10. x$ = SPACE$(LOF(1)) ' Set x$ as spaces equal to the length of the entire bnary file.
  11. GET #1, , x$
  12. ' Now parse for duplicates
  13. i = 1: j = 0
  14. DO UNTIL j * fieldsize > LEN(x$)
  15.     j = j + 1
  16.     find$ = MID$(x$, i, fieldsize)
  17.     IF INSTR(i + fieldsize, x$, find$) THEN PRINT j; find$ + "This entry is duplicated in the records."
  18.     i = i + fieldsize
  19. DATA elephant,dog,cat,rabbit,frog,horse,dog,mouse,elephant,pig,EOD

Pete

PS If you don't intend on using fixed field lengths, you can do this, but you have to put some kind of divider like | between each file record, so you don't get a solid string like dogcatrabbit, etc. with a divider, you would get dog|cat|rabbit| See what I mean? Those dividers would have to be part of the database construction.
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline badger

  • Forum Regular
  • Posts: 148
    • View Profile
Re: find last record in a random file
« Reply #22 on: October 01, 2020, 03:49:39 pm »
Pete

what do you mean by fixed field lengths. LOL i have gotten my self cornfused LOL.... here is my def typel

Code: QB64: [Select]
  1. TYPE customer
  2.         id AS STRING * 10
  3.         sfirst_name AS STRING * 25
  4.         slast_name AS STRING * 25
  5.         saddress AS STRING * 30
  6.         scity AS STRING * 25
  7.         sstate AS STRING * 2
  8.         szip AS STRING * 5
  9.         sphone AS STRING * 10
  10.         sfiller AS STRING * 124

this is what i assume fixed field lengths are. I like to use 256 length fields so i add a filler string to the end for future upgraded without having to change the file data.

Badger

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: find last record in a random file
« Reply #23 on: October 01, 2020, 08:24:47 pm »
By fixed length, I man using DIM, as in DIM a as string * 10

So what does that mean? Dog is only three characters, right? Well when you make a = "Dog" the word dog becomes a 10 character length string. Three alphabetical characters, followed by 7 spaces, CHR$(32).

Code: QB64: [Select]
  1. DIM a AS STRING * 10
  2. a = "Dog"
  3. PRINT "a = ["; a; "]";
  4. FOR i = 1 TO 10
  5.     PRINT ASC(MID$(a, i, 1));
  6. OPEN "mytemp2.txt" FOR RANDOM AS #1 LEN = 10
  7. PUT #1, 1, a
  8. a = ""
  9. PRINT "a = ["; a; "]"
  10. GET #1, 1, a
  11. PRINT "a = ["; a; "]";
  12. FOR i = 1 TO 10
  13.     PRINT ASC(MID$(a, i, 1));

Now if you wanted the record coming out of the file to be without those added spaces, you would need to convert it to: a = RTRIM$(a)

To me, the most difficult thing about fixed length RA files is setting the length, if you are not sure of the largest length record you may be placing into the database. This generally leads to a bloated RA file format, like those animal names being placed in a LEN = 80 RA file. I mean how many animals have a name over 80 characters long, right?

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: find last record in a random file
« Reply #24 on: October 01, 2020, 10:27:32 pm »
I think if I was going to do a RA data base file today, I wouldn't, specially if it were to need lots of strings.

Pete's reply reminded of all the wasted space involved with RA in last reply.

Nope it would be Binary only to load and store. Use a Record divider with one character, why not CHR$(10) and another character to divide the fields maybe "|". Open for Binary and Load it or Download it as a giant string. Split the string to records then split the records as needed to fields. Then reverse that process to load it back to the file again after adding and editing all the data. I might not even need a Type definition, just an double array with Field names with values from each record going in and out. Probably could sort by array index number.

I wonder what I am forgetting?

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: find last record in a random file
« Reply #25 on: October 02, 2020, 01:11:30 am »
I think if I was going to do a RA data base file today, I wouldn't, specially if it were to need lots of strings.

Pete's reply reminded of all the wasted space involved with RA in last reply.

Nope it would be Binary only to load and store. Use a Record divider with one character, why not CHR$(10) and another character to divide the fields maybe "|". Open for Binary and Load it or Download it as a giant string. Split the string to records then split the records as needed to fields. Then reverse that process to load it back to the file again after adding and editing all the data. I might not even need a Type definition, just an double array with Field names with values from each record going in and out. Probably could sort by array index number.

I wonder what I am forgetting?

If I need variable length strings in a database, I always write TWO databases.  The first is my data, the 2nd is my index to the data.

For example, my data might be:  dog, cheese, elephant, basketball

My first database would be binary data of :dogcheeseelephantbasketball

My second database would be the index of 3, 9, 17, 27

When I need any record, all I need is to check 2 indexes.   For example, to find the 3rd record in my database, I look at index 2 and 3.  Index 2 ends at byte 9, so I start reading the main database at byte 10, and I finish reading the database at Index 3, or at byte 17.

From byte 10 to 17 is “elephant”.

Hopefully, I should be home later today, so if you guys want a demo, I can work up a simple example later this afternoon, if anyone would find it useful.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: find last record in a random file
« Reply #26 on: October 02, 2020, 04:45:09 am »
the tecnique of Steve let me think about the three database with data plus a pointer to the next data or with 2 pointer  1 for previous data and 1 for next data...
yes going deeper into the Db structure! I love it.
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: find last record in a random file
« Reply #27 on: October 02, 2020, 12:37:34 pm »
Well I always liked data files I could edit in txt editor.

Steve, you change one thing in that index thing and you have to re-adjust everything.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: find last record in a random file
« Reply #28 on: October 02, 2020, 12:58:04 pm »
Well I always liked data files I could edit in txt editor.

Steve, you change one thing in that index thing and you have to re-adjust everything.

Take a look at the little sample I posted a bit ago.  You can alter/change your data file, with very little editing of the main data.  The index is just pointers to your data, so if your data gets longer, you just move it to the end of the existing data and simply point the position to where it’s at.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!