Author Topic: Opening files  (Read 8302 times)

0 Members and 1 Guest are viewing this topic.

Offline Jon Richfield

  • Newbie
  • Posts: 14
    • View Profile
Opening files
« on: June 08, 2020, 02:56:06 am »
Suppose I wish to process a file in a QB64 program. Of course I can read in the file name and path from the keyboard; however, often one wants to click on a file in a directory display and open the file with the program in question.
Can anyone please direct me to instructions for how to do that sort of thing.

Thanks for any suggestions.

Offline codeguy

  • Forum Regular
  • Posts: 174
    • View Profile
Re: Opening files
« Reply #1 on: June 08, 2020, 05:16:59 am »
You've got to use COMMAND$

https://www.qb64.org/wiki/COMMAND$
« Last Edit: June 08, 2020, 05:18:25 am by codeguy »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #2 on: June 08, 2020, 10:21:39 am »
Or do you mean a way to display a list of files and directories in QB64, select a file in that list and run some action, all in QB64? This can also be done with QB64.

You can either call a window from Windows via a library declaration to select a file, or you can write the whole thing and use DIRENTRY.H from Steve to list files and directories.

https://www.qb64.org/forum/index.php?topic=321.msg2126#msg2126
« Last Edit: June 08, 2020, 10:32:34 am by Petr »

Offline Jon Richfield

  • Newbie
  • Posts: 14
    • View Profile
Re: Opening files
« Reply #3 on: June 10, 2020, 12:16:12 pm »
Thanks Petr and Codeguy. I'll have to go into this to see what best applies to my requirements.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Opening files
« Reply #4 on: June 10, 2020, 01:30:29 pm »
If you have Windows and don't want to worry about Linux or Mac users (ie doing a cross platform app) there are easier ways.

