FileExists() and FileCopy() supporting Unicode file names
-
- Posts: 117
- Joined: Jun 21, 2018 11:14
FileExists() and FileCopy() supporting Unicode file names
These functions (included in file.bi) seems not to work with file names containing non-ASCII characters.
Where functions can be found which would support file names like "Сергeй.txt"?
Where functions can be found which would support file names like "Сергeй.txt"?
Re: FileExists() and FileCopy() supporting Unicode file names
The c runtime has many unicode functions.
I made up an exists here.
(I must use Poseidon ide for this)
I made up an exists here.
(I must use Poseidon ide for this)
Code: Select all
#include "crt.bi"
declare function wsystem cdecl alias "_wsystem" (byval as wstring ptr) as long 'not in crt.bi
function exists(filename as wstring) as boolean
dim as wstring * 50 r="rt+,ccs=UNICODE"'"r"
dim as file ptr fp = _wfopen(@filename,@r)
fclose(fp)
return cint(fp)
end function
dim as wstring * 15 w= wstr("Сергeй.txt")
wsystem("echo hello > "+w)
wsystem("echo hello there > asciname.txt")
wsystem("type " + w)
wsystem("type asciname.txt")
print
wsystem("dir " + "/b")
print exists(w)
print exists("asciname.txt")
print exists("dummy.txt2")
sleep
Re: FileExists() and FileCopy() supporting Unicode file names
Yes the *Microsoft* C runtime has many unicode functions out of necessity[1]. But they're definitely not part of the C standard runtime. Any function that begins with an underscore is a non-standard addition. So it works on Windows only, but it's definitely not portable to any other operating system.
The ANSI standard C runtime has zero support for unicode or unicode decoding and encoding. But on operating systems that use UTF-8 (pretty much any OS other than Windows), it doesn't really need to support unicode. That can be left to a higher level abstraction and other libraries.
[1] MS chose to use UCS-2, then later UTF-16, which meant they had to duplicate every API in their system to support 2-byte unicode characters, as well as traditional bytes.
The ANSI standard C runtime has zero support for unicode or unicode decoding and encoding. But on operating systems that use UTF-8 (pretty much any OS other than Windows), it doesn't really need to support unicode. That can be left to a higher level abstraction and other libraries.
[1] MS chose to use UCS-2, then later UTF-16, which meant they had to duplicate every API in their system to support 2-byte unicode characters, as well as traditional bytes.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: FileExists() and FileCopy() supporting Unicode file names
> Where functions can be found which would support file names like "Сергeй.txt"?
Here: https://github.com/JoseRoca/WinFBX
From AfxWin.inc:
Here: https://github.com/JoseRoca/WinFBX
From AfxWin.inc:
Code: Select all
' ========================================================================================
' Searches a directory for a file or subdirectory with a name that matches a specific name
' (or partial name if wildcards are used).
' Parameter:
' - pwszFileSpec: The directory or path, and the file name, which can include wildcard
' characters, for example, an asterisk (*) or a question mark (?).
' This parameter should not be NULL, an invalid string (for example, an empty string or a
' string that is missing the terminating null character), or end in a trailing backslash (\).
' If the string ends with a wildcard, period (.), or directory name, the user must have
' access permissions to the root and all subdirectories on the path. To extend the limit
' of MAX_PATH wide characters to 32,767 wide characters, prepend "\\?\" to the path.
' Return value:
' Returns TRUE if the specified file exists or FALSE otherwise.
' Remarks:
' Prepending the string "\\?\" does not allow access to the root directory.
' On network shares, you can use a pwszFileSpec in the form of the following:
' "\\server\service\*". However, you cannot use a pwszFileSpec that points to the share
' itself; for example, "\\server\service" is not valid.
' To examine a directory that is not a root directory, use the path to that directory,
' without a trailing backslash. For example, an argument of "C:\Windows" returns information
' about the directory "C:\Windows", not about a directory or file in "C:\Windows".
' To examine the files and directories in "C:\Windows", use an pwszFileSpec of "C:\Windows\*".
' Be aware that some other thread or process could create or delete a file with this name
' between the time you query for the result and the time you act on the information.
' If this is a potential concern for your application, one possible solution is to use
' the CreateFile function with CREATE_NEW (which fails if the file exists) or OPEN_EXISTING
' (which fails if the file does not exist).
' ========================================================================================
PRIVATE FUNCTION AfxFileExists (BYVAL pwszFileSpec AS WSTRING PTR) AS BOOLEAN
DIM fd AS WIN32_FIND_DATAW
IF pwszFileSpec = NULL THEN EXIT FUNCTION
DIM hFind AS HANDLE = FindFirstFileW(pwszFileSpec, @fd)
IF hFind = INVALID_HANDLE_VALUE THEN EXIT FUNCTION
FindClose hFind
' // Make sure that it is not a directory or a temporary file
IF (fd.dwFileAttributes AND FILE_ATTRIBUTE_DIRECTORY) <> FILE_ATTRIBUTE_DIRECTORY AND _
(fd.dwFileAttributes AND FILE_ATTRIBUTE_TEMPORARY) <> FILE_ATTRIBUTE_TEMPORARY THEN
FUNCTION = TRUE
END IF
END FUNCTION
' ========================================================================================
Code: Select all
' ========================================================================================
' Copies an existing file to a new file.
' - lpExistingFileName : The name of an existing file.
' To extend the limit of MAX_PATH characters to 32,767 wide characters prepend "\?" to the path.
' If lpExistingFileName does not exist, CopyFile fails, and GetLastError returns ERROR_FILE_NOT_FOUND.
' - lpNewFileName : The name of the new file.
' To extend the limit of MAX_PATH characters to 32,767 wide characters prepend "\?" to the path.
' - bFailIfExists
' If this parameter is TRUE and the new file specified by lpNewFileName already exists, the
' function fails. If this parameter is FALSE and the new file already exists, the function
' overwrites the existing file and succeeds.
' Return value:
' If the function succeeds, the return value is TRUE.
' If the function fails, the return value is FALSE. To get extended error information, call GetLastError.
' ========================================================================================
PRIVATE FUNCTION AfxCopyFile (BYVAL lpExistingFileName AS LPCWSTR, BYVAL lpNewFileName AS LPCWSTR, BYVAL bFailIfExists AS BOOLEAN = FALSE) AS BOOLEAN
RETURN CopyFileW(lpExistingFileName, lpNewFileName, bFailIfExists)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Unicode replacement for Free Basic's FileCopy.
' Returns 0 on success, or 1 if an error occurred.
' ========================================================================================
PRIVATE FUNCTION AfxFilecopy (BYVAL lpExistingFileName AS LPCWSTR, BYVAL lpNewFileName AS LPCWSTR) AS LONG
DIM nRet AS LONG = IIF(CopyFileW(lpExistingFileName, lpNewFileName, FALSE) = 0, 1, 0)
RETURN nRet
END FUNCTION
' ========================================================================================
Re: FileExists() and FileCopy() supporting Unicode file names
caseih
It seems much easier in Linux with shell
also this works straight off
Thanks Josep Roca, I shall test later.
It seems much easier in Linux with shell
Code: Select all
shell "if [ -f Сергeй.txt ]; then echo exists; fi"
shell "if [ ! -f Сергeй.txt ]; then echo does not exist; fi"
Code: Select all
dim as wstring * 15 w= wstr("Сергeй.txt")
print w
shell("echo hello > "+ w)
-
- Posts: 117
- Joined: Jun 21, 2018 11:14
Re: FileExists() and FileCopy() supporting Unicode file names
OK, I will test later too.
An additional question:
With
Unicode-supporting functions LoadFile() and SaveFile() (and ShellExecuteW()) are provided. As I have now discovered, also DeleteFile() is included. Are there othere file-related functions in this libraries? (Copy, Rename?)
An additional question:
With
Code: Select all
#Define unicode
#Include once "windows.bi"
#Include once "win/shellapi.bi"
Re: FileExists() and FileCopy() supporting Unicode file names
Here's a little helper for snooping around windows.
Call this file zzwindows.bas, put in your working folder.
compile with the -pp switch.
(fbc -pp zzwindows.bas)
This will give you zzwindows.pp.bas, which is the one you want to easily browse because it rests at the bottom of your working folder.
You have 28101 lines of windows constants/declarations e.t.c.
Code: Select all
#include "windows.bi"
#Include "win/shellapi.bi"
compile with the -pp switch.
(fbc -pp zzwindows.bas)
This will give you zzwindows.pp.bas, which is the one you want to easily browse because it rests at the bottom of your working folder.
You have 28101 lines of windows constants/declarations e.t.c.
Re: FileExists() and FileCopy() supporting Unicode file names
Here a file save and load (c) and the copy from windows.
Code: Select all
#include "crt.bi"
extern "windows"
declare function CopyFileW(byval lpExistingFileName as wstring ptr, byval lpNewFileName as wstring ptr, byval bFailIfExists as BOOLean) as BOOLean
end extern
const size=5000
sub save(filename as wstring,content as wstring)
dim as wstring * 20 w="wt+,ccs=utf-8"
var fp = _wfopen(@filename,@w)
if fp then fputws(@content,fp) else print "could not save "+filename
fclose(fp)
end sub
sub load(filename as wstring,content as wstring)
dim as wstring * 20 r="rt+,ccs=utf-8"
dim as wstring * size t
dim as file ptr fp = _wfopen(@filename,@r)
if fp=0 then print "Unable to load ";filename:sleep:exit sub
while 1
if (fgetws (@t,size,fp)= 0)then exit while
content+=t
wend
fclose(fp)
end sub
dim as wstring * 50 w= wstr("СергeйСергeй.txt")
dim as wstring * 100 message=wstr("hello from СергeйСергeй.txt, but I am in another file now")
save(w,message)
dim as boolean b =false 'creates a new file if false
print "copied "; copyfileW(w,"a newfile.txt",b)
print "Folder contents:"
print
shell "dir /b"
print
dim as wstring * 1000 content
load("a newfile.txt",content)
print content
sleep