Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
File name verfication
#1
So, was digging through the wiki and here. Hoping for a command, or a library but is there a simple way to verify input as a filename that won't crash a program with an illegal character?

Thanks guys and gals  Big Grin
Reply
#2
INPUT "Give me a file name =>"; file$
IF _FILEEXISTS(file$) THEN 
   PRINT "Found that file!"
ELSE
    PRINT "File doesn't exist!"
END IF

*********************

If you're looking for a way to check to see if a name is valid, for saving purposes rather than loading, that's something you'd have to write yourself as per the ruleset of what's acceptable for you OS.  (Windows is much pickier, for example, than Linux when it comes to valid file name characters.)
Reply
#3
This is my verification function, feel free to use it and/or adapt to your needs:
Code: (Select All)
LINE INPUT "Filename: "; f$

IF ValidFilename%(f$) THEN
    PRINT "Filename is ok."
ELSE
    PRINT "Filename contains invalid chars."
END IF
END

FUNCTION ValidFilename% (file$)
'--- so far, assume invalid ---
ValidFilename% = 0
'--- now check all chars ---
FOR i% = 1 TO LEN(file$)
    SELECT CASE ASC(file$, i%)
        CASE 34, 42, 47, 60, 62, 63, 124
            'invalid chars, list above is for Windows,
            'may need adjustment for other OS
            EXIT FUNCTION
    END SELECT
NEXT i%
'--- check succesfully passed ---
ValidFilename% = -1
END FUNCTION
Reply
#4
"Invalid" on Linux could include whatever ASCII code is less than 32. Could create a "fork bomb" with a control character. It's possible to put a newline as part of a filename which is sick.

The "bash" command processor in particular is very fussy, one could pull his/her hair out trying to program a script toward a list of filenames containing CHR$(32) spaces, apostrophe (needed most of the time to precisely quote stuff), ampersand (one of them launches a process and keeps it going, two of them is like colon in BASIC), colon (path separator), dollar sign (preface environment variables and replaceable parameters), grave accent (needed to fire a second instance of "bash" to then use the "stdout" out of it) and stuff like that.

A programmer might like to employ "bash" sometimes to see if a filename is "legal" on Linux.
Reply
#5
(03-15-2023, 05:37 AM)SMcNeill Wrote: INPUT "Give me a file name =>"; file$
IF _FILEEXISTS(file$) THEN 
   PRINT "Found that file!"
ELSE
    PRINT "File doesn't exist!"
END IF

*********************

If you're looking for a way to check to see if a name is valid, for saving purposes rather than loading, that's something you'd have to write yourself as per the ruleset of what's acceptable for you OS.  (Windows is much pickier, for example, than Linux when it comes to valid file name characters.)

I take you up on your challenge and came up with this. Anyone is free to use said code! I tried to make it customizable for others as wll.

Code: (Select All)
OPTION _EXPLICIT

CONST TRUE = -1, FALSE = NOT TRUE

DIM Try$

DO
    CLS
    INPUT "Enter a filename to check (enter quit or exit to exit): "; Try$
    IF UCASE$(Try$) = "QUIT" OR UCASE$(Try$) = "EXIT" THEN SYSTEM
    IF ISVALID(Try$) THEN PRINT CHR$(34) + Try$ + CHR$(34) + " is a vaild filename." ELSE PRINT CHR$(34) + Try$ + CHR$(34) + " is invalid as a filename."
    PRINT "Press any key to countinue..."
    SLEEP
    _DELAY .1
    _KEYCLEAR
LOOP


'This fuction returns true if vaild and false if not (as a bit)
FUNCTION ISVALID` (FileName AS STRING)

    DIM AS STRING Legal(1 TO 50), FileNameCanidate
    DIM AS STRING FileNameParts(1 TO 96)
    DIM AS INTEGER LoopCounter, LoopCounter1, NumberOfVaildCharacters

    FileNameCanidate = UCASE$(FileName)

    'Set the number of characters to check (easily add or remove desired characters)
    NumberOfVaildCharacters = 39

    'Define vaild characters (letters, numbers, spaces, and selected symbols only).
    Legal(1) = "A": Legal(2) = "B": Legal(3) = "C": Legal(4) = "D"
    Legal(5) = "E": Legal(6) = "F": Legal(7) = "G": Legal(8) = "H"
    Legal(9) = "I": Legal(10) = "J": Legal(11) = "K": Legal(12) = "L"
    Legal(13) = "M": Legal(14) = "N": Legal(15) = "O": Legal(16) = "P"
    Legal(17) = "Q": Legal(18) = "R": Legal(19) = "S": Legal(20) = "T"
    Legal(21) = "U": Legal(22) = "V": Legal(23) = "W": Legal(24) = "X"
    Legal(25) = "Y": Legal(26) = "Z": Legal(27) = " ": Legal(28) = "1"
    Legal(29) = "2": Legal(30) = "3": Legal(31) = "4": Legal(32) = "5"
    Legal(33) = "6": Legal(34) = "7": Legal(35) = "8": Legal(36) = "9"
    Legal(37) = "0": Legal(38) = "-": Legal(39) = "_"

        'All file names are limited to 100 (96 + 4 for .***) characters (paths are limited to 255)
    IF LEN(FileNameCanidate) >= 96 THEN ISVALID` = FALSE: EXIT FUNCTION

    'Filenames can not start or end with a space
    IF MID$(FileNameCanidate, 1, 1) = " " THEN ISVALID` = FALSE: EXIT FUNCTION
    IF MID$(FileNameCanidate, LEN(FileNameCanidate), 1) = " " THEN ISVALID` = FALSE: EXIT FUNCTION

    'Each part of the canidate name is pulled about to check.
    FOR LoopCounter = 1 TO LEN(FileNameCanidate)
        FileNameParts(LoopCounter) = MID$(FileNameCanidate, LoopCounter, 1)
    NEXT LoopCounter
   
    'Check the canidate vs the legal characters.
    'If a legal character is not found in a position, false is returned without further checking.
    FOR LoopCounter = 1 TO LEN(FileName)
        ISVALID` = FALSE 'Reset the tripwire
        FOR LoopCounter1 = 1 TO NumberOfVaildCharacters
            IF FileNameParts(LoopCounter) = Legal(LoopCounter1) THEN ISVALID` = TRUE: EXIT FOR
        NEXT LoopCounter1
        IF NOT ISVALID` THEN EXIT FUNCTION 'If not tripped to true, exit with further checking.
    NEXT LoopCounter

    'If all tests are passed then return true
    ISVALID` = TRUE
