Qbasicnews.com
February 27, 2020, 07:25:14 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: Back to Qbasicnews.com | QB Online Help | FAQ | Chat | All Basic Code | QB Knowledge Base
 
   Home   Help Search Login Register  
Pages: [1] 2
  Print  
Author Topic: How can QBasic write to certain lines of a file?  (Read 6474 times)
moochthemonkey
I hold this place together
*****
Posts: 801



« on: November 09, 2004, 10:13:03 PM »

How can qbasic write to a certain line of a file that already has text in it, without using the command APPEND to add on to the end of the file, or use the command OUTPUT to overwrite the file entirely? Thanks!
Logged

quote="na_th_an"]
Greenday, Spice Girls... Can you tell the difference?
[/quote]
potato
Ancient QBer
****
Posts: 409



WWW
« Reply #1 on: November 09, 2004, 10:24:30 PM »

cannot do using intrinsic QB
best way i know is to open the file, read the contents into an array, shift stuff down and insert, then reoutput

but you nerds can think of better.
Logged

ammit potato!
whitetiger0990
__/--\__
*****
Posts: 2964



WWW
« Reply #2 on: November 09, 2004, 10:35:39 PM »

that's if you want to insert. He said replace. But it's the same thing w/o shifting.
Logged


[size=10]Back by popular demand!
I will byte and nibble you bit by bit until nothing remains but crumbs.[/size]
Meg
Ancient QBer
****
Posts: 483


« Reply #3 on: November 10, 2004, 01:24:44 AM »

Although you'd prolly have to modify a lot of code if this is for an existing project, you could take a look at opening files for random-access.  Then you can declare a record-length and input/output to any part of the file you want.

see "OPEN filename FOR RANDOM AS #1 LEN = recordlength"

*peace*

Meg.
Logged
jatos
Ancient QBer
****
Posts: 464



« Reply #4 on: November 10, 2004, 05:03:03 AM »

alternatively you open it so you modify in binary, which allows you to do anything to the file. ALthough for this you may need to write some complicated routine. With ascii text files look at the ascii character codes, every two bits is a ascii code in the file.
Logged

atos-Software
http://www.datacentertalk.com - interested in how web hosting works? Here the place to go to find out.
Moneo
Na_th_an
*****
Posts: 1971


« Reply #5 on: November 13, 2004, 10:01:09 PM »

Quote from: "Offensive Screename"
How can qbasic write to a certain line of a file that already has text in it, without using the command APPEND to add on to the end of the file, or use the command OUTPUT to overwrite the file entirely? Thanks!

If you don't have experience with Random or Binary files, and you're not ready to learn now, then you're going to have to:
* Open your input file and open an output file to contain the updated file.
* Read records form the input file, writing them to the output file until you get to the record to be replaced.
* Write the record being replaced.
* Read and write the rest of the records.

Unless you have a very large input file, say more than 10,000 records, or your records are very large, you won't hardly notice the time to do this unless you have a very old, slow machine. Try it.

Keep It Simple.
*****
Logged
Licentia
Member
*
Posts: 57



« Reply #6 on: November 16, 2004, 11:00:39 PM »

Quote from: "Offensive Screename"
How can qbasic write to a certain line of a file that already has text in it, without using the command APPEND to add on to the end of the file, or use the command OUTPUT to overwrite the file entirely? Thanks!



  Maybe this will work:

 (This will be my first time ever offering help, rather than asking  Cheesy)

Code:


INPUT "which line do you want to replace?  choose a number from 1 to 5"; A

'which line of the 5 lines do you want to change?  maybe line 4?
'These are the lines in the text file.  Create a text file
'and make 5 lines like so:  then name it whatever.txt
'12
'23
'45
'56
'98

INPUT "what number do you want to replace it with"; B

'now choose what number you want to have replace what's printed
'on that particular line you chose.

DIM C(1 TO 5)

OPEN "whatever.txt" FOR INPUT AS #1