Code: QB64: [Select]
  1. _TITLE "Tiny Navigator: press f to window and select a file" 'B+ started 2019-08-22
  2. SCREEN _NEWIMAGE(1000, 600, 32)
  3. _SCREENMOVE 100, 50
  4. ' 2019-08-22 orig post at https://www.qb64.org/forum/index.php?topic=1646.msg108682#msg108682
  5. ' 2019-08-23_13-25 try fix (to nav all directories) with one place for tmpFile, theory can't write files in some dir's
  6. ' For some reason Windows won't write to a fully pathed file in my user folder???from a SHELL command
  7. ' Try testing if dir exists "C:\temp" exists and making one if not, yes! and I can write my temp files there
  8. ' and now I can chDir anywhere!!!!
  9. ' 2019-08-23_14-25 Take Steve's Advice to use users tmp directory for temp files
  10. ' 2019-08-23_23+ Have files window working for file selection
  11.  
  12. DIM SHARED selectedFile AS STRING
  13. DIM SHARED tmpDir AS STRING '  establish a permanent spot for temp files
  14. IF ENVIRON$("TEMP") <> "" THEN 'Thanks to Steve McNeill use user temp files directory
  15.     tmpDir = ENVIRON$("TEMP")
  16. ELSEIF ENVIRON$("TMP") <> "" THEN
  17.     tmpDir = ENVIRON$("TMP")
  18. ELSE 'Thanks to Steve McNeill this should be very unlikely
  19.     IF _DIREXISTS("C:\temp") THEN ELSE MKDIR "C:\temp"
  20.     tmpDir = "C:\temp"
  21.  
  22. DIM mySelection&, done$, i, t$
  23.     COLOR _RGB32(180, 180, 255)
  24.     CLS
  25.     t$ = "Current Directory: " + _CWD$
  26.     LOCATE 2, (_WIDTH / 8 - LEN(t$)) / 2: PRINT t$
  27.     REDIM DIRs(0) AS STRING
  28.     loadDIR DIRs()
  29.     REDIM FILs(0) AS STRING
  30.     loadFiles FILs()
  31.     FOR i = 0 TO UBOUND(FILs)
  32.         IF i < 30 THEN LOCATE i + 4, 60: PRINT FILs(i) ELSE EXIT FOR
  33.     NEXT
  34.     mySelection& = getArrayItemNumber&(5, 5, 50, 30, DIRs())
  35.     CLS
  36.     IF selectedFile <> "" THEN
  37.         PRINT "You selected a file: "; selectedFile
  38.         INPUT "Press enter to continue navigator, any + enter to quit... "; done$
  39.         selectedFile = ""
  40.     ELSEIF mySelection& <> -1719 THEN
  41.         CHDIR DIRs(mySelection&)
  42.     ELSE
  43.         PRINT "Nothing selected."
  44.         INPUT "Press enter to continue navigator, any + enter to quit... "; done$
  45.     END IF
  46.     _LIMIT 60
  47. LOOP UNTIL done$ <> ""
  48.  
  49. SUB loadDIR (fa() AS STRING)
  50.     DIM tmpFile AS STRING, Index%, fline$, d$
  51.     tmpFile = tmpDir + "\DIR$INF0.INF" 'aha!, not a fully pathed file to user directory but here is good!
  52.     SHELL _HIDE "DIR /a:d >" + tmpFile 'get directories  but have to do a little pruning
  53.     OPEN tmpFile FOR INPUT AS #1
  54.     Index% = -1
  55.     DO WHILE NOT EOF(1)
  56.         LINE INPUT #1, fline$
  57.         IF INSTR(fline$, "<DIR>") THEN
  58.             d$ = _TRIM$(rightOf$(fline$, "<DIR>"))
  59.             Index% = Index% + 1
  60.             REDIM _PRESERVE fa(Index%)
  61.             fa(Index%) = d$
  62.         END IF
  63.     LOOP
  64.     CLOSE #1
  65.     KILL tmpFile
  66.  
  67. SUB loadFiles (fa() AS STRING)
  68.     DIM tmpFile AS STRING, Index%
  69.     tmpFile = tmpDir + "\FILE$INF0.INF" 'aha!, not a fully pathed file to user directory but here is good!
  70.     SHELL _HIDE "DIR *.* /a:-d /b /o:-gen > " + tmpFile
  71.     OPEN tmpFile$ FOR INPUT AS #1
  72.     Index% = -1
  73.     DO WHILE NOT EOF(1)
  74.         Index% = Index% + 1
  75.         REDIM _PRESERVE fa(Index%) AS STRING
  76.         LINE INPUT #1, fa(Index%)
  77.     LOOP
  78.     CLOSE #1
  79.     KILL tmpFile$
  80.  
  81. FUNCTION rightOf$ (source$, of$)
  82.     IF INSTR(source$, of$) > 0 THEN rightOf$ = MID$(source$, INSTR(source$, of$) + LEN(of$))
  83.  
  84. ' "Escape returns -1719 to allow a Cancel function and signal no slection."
  85. FUNCTION getArrayItemNumber& (locateRow, locateColumn, boxWidth, boxHeight, arr() AS STRING)
  86.     'Notes: locateRow, locateColumn for top right corner of selection box on screen in characters for LOCATE.
  87.     'boxWidth and boxHeight are in character units, again for locate and print at correct places.
  88.     'All displaying is restricted to inside the box, which has PgUP and PgDn as top and bottom lines in the display.
  89.  
  90.     DIM curRow AS INTEGER, curCol AS INTEGER, fg AS _UNSIGNED LONG, bg AS _UNSIGNED LONG
  91.     DIM maxWidth AS INTEGER, maxHeight AS INTEGER, page AS INTEGER, hlite AS INTEGER, mx AS INTEGER, my AS INTEGER
  92.     DIM lastMX AS INTEGER, lastMY AS INTEGER, row AS INTEGER, mb AS INTEGER
  93.     DIM lba AS LONG, uba AS LONG, choice AS LONG, kh AS LONG, index AS LONG
  94.     DIM clrStr AS STRING, b AS STRING, selNum&
  95.  
  96.     'save old settings to restore at end ofsub
  97.     curRow = CSRLIN
  98.     curCol = POS(0)
  99.     fg = _DEFAULTCOLOR
  100.     bg = _BACKGROUNDCOLOR
  101.     _KEYCLEAR
  102.  
  103.     maxWidth = boxWidth '       number of characters in box
  104.     maxHeight = boxHeight - 2 ' number of lines displayed of array at one time = 1 page
  105.     lba = LBOUND(arr)
  106.     uba = UBOUND(arr)
  107.     page = 0
  108.     hlite = 0 '                 line in display ready for selection by spacebar or if no number is started, enter
  109.     clrStr$ = SPACE$(maxWidth) 'clearing a display line
  110.  
  111.     GOSUB update '              show the beginning of the array items for selection
  112.  
  113.     'signal cancel selection process, exit sub with this unlikely index to signal canel
  114.     choice = -1719 'primes 7 and 8, not likely to be a select index of an array
  115.  
  116.     DO 'until get a selection or demand exit
  117.  
  118.         'handle the key stuff
  119.         kh& = _KEYHIT
  120.         IF kh& THEN
  121.             IF kh& > 0 AND kh& < 255 THEN
  122.                 IF INSTR("0123456789", CHR$(kh&)) > 0 THEN b$ = b$ + CHR$(kh&): GOSUB update
  123.                 IF CHR$(kh&) = "f" THEN
  124.                     REDIM FILs(0) AS STRING
  125.                     loadFiles FILs()
  126.                     selNum& = getArrayItemNumber&(5, 60, 60, 30, FILs())
  127.                     COLOR _RGB32(180, 180, 255)
  128.                     CLS 'need to signal out of file selection
  129.                     IF selNum& >= LBOUND(FILs) AND selNum& <= UBOUND(FILs) THEN selectedFile = FILs(selNum&)
  130.                     EXIT DO
  131.                     'back to directory select
  132.                 END IF
  133.  
  134.                 IF CHR$(kh&) = "c" THEN b$ = "": GOSUB update
  135.                 IF kh& = 13 THEN 'enter pressed check if number is being entered?
  136.                     IF LEN(b$) THEN
  137.                         IF VAL(b$) >= lba AND VAL(b$) <= uba THEN 'we have number started
  138.                             choice = VAL(b$): EXIT DO
  139.                         ELSE 'clear b$ to show some response to enter
  140.                             b$ = "": GOSUB update 'clear the value that doesn't work
  141.                         END IF
  142.                     ELSE
  143.                         choice = hlite + page * maxHeight + lba 'must mean to select the highlighted item
  144.                     END IF
  145.                 END IF
  146.                 IF kh& = 27 THEN EXIT DO 'escape clause offered to Cancel selection process
  147.                 IF kh& = 32 THEN choice = hlite + page * maxHeight + lba 'best way to choose highlighted selection
  148.                 IF kh& = 8 THEN 'backspace to edit number
  149.                     IF LEN(b$) THEN b$ = LEFT$(b$, LEN(b$) - 1): GOSUB update
  150.                 END IF
  151.             ELSE
  152.                 SELECT CASE kh& 'choosing sections of array to display and highlighted item
  153.                     CASE 20736 'pg dn
  154.                         IF (page + 1) * maxHeight + lba <= uba THEN page = page + 1: GOSUB update
  155.                     CASE 18688 'pg up
  156.                         IF (page - 1) * maxHeight + lba >= lba THEN page = page - 1: GOSUB update
  157.                     CASE 18432 'up
  158.                         IF hlite - 1 < 0 THEN
  159.                             IF page > 0 THEN
  160.                                 page = page - 1: hlite = maxHeight - 1: GOSUB update
  161.                             END IF
  162.                         ELSE
  163.                             hlite = hlite - 1: GOSUB update
  164.                         END IF
  165.                     CASE 20480 'down
  166.                         IF (hlite + 1) + page * maxHeight + lba <= uba THEN 'ok to move up
  167.                             IF hlite + 1 > maxHeight - 1 THEN
  168.                                 page = page + 1: hlite = 0: GOSUB update
  169.                             ELSE
  170.                                 hlite = hlite + 1: GOSUB update
  171.                             END IF
  172.                         END IF
  173.                     CASE 18176 'home
  174.                         page = 0: hlite = 0: GOSUB update
  175.                     CASE 20224 ' end
  176.                         page = INT((uba - lba) / maxHeight): hlite = maxHeight - 1: GOSUB update
  177.                 END SELECT
  178.             END IF
  179.         END IF
  180.  
  181.         'handle the mouse stuff
  182.         WHILE _MOUSEINPUT
  183.             IF _MOUSEWHEEL = -1 THEN 'up?
  184.                 IF hlite - 1 < 0 THEN
  185.                     IF page > 0 THEN
  186.                         page = page - 1: hlite = maxHeight - 1: GOSUB update
  187.                     END IF
  188.                 ELSE
  189.                     hlite = hlite - 1: GOSUB update
  190.                 END IF
  191.             ELSEIF _MOUSEWHEEL = 1 THEN 'down?
  192.                 IF (hlite + 1) + page * maxHeight + lba <= uba THEN 'ok to move up
  193.                     IF hlite + 1 > maxHeight - 1 THEN
  194.                         page = page + 1: hlite = 0: GOSUB update
  195.                     ELSE
  196.                         hlite = hlite + 1: GOSUB update
  197.                     END IF
  198.                 END IF
  199.             END IF
  200.         WEND
  201.         mx = INT((_MOUSEX - locateColumn * 8) / 8) + 2: my = INT((_MOUSEY - locateRow * 16) / 16) + 2
  202.         IF _MOUSEBUTTON(1) THEN 'click contols or select array item
  203.             'clear mouse clicks
  204.             mb = _MOUSEBUTTON(1)
  205.             IF mb THEN 'clear it
  206.                 WHILE mb 'OK!
  207.                     IF _MOUSEINPUT THEN mb = _MOUSEBUTTON(1)
  208.                     _LIMIT 100
  209.                 WEND
  210.             END IF
  211.  
  212.             IF mx >= 1 AND mx <= maxWidth AND my >= 1 AND my <= maxHeight THEN
  213.                 choice = my + page * maxHeight + lba - 1 'select item clicked
  214.             ELSEIF mx >= 1 AND mx <= maxWidth AND my = 0 THEN 'page up or exit
  215.                 IF my = 0 AND (mx <= maxWidth AND mx >= maxWidth - 2) THEN 'exit sign
  216.                     EXIT DO 'escape plan for mouse click top right corner of display box
  217.                 ELSE 'PgUp bar clicked
  218.                     IF (page - 1) * maxHeight + lba >= lba THEN page = page - 1: GOSUB update
  219.                 END IF
  220.             ELSEIF mx >= 1 AND mx <= maxWidth AND my = maxHeight + 1 THEN 'page down bar clicked
  221.                 IF (page + 1) * maxHeight + lba <= uba THEN page = page + 1: GOSUB update
  222.             END IF
  223.         ELSE '   mouse over highlighting, only if mouse has moved!
  224.             IF mx >= 1 AND mx <= maxWidth AND my >= 1 AND my <= maxHeight THEN
  225.                 IF mx <> lastMX OR my <> lastMY THEN
  226.                     IF my - 1 <> hlite AND (my - 1 + page * maxHeight + lba <= uba) THEN
  227.                         hlite = my - 1
  228.                         lastMX = mx: lastMY = my
  229.                         GOSUB update
  230.                     END IF
  231.                 END IF
  232.             END IF
  233.         END IF
  234.         _LIMIT 200
  235.     LOOP UNTIL choice >= lba AND choice <= uba
  236.     getArrayItemNumber& = choice
  237.     COLOR fg, bg
  238.     'clear key presses
  239.     _KEYCLEAR
  240.     LOCATE curRow, curCol
  241.     'clear mouse clicks
  242.     mb = _MOUSEBUTTON(1)
  243.     IF mb THEN 'clear it
  244.         WHILE mb 'OK!
  245.             IF _MOUSEINPUT THEN mb = _MOUSEBUTTON(1)
  246.             _LIMIT 100
  247.         WEND
  248.     END IF
  249.     EXIT SUB
  250.  
  251.  
  252.     update: '--------------- display of array sections and controls on screen
  253.  
  254.     'fix hlite if it has dropped below last array item
  255.     WHILE hlite + page * maxHeight + lba > uba
  256.         hlite = hlite - 1
  257.     WEND
  258.  
  259.     'main display of array items at page * maxHeight (lines high)
  260.     FOR row = 0 TO maxHeight - 1
  261.         IF hlite = row THEN COLOR _RGB(200, 200, 255), _RGB32(0, 0, 88) ELSE COLOR _RGB32(0, 0, 88), _RGB(200, 200, 255)
  262.         LOCATE locateRow + row, locateColumn: PRINT clrStr$
  263.         index = row + page * maxHeight + lba
  264.         IF index >= lba AND index <= uba THEN
  265.             LOCATE locateRow + row, locateColumn
  266.             PRINT LEFT$(LTRIM$(STR$(index)) + ") " + arr(index), maxWidth)
  267.         END IF
  268.     NEXT
  269.  
  270.     'make page up and down bars to click, print PgUp / PgDn if available
  271.     COLOR _RGB32(200, 200, 255), _RGB32(0, 100, 50)
  272.     LOCATE locateRow - 1, locateColumn: PRINT SPACE$(maxWidth)
  273.     IF page <> 0 THEN LOCATE locateRow - 1, locateColumn: PRINT LEFT$(" Pg Up" + SPACE$(maxWidth), maxWidth)
  274.     LOCATE locateRow + maxHeight, locateColumn: PRINT SPACE$(maxWidth)
  275.     IF page <> INT(uba / maxHeight) THEN
  276.         LOCATE locateRow + maxHeight, locateColumn: PRINT LEFT$(" Pg Dn" + SPACE$(maxWidth), maxWidth)
  277.     END IF
  278.     'make exit sign for mouse click
  279.     COLOR _RGB32(255, 255, 255), _RGB32(200, 100, 0)
  280.     LOCATE locateRow - 1, locateColumn + maxWidth - 3
  281.     PRINT " X "
  282.  
  283.     'if a number selection has been started show it's build = b$
  284.     IF LEN(b$) THEN
  285.         COLOR _RGB(255, 255, 0), _RGB32(0, 0, 0)
  286.         LOCATE locateRow + maxHeight, locateColumn + maxWidth - LEN(b$) - 1
  287.         PRINT b$;
  288.     END IF
  289.     _DISPLAY
  290.     _LIMIT 100
  291.     RETURN
  292.  
  293.  

