Open a file with a unicode-encoded name

New to FreeBASIC? Post your questions here.
newbieforever
Posts: 117
Joined: Jun 21, 2018 11:14

Open a file with a unicode-encoded name

Post by newbieforever »

Soon I'm running out of questions...

I want to write (by Print) a binary string 'strin' to a binary file filenam, but filenam is a name containing unicode characters (i.e. 'filenam' is a unicode-encoded string).

Simply

Code: Select all

Open filenam For Binary As #1
Print #1, strin
doesn't work: Print writes correctly, but the name of the created file is not correct.

How this could be done correctly?
Last edited by newbieforever on Jul 01, 2018 22:17, edited 1 time in total.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Open a file with a unicode-encoded name

Post by MrSwiss »

@newbieforever,

this is a Forum, NOT a 'online-tutorial', read the Manual ...
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Open a file with a unicode-encoded name

Post by Josep Roca »

OPEN does not support unicode file names. You can use functions of the C runtime or, if you are working with Windows, you can also use API functions such CreateFileW, WriteFile and ReadFile.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Open a file with a unicode-encoded name

Post by dodicat »

Code: Select all

 

 #Include "file.bi"
Sub savefile(filename As wstring,p As String)
    Dim As Integer n
    n=Freefile
    If Open (filename For Binary Access Write As #n)=0 Then
        Put #n,,p
        Close
    Else
        Print "Unable to save " + filename
    End If
End Sub

Function loadfile(file as wstring) as String
	If FileExists(file)=0 Then Print file;" not found":Sleep:end
   var  f=freefile
    Open file For Binary Access Read As #f
    Dim As String text
    If Lof(f) > 0 Then
      text = String(Lof(f), 0)
      Get #f, , text
    End If
    Close #f
    return text
end Function

dim as wstring * 8 file= wchr(313,303,301)+".txt" 'the filename
print "The filename is  "; file

dim as string binaryfile="1234"+chr(0)+"5"+chr(206)+"6789"

savefile(file,binaryfile)       'saved to disk

dim as string s =loadfile(file) 'loaded from disk
print s

kill file 'erase the file

sleep
 
newbieforever
Posts: 117
Joined: Jun 21, 2018 11:14

Re: Open a file with a unicode-encoded name

Post by newbieforever »

@MrSwiss: "This is a Forum, NOT a 'online-tutorial', read the Manual ..."
You are right, of course, but this seems to be a very specific question: after 3 or 4 hours of searching my progress was zero...

@dodicat:
I think I understand the basic method presented in your code, but I am unable to translate it to be used in my specific setting.
I alredy have the filename as string 'filenam' which was extracted from a unicode file: 'stg' is the string (Dim As String stg) read from the unicode-encoded file, and 'filenam' is extracted from this string by filenam = mid(stg, pos, lngth). (My 'strin', which is to be written to 'filenam', was generated in the same way.)
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Open a file with a unicode-encoded name

Post by jj2007 »

dodicat wrote:dim as wstring * 8 file= wchr(313,303,301)+".txt" 'the filename
print "The filename is "; file
Did you test it with a real Unicode name?

Code: Select all

dim as wstring * 10 file= wchr(&h0414, &h043e, &h0431, &h0440, &h043E)+".txt" 'the filename
...
The filename is  Добро.txt
Unable to save Добро.txt
Добро.txt not found
The filename is Unicode, but FB uses CreateFileA under the hood.

This works:

Code: Select all

dim as wstring * 10 file= wchr(&h0041, &h0042, &h0043, &h0044, &h0045, &h002E, &h0074, &h0078, &h0074) 'ABCDE.txt
Honestly, this could be handled better. This works and writes Hello World to a file: FileWrite "Добро.txt", "Привет мир" ... but it's not FreeBasic.
Last edited by jj2007 on Jul 01, 2018 23:48, edited 1 time in total.
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Open a file with a unicode-encoded name

Post by Josep Roca »

> Did you test it with a real Unicode name?

Guess not. As OPEN only woks with ansi strings, if you use a wstring for the filename, it will be automatically converted to ansi.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Open a file with a unicode-encoded name

Post by jj2007 »

Yes indeed. My edit and your post crossed ("FB uses CreateFileA under the hood").
newbieforever
Posts: 117
Joined: Jun 21, 2018 11:14

Re: Open a file with a unicode-encoded name

Post by newbieforever »

??? I am confused now... There is no working solution here until now, right?
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Open a file with a unicode-encoded name

Post by jj2007 »

newbieforever wrote:??? I am confused now... There is no working solution here until now, right?
Correct. If you are on Windows, you can go the official WinAPI road:

Code: Select all

Sub savefile(filename As wstring,p As String)
    Dim As Integer n
    n=CreateFileW(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)
    If n then 'Open (filename For Binary Access Write As #n)=0 Then
        Put #n,,p   ' will NOT work
        Close
    Else
        Print "Unable to save " + filename
    End If
End Sub
Problem: Put and Close won't work because they use the internal FB file handles. So you would have to implement also WriteFile and CloseHandle.
newbieforever
Posts: 117
Joined: Jun 21, 2018 11:14

Re: Open a file with a unicode-encoded name

Post by newbieforever »

jj2007: "If you are on Windows, you can go the official WinAPI road."

I understand.

Back to the start... A first success for me:

Code: Select all

'#Define UNICODE    ' With this CreateFile() could be used instead of CreateFileW()!
#Include "windows.bi"

Dim As WString * 250 fil = "Добро.txt"

' This works:
CreateFileW(fil, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)
This works fine, a file with the correct name is created.

This is followed my a first "side problem": Above the filename is set inside the code. In my case the filename 'fil' is extracted from a unicode file content: 'stg' is the string (Dim As String stg) read from the unicode-encoded file, and 'fil' is extracted from this string by fil = mid(stg, pos, lngth). The received string 'fil' is the correct filename I need. But if I use the CreateFileW line in my code, the created file's name consists only of the first character of 'fil'.
Last edited by newbieforever on Jul 02, 2018 10:04, edited 1 time in total.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Open a file with a unicode-encoded name

Post by MrSwiss »

stg -- is the problem, because:

Code: Select all

Dim As String ... ' must be WString, to work!
You must stick to the same data-type, either ANSI or UNICODE (throughout the prog.)

ANSI = String; UNICODE = WString
newbieforever
Posts: 117
Joined: Jun 21, 2018 11:14

Re: Open a file with a unicode-encoded name

Post by newbieforever »

MrSwiss wrote:You must stick to the same data-type, either ANSI or UNICODE (throughout the prog.)
Oh God, in what a mess I got into!?

I read stg (as String, not Wstring) from a file, I do a lot of string manipulations with this stg, all this is working perfectly! I need all this for the main job! Only one of this string manipulations is to extract the required file name from stg: the file (or stg) contains an individual section which is the unicode-encoded filename, and I extract this filename by fil = mid(stg, pos, lngth) because I am able to find out pos and lngth. No chance to convert fil to a form which can be used e.g. in CreateFileW()?
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Open a file with a unicode-encoded name

Post by MrSwiss »

Well, you've just lost me because, as far as I understand:
  • the file you are reading from, is: UNICODE (encoded=UTF16)
  • therefore, a WString is needed to properly read it's content
  • MID() statement, supports both: String/WString
So, where is the problem, with the extracted File-Name?

It's good practice, to post the failing code, instead of a lenghty description.
Makes *spotting* the mistakes, far easier ... (use the code-tags, provided)
Last edited by MrSwiss on Jul 02, 2018 11:25, edited 1 time in total.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Open a file with a unicode-encoded name

Post by jj2007 »

newbieforever wrote:I extract this filename by fil = mid(stg, pos, lngth) because I am able to find out pos and lngth. No chance to convert fil to a form which can be used e.g. in CreateFileW()?
It would be helpful if you posted full code for that. For example, does your attempt to read with the mid() function fail also for #Define Unicode?

In the meantime, here is the code to write to a Unicode file:

Code: Select all

#Define winapimode 1	' for playing with the two options
#Include "file.bi"
#include "Windows.bi"

Sub savefile(filename As wstring, p As String)
  Print "Opening [";filename;"]"
  if winapimode then
	Dim As any ptr n, pstr
	Dim As Integer byteswritten
	n=CreateFileW(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)
	If n<>-1 then
		WriteFile(n, Peek(any ptr, VarPtr(p)), Len(p), @byteswritten, 0)
		Print byteswritten; " bytes written"
		CloseHandle(n)
	Else
		Print "Unable to open " + filename
	End If
  else
	Dim As Integer n
	n=freefile
	If Open(filename For Binary Access Write As #n)=0 then
		Put #n,,p
		Close
	Else
		Print "Unable to open " + filename
	End If
  endif
End Sub
winapimode 0 (i.e. use the standard FB syntax) works fine if the filename is not "true" Unicode, e.g. "MyFile.txt"
Post Reply