'C(1 to 5) contains the numbers in the text file

FOR D = 1 TO 5
  INPUT #1, C(D)
  E = E + 1   'E increases 1 each time through the loop.
  IF E = A THEN  'If E equals the line number you chose.....
    C(D) = B  'C(D) changes to the value you chose.
  END IF
NEXT D

CLOSE #1

OPEN "whatever.txt" FOR OUTPUT AS #1

'now everything is printed out to the same text file.

FOR D = 1 TO 5
  PRINT #1, C(D)
NEXT D

CLOSE #1

Logged
moochthemonkey
I hold this place together
*****
Posts: 801



« Reply #7 on: November 16, 2004, 11:15:00 PM »

Thanks guys! I'll check this stuff out..

Actually, what I really wanted to do was just take all the lines in one file, assemble them into one line Cheesy
Logged

quote="na_th_an"]
Greenday, Spice Girls... Can you tell the difference?
[/quote]
Licentia
Member
*
Posts: 57



« Reply #8 on: November 16, 2004, 11:30:32 PM »

Quote from: "Offensive Screename"
Thanks guys! I'll check this stuff out..

Actually, what I really wanted to do was just take all the lines in one file, assemble them into one line Cheesy


  Like so:  ?

CLS

INPUT "how many lines are we talking here"; A

OPEN "whatever.txt" FOR INPUT AS #1

DIM C(1 TO A)

'load all the lines into memory:

FOR B = 1 TO A
  INPUT #1, C(B)
NEXT B

CLOSE #1

OPEN "another.txt" FOR OUTPUT AS #1

'print all the lines back in less lines thanks to the semi-colon ;

FOR B = 1 TO A
  PRINT #1, C(B);
NEXT B

CLOSE #1
Logged
Moneo
Na_th_an
*****
Posts: 1971


« Reply #9 on: November 20, 2004, 11:47:25 PM »

Quote from: "Offensive Screename"
Thanks guys! I'll check this stuff out..

Actually, what I really wanted to do was just take all the lines in one file, assemble them into one line Cheesy

Your original request and what you "really want" are totally different. Thanks for sending us on a wild goose chase. :wink:
*****
Logged
Moneo
Na_th_an
*****
Posts: 1971


« Reply #10 on: November 21, 2004, 12:15:11 AM »

Licentia, A few suggestions on your code.

1) You shouldn't trust the user to give you the correct number of lines on the file.  Open, read, and count every record into your variable A.

2) When you intend reading every record from a file, don't rely on an external counter to control a FOR loop, read every record until End-Of-File as follows:
Code:
open "xxx.fil" for input as #1
do while not eof(1)
      line input #1,rec$
      xxxxxxxxxxx
loop
close #1


3) In your last loop, where you write out the records concatenating them by using the semicolon --- you obviously didn't test this, because the entire record will not be written out. It will sit there suspended waiting for a PRINT #1 instruction without a semicolon. So, after the NEXT B, do a PRINT #1.

4) In general your solution is ok unless you have lots of records; that is, records with a total number of bytes in excess of 32K. If that happens, you will overflow the C array.

5) Actually, you dont need to store the data in an array. Open the input file and open a different output file. Then, as you read a record from the input file, write it to the output file using the semicolon technique. This way you don't need to figure out how many records there are, and no need for an array. Again, if the number of records is too large, the PRINT comand will hang up because it will be holding too many bytes in it's buffer, because of the semicolon.

P.S. Licencia, are you male or female?
*****
Logged
Neo
Na_th_an
*****
Posts: 2150



« Reply #11 on: November 21, 2004, 07:58:33 AM »

Slow, but functional (method BINARY):
[syntax="QBasic"]'@@@@@@@@@@@@@@@@
' Standard Stuff
'@@@@@@@@@@@@@@@@
DEFINT A-Z
'$DYNAMIC