The majority of this code is spent with selecting an item from an array, in this case an array of directories or of files when you press f. You could use simpler techniques. LoadDirs and LoadFiles are main routines for getting folders and files from current directory if I recall correctly.
« Last Edit: June 10, 2020, 01:35:08 pm by bplus »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #5 on: June 10, 2020, 03:58:00 pm »
Nicely done, BPlus.

Be careful with using DIR statement to file. Ashish and me have already found that it returns differently formatted output to a text file, depending on the system locale used. Therefore, it is better to use the  Steve's library DIRENTRY.H

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Opening files
« Reply #6 on: June 10, 2020, 04:28:30 pm »
Nicely done, BPlus.

Be careful with using DIR statement to file. Ashish and me have already found that it returns differently formatted output to a text file, depending on the system locale used. Therefore, it is better to use the  Steve's library DIRENTRY.H

Hi @Petr,

Thanks.

Quote
... have already found that it returns differently formatted output to a text file, depending on the system locale used.

Are you guys getting file creation dates or dates of any type?

I am not getting those details with my SHELL command.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #7 on: June 10, 2020, 05:14:29 pm »
This was the case for obtaining file names in 8.3 and long format, and the same for directories. It was used by my player, the 8.3 format was used to access paths with unicode characters in the name.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Opening files
« Reply #8 on: June 10, 2020, 06:26:28 pm »
This was the case for obtaining file names in 8.3 and long format, and the same for directories. It was used by my player, the 8.3 format was used to access paths with unicode characters in the name.

