Announcement

Collapse
No announcement yet.

Random Write - Variable - Example Bug

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Random Write - Variable - Example Bug

    The following code is in the manual and produces:
    Joe 1  Joe 2  Joe 3 

    why dont I see the Integer Numbers?


    #COMPILE EXE "Random.exe"

    TYPE TestRec
    uName AS STRING * 10
    uNumber AS INTEGER
    END TYPE

    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'
    FUNCTION PBMAIN

    DIM Rec AS TestRec, Record AS INTEGER

    OPEN "RANDOM.DTA" FOR RANDOM AS #1 LEN = LEN(TestRec)

    FOR Record = 1 TO 3
    Rec.uName = "Joe" + STR$(Record)
    Rec.uNumber = Record
    PUT #1,Record, Rec
    NEXT Record

    CLOSE #1


    END FUNCTION
    '------------------------------------------------------------------------------

    ------------------
    Kind Regards
    Mike

  • #2
    I just ran the example and looked at the resulting "random.dta"
    file and I could see Joe 1, Joe 2 and Joe 3 in the file. There
    must be something else coming into play on your end????

    ------------------
    Paul Squires
    mailto:[email protected][email protected]</A>

    [This message has been edited by Paul Squires (edited March 04, 2001).]
    Paul Squires
    FireFly Visual Designer (for PowerBASIC Windows 10+)
    Version 3 now available.
    http://www.planetsquires.com

    Comment


    • #3
      What are you expecting to see? Integers are stored in 2-byte binary represenation. The number one is actually stored as chr$(0) + chr$(1) (did i get that right? i always get my endians mixed up )
      When you open the random file in a text editor you won't see a 1, you'll see a ch$(0) + chr$(1) - these are not human readable via a text editor (a hex-editor, yes, but not a text editor).
      Best Regards,
      Don


      ------------------
      www.basicguru.com/dickinson
      Don Dickinson
      www.greatwebdivide.com

      Comment


      • #4
        Yes I get Joe1 Joe2 and Joe3
        BUT those are the strings. The VARIABLE should also be after each "Joe" all I get is three "  "

        FYI I am writing an app that converts 10k lines of data. It creates a new file in the process. After the file is created I want to go back in and insert the total number of lines in the file on the first line for the next EXE to read

        ------------------
        Kind Regards
        Mike

        Comment


        • #5
          Add the following to your code, after file is closed after writing,
          and see that it works.
          Code:
          OPEN "RANDOM.DTA" FOR RANDOM AS #1 LEN = LEN(TestRec)
            GET #1, 3, Rec 'Get third record
            MSGBOX Rec.uName & STR$(Rec.uNumber)
            GET #1, 2, Rec 'Get second record 
            MSGBOX Rec.uName & STR$(Rec.uNumber)
          CLOSE #1

          ------------------

          Comment


          • #6
            Don,

            It doesnt say that Variables are stored in Binary format in the manual, but to answer your question I was hoping to see:
            1 2 3
            I am creating an ascii file. Every other line is Ascii format.

            So i guess the question becomes, how do I PUT a variable in ascii format, (just like all the variables written to the file with
            WRITE# )

            ------------------
            Kind Regards
            Mike

            Comment


            • #7
              Borje,
              Yes that worx - thx, but the Ascii File Random.dta must be readable in ascii format for another EXE.

              I need to find a way to overwrite the first record with an ascii number. Is the only way to do this with the number converted to a string?

              ------------------
              Kind Regards
              Mike

              Comment


              • #8
                If you want to put a variable in ASCII format, change the declared
                type to something like:
                Code:
                TYPE TestRec
                  uName   AS STRING * 10
                  uNumber AS STRING * 10
                END TYPE
                ..and convert the variable to string format before you PUT it into the
                record. Better to use the way you do, though, and convert to string
                after GET command, using FORMAT$(Rec.uNumber). STR$(), used in my
                sample adds a leading space, so better to use FORMAT$ for other use than
                showing in MSGBOX..


                ------------------

                Comment


                • #9
                  OK thx but I tried that. There is a problem - it overwrites my data!

                  Here is a much better example of what i am trying to do. The problem is evident in the .dta file

                  #COMPILE EXE "Random.exe"

                  GLOBAL Line1Str AS STRING * 10
                  GLOBAL Record AS LONG, Count AS LONG
                  GLOBAL SomeVar1 AS LONG, SomeVar2 AS LONG
                  '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'
                  FUNCTION PBMAIN

                  OPEN "RANDOM.DTA" FOR OUTPUT AS #1
                  FOR Record=3001 TO 3014
                  SomeVar1 = VAL(DATE$)
                  SomeVar2 = VAL(TIME$)
                  WRITE #1, Record-3000, 0, 0, 0, SomeVar1, 0, 0, SomeVar2, Record
                  INCR Count
                  NEXT
                  CLOSE #1

                  '--------------- write the number of lines on Line 1

                  OPEN "RANDOM.DTA" FOR RANDOM AS #1 LEN = LEN(Line1Str)
                  Line1Str = LTRIM$(STR$(Count))
                  PUT #1, 1, Line1Str
                  CLOSE #1

                  END FUNCTION
                  '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'

                  ------------------
                  Kind Regards
                  Mike

                  Comment


                  • #10
                    Look up the SEEK command. You can place a header at the beginning
                    of a file, like a full structure or a variable, using PUT/GET, then
                    use SEEK to set position to proper place and WRITE/INPUT whatever
                    you need.

                    If header is just one LONG, PUT/GET it at beginning of file, then
                    use, SEEK #1, 4 to set position for further WRITE/PRINT/INPUT..

                    Correction: Should be SEEK #1, 5, unless you have you used BASE = 0
                    on the OPEN line (according to PB's helpfile).
                    ------------------


                    [This message has been edited by Borje Hagsten (edited March 04, 2001).]

                    Comment


                    • #11
                      Sorry Borje, that went right over my head. Can you use my example to show me pls

                      Actually, I have 3 or 4 variables to write on the first line. the first of which is the total number of lines in the file.

                      ------------------
                      Kind Regards
                      Mike

                      Comment


                      • #12
                        Mike, perhaps it would be easier to create a second file to
                        contain statistics / pointers for the first file?



                        ------------------
                        Bernard Ertl
                        Bernard Ertl
                        InterPlan Systems

                        Comment


                        • #13
                          No can do Bern. First Line has to contain all the pertinant info about the file and the data in the file. Thats the format im trying to emulate.

                          Of course I could just copy the first file to a second file and write the first line correctly as I do it, but for 10k+ lines that seems kinda lame.

                          It must be possible to write randomly to a file without being constrained to Binary data surely?

                          ------------------
                          Kind Regards
                          Mike

                          Comment


                          • #14
                            Okay, so a bit more complicated, if each line must be separate string
                            and first line hold file data in form of a string. Forget SEEK. Here's
                            a way of doing it - involves reading entire file into an array:
                            Code:
                            LOCAL I AS LONG, J AS LONG, hString AS STRING, tmp AS STRING, Rec() AS TestRec
                             
                            'Create first instance of test file
                            OPEN "RANDOM.DTA" FOR OUTPUT AS #1
                              PRINT #1, FORMAT$(I) 'empty line, for file data
                              FOR I = 1 TO 3
                                PRINT #1, "Joe" + STR$(I)
                                PRINT #1, FORMAT$(I)
                              NEXT
                            CLOSE #1
                             
                            'Read test file into array
                            I = 0
                            OPEN "RANDOM.DTA" FOR INPUT AS #1
                              IF LOF(1) THEN LINE INPUT #1, hString 'read file data separately
                              DO WHILE NOT EOF(1)
                                 IF I MOD 20 = 0 THEN REDIM PRESERVE Rec(I + 20)
                                 LINE INPUT #1, Rec(I).uName
                                 LINE INPUT #1, tmp
                                 Rec(I).uNumber = VAL(tmp)
                                 INCR I
                              LOOP
                              DECR I
                              REDIM PRESERVE Rec(I)
                            CLOSE #1
                            MSGBOX hString & $CRLF & Rec(0).uName & STR$(Rec(0).uNumber)
                             
                            'Write all back, including first line data
                            OPEN "RANDOM.DTA" FOR OUTPUT AS #1
                              PRINT #1, FORMAT$(I) 'print file data separately
                              FOR J = 0 TO I
                                PRINT #1, Rec(J).uName
                                PRINT #1, FORMAT$(Rec(J).uNumber)
                              NEXT
                            CLOSE #1
                             
                            'Check to see that it worked
                            I = 0
                            OPEN "RANDOM.DTA" FOR INPUT AS #1
                              IF LOF(1) THEN LINE INPUT #1, hString
                              DO WHILE NOT EOF(1)
                                 IF I MOD 20 = 0 THEN REDIM PRESERVE Rec(I + 20)
                                 LINE INPUT #1, Rec(I).uName
                                 LINE INPUT #1, tmp
                                 Rec(I).uNumber = VAL(tmp)
                                 INCR I
                              LOOP
                              REDIM PRESERVE Rec(I - 1)
                            CLOSE #1
                            MSGBOX hString & $CRLF & Rec(0).uName & STR$(Rec(0).uNumber)

                            ------------------


                            [This message has been edited by Borje Hagsten (edited March 04, 2001).]

                            Comment


                            • #15
                              Borje,
                              Thanks so much for that example. That will work but it seems crazy to have to read the whole file into memory just to write the first line.

                              I might as well just read each line of the file and write it to a new file. That way I can write the first line with all the data needed.

                              Also If I use a file with 1min data, thats 405 lines per day, 5 days per week, 52 weeks per year = 105300. I need to go back at least 4 years so thats 421000 lines.

                              I would much rather find a way to over write the first line!

                              ------------------
                              Kind Regards
                              Mike

                              Comment


                              • #16
                                Personally, I'd "reserve" a fixed number of bytes at the beginning of the file, using some muliple of the actual data record size.

                                Then you can write to that portion of the file with BINARY mode, and reopen the file in RANDOM mode and read the records.

                                For example, if your record is 32 bytes, reserve the 1st two records for the "ascii" data, and start your real records at byte 65 (record 3). You could also read/write the records in binary mode too - what ever is easier for you. The following technique will enable the first 24 bytes to be read with LINE INPUT if required.
                                Code:
                                ' pseudocode:
                                TYPE TestRec
                                  uName AS STRING * 10
                                  uNumber AS INTEGER
                                END TYPE
                                 
                                TYPE HeaderRec
                                  Header AS STRING * 22 ' (10 + 2) * 2 - 2
                                  Terminator AS STRING * 2
                                END TYPE
                                  
                                Dim Rec AS TestRec
                                Dim Header As HeaderRec
                                 
                                Header.Header = "Record Count = " + FORMAT$(RecCount&)
                                Header.Terminator = $CRLF
                                 
                                OPEN file$ FOR BINARY AS #1
                                 PUT$ #1,, Header
                                CLOSE #1
                                
                                OPEN file$ FOR RANDOM AS #1
                                 FOR x& = 3 to (LOF(1) - LEN(Header)) \ LEN(Rec)
                                  GET #1, x&, Rec
                                  '... process Rec
                                 NEXT x&
                                CLOSE #1
                                 
                                ' Now read the first two records as you would a sequential file.
                                OPEN file$ FOR INPUT AS #1
                                 LINE INPUT #1, a$
                                 MSGBOX a$
                                CLOSE
                                Anyway, I hope you get the idea.


                                ------------------
                                Lance
                                PowerBASIC Support
                                mailto:[email protected][email protected]</A>
                                Lance
                                mailto:[email protected]

                                Comment


                                • #17
                                  There many ways to do this. Problem is you need the file to be like
                                  ordinary text file, if I have understood this correctly. If each
                                  record (line) has same length, the following may give you an idea
                                  of a better way:
                                  Code:
                                  #COMPILE EXE "Random.exe"
                                   
                                  TYPE TestRec
                                    uName   AS STRING * 10
                                    uNumber AS STRING * 10
                                  END TYPE
                                   
                                  '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'
                                  FUNCTION PBMAIN
                                  LOCAL I AS LONG, hString AS STRING, Rec AS TestRec
                                   
                                  'Create test file
                                  OPEN "RANDOM.DTA" FOR OUTPUT AS #1
                                    PRINT #1, SPACE$(10)
                                    FOR I = 1 TO 3
                                       Rec.uName = "Joe" + STR$(I)
                                       Rec.uNumber = FORMAT$(I)
                                      PRINT #1, Rec.uName
                                      PRINT #1, Rec.uNumber
                                    NEXT
                                  CLOSE #1
                                   
                                  'Test to see whole file
                                  OPEN "RANDOM.DTA" FOR BINARY AS #1
                                     hString = SPACE$(LOF(1))
                                     GET #1,, hString
                                  CLOSE #1
                                  MSGBOX hString
                                   
                                  'Change header
                                  OPEN "RANDOM.DTA" FOR BINARY AS #1 BASE = 0
                                     hString = FORMAT$(I - 1)     '<- Change header
                                     PUT #1,, hString
                                   
                                     I = 1
                                     Rec.uName = "Borje" + STR$(I)
                                     SEEK #1, I * 12               '<- set position to first record
                                     PUT #1,, Rec.uName            '<- put changed data
                                  CLOSE #1
                                   
                                  'Test to see whole file
                                  OPEN "RANDOM.DTA" FOR BINARY AS #1
                                     hString = SPACE$(LOF(1))
                                     GET #1,, hString
                                  CLOSE #1
                                  MSGBOX hString
                                   
                                  END FUNCTION

                                  ------------------

                                  Comment


                                  • #18
                                    Thx Lance, But I have to adhere to the file format im trying to emulate ie all Ascii charaters/Numbers

                                    Borje,
                                    Thx for that example. I have examined it carefully. I am trying to avoing reading 100k lines into memory tho.

                                    I think I must simply create another file and reall all the lines one by one in and write them to the new file.

                                    It is becoming obvious that RANDOM was designed for Binary read/Write and not Ascii data like the INPUT# and WRITE# cousins.

                                    Thx again

                                    ------------------
                                    Kind Regards
                                    Mike

                                    Comment


                                    • #19
                                      It is becoming obvious that RANDOM was designed for Binary read/Write and not Ascii data like the INPUT# and WRITE# cousins.
                                      No, that's not correct. The *type* of data - printable or unprintable - has nothing to do with the *access mode* used (except as below).

                                      INPUT# and WRITE#/PRINT# were designed for *sequential* access.

                                      PUT/GET/SEEK were designed for random (small letters) access.

                                      The only place data "type" makes a difference is in the INPUT# or LINE INPUT# verbs, where the verb means, "read from the current file pointer forwar up to the next comma/CRLF/EOF and advance the pointer beyond the delimiter." Consequently, you cannot use these verbs with data which may be *interpreted* as one of the delimiter characters.

                                      The so-called "binary" representation of the the integer value 13 would be interpreted as CHR$(13) + CHR$(0) , or carriage return, nul; so LINE INPUT$ should not be used to get the value of 16-bit integers expressed in native ("binary") format.

                                      MCM

                                      Michael Mattias
                                      Tal Systems Inc. (retired)
                                      Racine WI USA
                                      [email protected]
                                      http://www.talsystems.com

                                      Comment


                                      • #20
                                        I don't understand. If you use my last sample, you can change any
                                        record with the help of SEEK and PUT. No need to read whole file
                                        into memory, even though 100KB isn't much today.. :-)


                                        ------------------

                                        Comment

                                        Working...
                                        X