'@@@@@@@@@@@@@@@@@
' Open Input File
'@@@@@@@@@@@@@@@@@
FF = FREEFILE
OPEN "LARGE.TXT" FOR BINARY AS #FF
   '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ' Get length, calc buffer size etc
   '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   flen& = LOF(FF)
   SEEK #FF, 1
   buffersize = FRE("") \ 5
   got& = 0
   '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ' Open Output File (delete if exists)
   '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   FE = FREEFILE
   OPEN "OUTPUT.TXT" FOR OUTPUT AS #FE
   CLOSE #FE
   OPEN "OUTPUT.TXT" FOR BINARY AS #FE
      '@@@@@@@@@@@@@@@@@@@@@@@@@@
      ' Read all bytes from file
      '@@@@@@@@@@@@@@@@@@@@@@@@@@
      DO UNTIL got& = flen&
         '@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         ' Buffer too big? Resize it!
         '@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         IF got& + buffersize > flen& THEN buffersize = flen& - got&
         '@@@@@@@@@@@@@@@@@@@@@@@@
         ' Fill buffer with bytes
         '@@@@@@@@@@@@@@@@@@@@@@@@
         Buffer$ = SPACE$(buffersize)
         GET #FF, , Buffer$

         '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         ' Delete all ASCII character 10 and 13
         '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         conv$ = ""
         FOR I = 1 TO buffersize
            IF MID$(Buffer$, I, 1) <> CHR$(10) AND MID$(Buffer$, I, 1) <> CHR$(13) THEN conv$ = conv$ + MID$(Buffer$, I, 1)
         NEXT I

         '@@@@@@@@@@@@@@@@@@@@@@
         ' Write to output file
         '@@@@@@@@@@@@@@@@@@@@@@
         PUT #FE, , conv$

         '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         ' Update counter to prevent eternal loop
         '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         got& = got& + buffersize
      LOOP
   CLOSE #FE
CLOSE #FF[/syntax]

Another way to do all this, faster and easier (method INPUT):
[syntax="QBasic"]'@@@@@@@@@@@@@@@@
' Standard Stuff
'@@@@@@@@@@@@@@@@
DEFINT A-Z
'$DYNAMIC

'@@@@@@@@@@@@@@@@@
' Open input file
'@@@@@@@@@@@@@@@@@
FF = FREEFILE
OPEN "LARGE.TXT" FOR INPUT AS #FF
   '@@@@@@@@@@@@@@@@@@
   ' Open output file
   '@@@@@@@@@@@@@@@@@@
   FE = FREEFILE
   OPEN "OUTPUT.TXT" FOR OUTPUT AS #FE
      '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      ' Read all lines from the file (EOF = End Of File)
      '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      DO UNTIL EOF(FF)
         '@@@@@@@@@@@@@@@@@@@
         ' Read line of data
         '@@@@@@@@@@@@@@@@@@@
         LINE INPUT #FF, somedata$
         '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         ' Print it in file without the usual CrLf
         '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         PRINT #FE, somedata$;
      LOOP
   CLOSE #FE
CLOSE #FF[/syntax]

Moneo: the code I posted (with the INPUT) works Wink
Quote from: "Moneo"
3) In your last loop, where you write out the records concatenating them by using the semicolon --- you obviously didn't test this, because the entire record will not be written out. It will sit there suspended waiting for a PRINT #1 instruction without a semicolon. So, after the NEXT B, do a PRINT #1.

No. All suspended data will be written when the file is closed using CLOSE. If you do a PRINT #1 after the NEXT B, you'll get a CrLf at the end of your file, which is not what you want.

Quote from: "Moneo"
5) Actually, you dont need to store the data in an array. Open the input file and open a different output file. Then, as you read a record from the input file, write it to the output file using the semicolon technique. This way you don't need to figure out how many records there are, and no need for an array. Again, if the number of records is too large, the PRINT comand will hang up because it will be holding too many bytes in it's buffer, because of the semicolon.