8.3? Do you mean the old DOS 8 letters base name and 3 letters extension?

I am using *.* format ;-))

for folders
Code: QB64: [Select]
  1. SHELL _HIDE "DIR /a:d >" + tmpFile

for files
Code: QB64: [Select]
  1. SHELL _HIDE "DIR *.* /a:-d /b /o:-gen > " + tmpFile


Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #9 on: June 11, 2020, 11:29:07 am »
Hi again. Yes, 8.3 format. Why?

In unicode can be file name using DIR returned as:    kulaœouŸk  jeskynØ pln  kr pn¡k….gif
This is not valid file name. So therefore is need old format for access to file.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Opening files
« Reply #10 on: June 11, 2020, 11:41:25 am »
Hi again. Yes, 8.3 format. Why?

In unicode can be file name using DIR returned as:    kulaœouŸk  jeskynØ pln  kr pn¡k….gif
This is not valid file name. So therefore is need old format for access to file.

@Petr  When you say those names aren't valid, even when DIR gives you those names, that they won't work if you say in code to change directory to one of those "invalid" file names, yes?

(assuming your answer would be yes)
Man this makes me glad to be using English, English was not my favorite class is school but live long enough and everything changes, I love reading even some of the classics. Did not like Animal Farm though (just read) but I digress...