END FUNCTION

Instead of what's not vaild, I tried to capture what is vaild and also ensure our file meets whatever restrictions that is set. I also included a limit and spaces to avoid stranger file names.

(03-15-2023, 07:39 AM)RhoSigma Wrote: This is my verification function, feel free to use it and/or adapt to your needs:
Code: (Select All)
LINE INPUT "Filename: "; f$

IF ValidFilename%(f$) THEN
    PRINT "Filename is ok."
ELSE
    PRINT "Filename contains invalid chars."
END IF
END

FUNCTION ValidFilename% (file$)
'--- so far, assume invalid ---
ValidFilename% = 0
'--- now check all chars ---
FOR i% = 1 TO LEN(file$)
    SELECT CASE ASC(file$, i%)
        CASE 34, 42, 47, 60, 62, 63, 124
            'invalid chars, list above is for Windows,
            'may need adjustment for other OS
            EXIT FUNCTION
    END SELECT
NEXT i%
'--- check succesfully passed ---
ValidFilename% = -1
END FUNCTION

I like how short and simple this is! If I saw it before I made one, I might have just used this instead  Cool
Reply
#6
You can also do wide strings
Tread on those who tread on you

Reply
#7
Code: (Select All)
ISVALID` = TRUE
    FOR LoopCounter = 1 TO LEN(FileName)
        FOR LoopCounter1 = 1 TO NumberOfVaildCharacters
            IF FileNameParts(LoopCounter) <> Legal(LoopCounter1) THEN ISVALID` = FALSE: EXIT FUNCTION
        NEXT LoopCounter1
    NEXT LoopCounter

Set the function return value and leave straight away, no need to check it and no need to "set the trap" at each character in the "FileName" to check. This was coded also for more consistency with the function body code that appears before this demonstration.

Also I suggest using a "FOR... NEXT" loop to initialize most of the Legal() array. Because you will have to include uppercase and lowercase letters to check on Linux and MacOS. Filenames on Unix and Unix-like operating systems are case sensitive.
Reply
#8
Quote:@RhoSigma - This is my verification function, feel free to use it and/or adapt to your needs

QB64 cannot read German umlauts or special characters in file names or folders. The program doesn't recognize them either. That is, for example the Übungen (Exercises) folder will not found. -- 132 = ä

Code: (Select All)
'Ueberpruefung eines anzugebenen Dateinamens, RhoSigma - 16. Maerz 2023

Option _Explicit

Declare Function ValidFilename(file As String) As Integer

Dim As String file

Locate 2, 3
Line Input "Filename: "; file

If ValidFilename(file) Then
  Locate CsrLin + 1, 3
  Print "Filename is ok."
Else
  Locate CsrLin + 1, 3
  Beep: Print "Filename contains invalid chars."
End If

End 'Main program

Function ValidFilename (file As String)

  Dim As Integer i

  '--- so far, assume invalid ---
  ValidFilename = 0

  '--- now check all chars ---
  For i = 1 To Len(file)
    Select Case Asc(file, i)
      Case 34, 38, 42, 44, 47, 60, 62, 63, 64, 124, 132
        'invalid chars, list above is for Windows,
        'may need adjustment for other OS
        Exit Function
    End Select
  Next i

  '--- check succesfully passed ---
  ValidFilename = -1
End Function

This condition does not work, the program is aborted even if the name is correct. I put that after the FOR loop.
Code: (Select All)
If Asc(file) = 132 Or 142 Or 148 Or 151 Or 153 Or 154 Then
  Locate CsrLin + 2, 3
  Beep: Print "QB64 cannot read German umlauts or special characters in file names."
  Sleep 3
  System
End If

[Image: DE-Umlaute-2023-03-16.jpg]
Reply
#9
That should be:
Code: (Select All)
Select Case Asc(file)
  Case 132, 142, 148, 151, 153, 154
    Locate CsrLin + 2, 3
    Beep: Print "QB64 cannot read German umlauts or special characters in file names."
    Sleep 3
    System
End Select

Cannot transfer a "SELECT CASE" clause directly into an "IF" statement like that.

This was a modification to the block you presented. I noticed above the line was "Asc(file, i)" so what you're actually doing is checking only the first character of string variable "file".

It's not recommended to use strange characters in your filenames especially if it involves a program that will be shared with somebody else.
Reply
#10
If I can find my code then I'll send it. I was dealing with files with Korean, Chinese, and Japanese characters in the filename with no issues at all by just replicating FileExists but with wide string usage as well as using my AnsiToUnicode wrappers for converting between CP437 and UTF8 and vice-versa. The only issue you might have would be trying to display the name of the chosen file. I think you would also need to use the wide version of GetOpenFileName like I did. I was even able to replicate the drag and drop functions in QB64 as wide versions. I have no problem dropping any files with foreign characters in them.
Tread on those who tread on you

Reply




Users browsing this thread: 5 Guest(s)