Unless that PRINT command buffer is 10 MB, the code just works Wink (I tried it on files of 10 MB). Obviously either #1 The print command writes immediately to file without CrLf, or #2 The print command detects itself when the buffer is full and then writes to file.
Logged
Moneo
Na_th_an
*****
Posts: 1971


« Reply #12 on: November 21, 2004, 10:39:39 PM »

I actually never tried writing to a file using the semicolon. I guess you're right, the close will flush the write. I know that the semicolon thing won't work when printing to the screen or a printer (LPRINT), 'cause there's no close to flush out the print.

Regarding the buffer which holds the data suspended by the semicolon, I really don't know where that buffer is nor how long it can be. 10 Mb worked for you, well that's bigger than what I would have thought. Interesting!
*****
Logged
Neo
Na_th_an
*****
Posts: 2150



« Reply #13 on: November 22, 2004, 04:37:00 AM »

Quote from: "Moneo"
I actually never tried writing to a file using the semicolon. I guess you're right, the close will flush the write. I know that the semicolon thing won't work when printing to the screen or a printer (LPRINT), 'cause there's no close to flush out the print.

Actually there is... but it's not a command in QB. You'll have to send the EndDoc command or similar to the printer by means of LPRINT. I never tried printing in QB (my LPT1 is already full), but that's how I think it can be done.
About the screen, what exactly do you mean? The print for screen command just works with the semicolon as well, I've used it numerous times.

Quote from: "Moneo"
Regarding the buffer which holds the data suspended by the semicolon, I really don't know where that buffer is nor how long it can be. 10 Mb worked for you, well that's bigger than what I would have thought. Interesting!

Yes, it is interesting. I think it's either of my suggestions #1 and #2 (previous post), or something completely different I didn't think of. 10 MB is a bit much for a buffer... Wink
Logged
Licentia
Member
*
Posts: 57



« Reply #14 on: November 23, 2004, 05:10:59 PM »

Quote from: "Moneo"
Licentia, A few suggestions on your code.

1) You shouldn't trust the user to give you the correct number of lines on the file.  Open, read, and count every record into your variable A.



  I don't know yet how to do any differently, other than maybe to say that if the variable < 0 or something then don't load.


Quote from: "Moneo"

2) When you intend reading every record from a file, don't rely on an external counter to control a FOR loop, read every record until End-Of-File as follows:
Code:
open "xxx.fil" for input as #1
do while not eof(1)
      line input #1,rec$
      xxxxxxxxxxx
loop
close #1



  I'll try that.  I've been needing such a command.

Quote from: "Moneo"

3) In your last loop, where you write out the records concatenating them by using the semicolon --- you obviously didn't test this, because the entire record will not be written out. It will sit there suspended waiting for a PRINT #1 instruction without a semicolon. So, after the NEXT B, do a PRINT #1.


  I thought I had, but I typed in the comments after right into the post, and I must have deleted something while doing so.

Quote from: "Moneo"

4) In general your solution is ok unless you have lots of records; that is, records with a total number of bytes in excess of 32K. If that happens, you will overflow the C array.


  I know, that's happened to me lots, and I don't know how to get around it.

Quote from: "Moneo"

5) Actually, you dont need to store the data in an array. Open the input file and open a different output file. Then, as you read a record from the input file, write it to the output file using the semicolon technique. This way you don't need to figure out how many records there are, and no need for an array. Again, if the number of records is too large, the PRINT comand will hang up because it will be holding too many bytes in it's buffer, because of the semicolon.


  I've seen other QuickBasic software that doesn't have any problems inputing large amounts of data.  Inputing 12,000 plus lines of 6/49 combinations from a file without any output to another file whatsoever.  I haven't found a way to do that.  

Quote from: "Moneo"

P.S. Licencia, are you male or female?
*****


  I don't see why that's relevant, but Male.  My avatar picture is Alis from Phantasy Star 1.  One of my favorite old games..  I wanted to put something else, but I couldn't find a small enough pic of anything I wanted.
Logged
Pages: [1] 2
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!