Unicode: how to properly read and display directory entries?

Dmitry Olshansky dmitry.olsh at gmail.com
Fri Nov 5 10:10:59 PDT 2010


On 05.11.2010 18:25, Tyro[a.c.edwards] wrote:
> On 11/5/2010 10:51 PM, Kagamin wrote:
>> Tyro[a.c.edwards] Wrote:
>>
>>> Hello,
>>>
>>> What is the proper way to read a directory such that file names are not
>>> garbled? Here is the example I borrowed form the std.file 
>>> documentation.
>>> Screen shots of folder is attached. Thanks.
>>>
>>> void main(string[] args)
>>> {
>>> bool callback(DirEntry* de)
>>> {
>>> if (de.isfile)
>>> mciPlay(toUTF8(de.name));
>>> return true;
>>> }
>>>
>>> listdir("snd",&callback);
>>> }
>>>
>>> D:\code>play
>>> snd\american.ogg
>>> snd\bigdog.flac
>>> snd\blackmail.mp3
>>> snd\ding.wav
>>> snd\kam.aif.aiff
>>> snd\豺。縺・ogg
>>>
>>
>> http://d.puremagic.com/issues/show_bug.cgi?id=2742
>
> Much appreciate the info. I'm not however interested in outputting to 
> the console. I'm trying to call mciSendString with the name of each 
> file contained in the directory. The process fails however, when it 
> encounters a Japanese file name. Please see code below. Any idea what 
> I'm doing wrong?
>
> import std.file;
> import std.string : cstring = toStringz;
> import std.c.windows.windows;
>
> pragma(lib, "winmm.lib" );
>
> extern(Windows) {
> uint mciSendStringW(
> LPCWSTR lpszCommand,
> LPWSTR lpszReturnString,
> uint cchReturn,
> HANDLE hwndCallback);
> }
>
> void main(string[] args)
> {
> bool callback(DirEntry* de)
> {
> if (de.isfile)
> mciPlay(de.name);
> return true;
> }
>
> listdir("snd", &callback);
> }
>
> void mciPlay(string audio)
> {
> uint mciSendString(string s)
> {
> return mciSendStringW( cast(LPCWSTR)s, cast(LPWSTR)null, 0, 
> cast(HANDLE)0 );
> }
>
> auto exists = mciSendString(`open "` ~ audio ~ `" type mpegvideo alias 
> myFile`);
> auto played = mciSendString("play myFile wait");
> scope(exit) mciSendString("close myFile");
> }
In short : never rely on the casts to do the right thing.
Bug is here:
return mciSendStringW( cast(LPCWSTR)s, cast(LPWSTR)null, 0, 
cast(HANDLE)0 );
changing that to more accurate:
return mciSendStringW(toUTF16z(s) , cast(LPWSTR)null, 0, cast(HANDLE)0 );
works for me, even with this name:
snd\와카미야 온마쓰리.mp3

If you use W version you need to re-encode your UTF8 string to UTF16.
AFAIK Windows uses slightly outdated version of UTF16, check the web on 
issues.

-- 
Dmitry Olshansky



More information about the Digitalmars-d-learn mailing list