If your answer is not yes, what is the problem then? what makes you say they are invalid?

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #11 on: June 11, 2020, 01:47:07 pm »
The problem is this (I guess I could also write it at once ...)

To get names in 8.3 format as well as names in long format I use DIR without formatting parameters. This will give me a full statement. I can display the long name correctly using MAPUNICODE, but I cannot use it for access. That's what the short name is for me.

And the thing I'm talking about all the time is that this statement has otherwise shifted columns in the statement to a file, so it can't be used internationally. Well, not directly. You must first determine the locale in which the computer is running and adjust the reading of data from the file accordingly.

I used this approach in my QB64Player program, which didn't work for Ashish, but for me, and also for people from Germany, Italy, and I think also from the United States. After analyzing why, I found that the Indian version of windows produces a DIR statement shifted by one or two characters, so a program that did not count on it then returned bad names from the file. However, if I reckoned that all file and directory names would be in English only, then I could use listings of only files and only directories and only long names, and I would not know about this problem.

Offline Jon Richfield

  • Newbie
  • Posts: 14
    • View Profile
Re: Opening files
« Reply #12 on: June 12, 2020, 02:42:24 am »
Thanks bplus,

That will take a bit of reading, but looks as though it is in the right direction.

Offline Jon Richfield

  • Newbie
  • Posts: 14
    • View Profile
Re: Opening files
« Reply #13 on: June 12, 2020, 02:45:43 am »
If you have Windows and don't want to worry about Linux or Mac users (ie doing a cross platform app) there are easier ways.

.....

The majority of this code is spent with selecting an item from an array, in this case an array of directories or of files when you press f. You could use simpler techniques. LoadDirs and LoadFiles are main routines for getting folders and files from current directory if I recall correctly.

Forgive my blundering; I still haven't mastered the facilities in this forum. 😳 Everything in time 😉

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: Opening files
« Reply #14 on: June 12, 2020, 04:44:14 am »
@bplus
maybe you could write a file requester using GetOpenFileName (Windows)
here are some examples in C(++) https://docs.microsoft.com/en-us/windows/win32/dlgbox/using-common-dialog-boxes
I translated the open file example on that site to FB, don't how to do it in QB64, would interesting to see
« Last Edit: June 12, 2020, 05:38:43 am by jack »