digitalmars.D.learn - Mistake of opening of a file having a name in cp1251.
- MGW (65/65) Apr 02 2015 Greetings to all!
- Danny (16/16) Apr 03 2015 According to the documentation
- MGW (3/3) Apr 03 2015 The decision, which I have applied using function
- Steven Schveighoffer (5/14) Apr 03 2015 Please see if this will fix your problem, currently open PR:
Greetings to all! I work on Windows with cp1251 and I have a mistake in the program: import std.stdio; int main (string [] args) { string nameFile = `«Ёлки с объектами №876».txt`; File f = File (nameFile, "w"); f.writeln ("Greetings!"); return 0; } This mistake of a kind: std.exception. ErrnoException std\stdio.d (372): Cannot open file ` ┬л╨Б ╨╗╨║╨╕ ╨Ю ╨▒ ╤К ╨╡╨║╤ 876 ┬╗. txt ' in mode ` w ' (Invalid argument) For correction of this mistake I had to change a file std\stdio.d, having added in it function fromUtf8toAnsiW (). The piece of an source code of a file std\stdio.d with changes is presented more low. private FILE* fopen(in char[] name, in char[] mode = "r") trusted // nothrow nogc - mgw отключено из-за fromUtf8toAnsiW { import std.internal.cstring : tempCString; version(Windows) { // 02.04.2015 8:31:19 repair for dmd 2.067.0 wchar* fromUtf8toAnsiW(in char[] s, uint codePage = 0) trusted { import std.c.windows.windows: WideCharToMultiByte, GetLastError; import std.windows.syserror: sysErrorString; import std.conv: to; char[] result, rez; int readLen; auto ws = std.utf.toUTF16z(s); result.length = WideCharToMultiByte(codePage, 0, ws, -1, null, 0, null, null); if (result.length) { readLen = WideCharToMultiByte(codePage, 0, ws, -1, result.ptr, to!int(result.length), null, null); for(int i; i != result.length; i++) { rez ~= result[i]; rez ~= 0; } rez ~= 0; rez ~= 0; } if (!readLen || readLen != result.length) { throw new Exception("Couldn't convert string: " ~ sysErrorString(GetLastError())); } return cast(wchar*)rez.ptr; } import std.internal.cstring : tempCStringW; // return _wfopen(name.tempCStringW(), mode.tempCStringW()); return _wfopen(fromUtf8toAnsiW(name), mode.tempCStringW()); } else version(Posix) { import core.sys.posix.stdio : fopen; return fopen(name.tempCString(), mode.tempCString()); } else { return .fopen(name.tempCString(), mode.tempCString()); } } With the given correction all works correctly. Question. Whether correctly such change from the point of view of programming canons on D ?
Apr 02 2015
According to the documentation <https://msdn.microsoft.com/de-de/library/yeby3zcb.aspx>, _wfopen already takes a wide-character string, not an ANSI string. So return _wfopen(name.tempCStringW(), mode.tempCStringW()); would be the correct way. All these weird ansi versions are Windows 98 era legacy, they aren't commonly used anymore. Please also try whether your C runtime implements _wfopen correctly or otherwise your file name is somehow broken (maybe it's on a FAT filesystem etc). For that, please try opening it in a C program using _wfopen(_T("filenamehere"), "r"); For comparison, try to create a file with the same name on an NTFS filesystem and try opening it in a C program using _wfopen(_T("filenamehere"), "r"); Does that work? Also, what version and flavour (DMD, GDC, LDC) of D do you use?
Apr 03 2015
The decision, which I have applied using function fromUtf8toAnsiW() already works correctly. I use dmd 2.067.0
Apr 03 2015
On 4/3/15 2:26 AM, MGW wrote:Greetings to all! I work on Windows with cp1251 and I have a mistake in the program: import std.stdio; int main (string [] args) { string nameFile = `«Ёлки с объектами №876».txt`; File f = File (nameFile, "w"); f.writeln ("Greetings!"); return 0; }Please see if this will fix your problem, currently open PR: https://github.com/D-Programming-Language/phobos/pull/3138 Seems like the same issue -Steve
Apr 03 2015