HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2016
0210
科学太郎ディレクトリのファイル一覧で取得の不具合発見!!0解決


科学太郎

リンク

2016/2/10(Wed) 22:40:35|NO.74545

HSP には dirlist 命令で簡単にファイル一覧を文字列で取得できますね。
しかし、ファイル名がシフトJIS文字で 260 バイトを超えると途中で中断されます。
これにより、フォルダ内に 1000 以上も画像があるのに 102 件しか取得できなくなります。
いろいろと調べて原因が判明しましたので報告します。

//------------------------------------------------------------------------------ // WIN32_FIND_DATAのサンプル by 科学太郎(中断される) //============================================================================== // @URL(https://msdn.microsoft.com/en-us/library/aa365740.aspx)→「WIN32_FIND_DATA」 // @URL(https://msdn.microsoft.com/ja-jp/library/cc429233.aspx)→「FindFirstFile」 // @URL(https://msdn.microsoft.com/ja-jp/library/cc429242.aspx)→「FindNextFile」 // @URL(https://msdn.microsoft.com/ja-jp/library/cc429224.aspx)→「FindClose」 //------------------------------------------------------------------------------ // @URL(http://blog.goo.ne.jp/masaki_goo_2006/e/bfaf314985c0e4a5b4cb94a29df75fab)→「ファイル名の検索」 // @URL(http://blog.goo.ne.jp/masaki_goo_2006/e/6c6aecf0b48c4ecdbc91e48ce415c4dd)→「ファイル名の再帰検索」 // @URL(http://www.tvg.ne.jp/menyukko/cauldron/hmfileinfo.html)→「HSP用 ファイル情報取得モジュール - 略して仮。」 // @URL(http://chokuto.ifdef.jp/urawaza/struct/WIN32_FIND_DATA.html)→「WIN32_FIND_DATA」 //------------------------------------------------------------------------------ #include "Kernel32.as" //-------------------------------------- // 記号定数(API定数) //-------------------------------------- #const global MAX_PATH 260 #const global INVALID_HANDLE_VALUE $FFFFFFFF //-------------------------------------- // 列挙定数(WIN32_FIND_DATA) //-------------------------------------- #enum global fd_dwFileAttributes=0 #enum global fd_ftCreationTimeL #enum global fd_ftCreationTimeH #enum global fd_ftLastAccessTimeL #enum global fd_ftLastAccessTimeH #enum global fd_ftLastWriteTimeL #enum global fd_ftLastWriteTimeH #enum global fd_nFileSizeHigh #enum global fd_nFileSizeLow #enum global fd_dwReserved0 #enum global fd_dwReserved1 #enum global fd_cFileName #enum global fd_cAlternateFileName=(fd_cFileName+260/4) #enum global DIM_WIN32_FIND_DATA=(fd_cAlternateFileName+16/4) #enum global SIZE_WIN32_FIND_DATA=(DIM_WIN32_FIND_DATA*4) //-------------------------------------- // メイン部 //-------------------------------------- *Init dim hFind dim fdFile,DIM_WIN32_FIND_DATA dupptr fdFileName,varptr(fdFile.fd_cFileName),MAX_PATH,2 ;文字列型 *Main screen 0,640,480,SCREEN_NORMAL title "WIN32_FIND_DATAのサンプル(中断される)" ;エディット・ボックスの配置 sdim sBuff mesbox sBuff,ginfo_winX,ginfo_winY,5 ;検索 FindFirstFile "F:\\壁紙\\*.*",varptr(fdFile):hFind=stat if(hFind!=INVALID_HANDLE_VALUE){ repeat sBuff+=fdFileName+"\n" FindNextFile hFind,varptr(fdFile) if(stat==0):break loop FindClose hFind } objprm 0,sBuff stop //------------------------------------------------------------------------------ // End of sample127a.hsp //------------------------------------------------------------------------------

FindNextFile 命令の戻り値で繰り返しを抜けると途中で中断される。

//------------------------------------------------------------------------------ // WIN32_FIND_DATAのサンプル by 科学太郎(中断されない) //============================================================================== // @URL(https://msdn.microsoft.com/en-us/library/aa365740.aspx)→「WIN32_FIND_DATA」 // @URL(https://msdn.microsoft.com/ja-jp/library/cc429233.aspx)→「FindFirstFile」 // @URL(https://msdn.microsoft.com/ja-jp/library/cc429242.aspx)→「FindNextFile」 // @URL(https://msdn.microsoft.com/ja-jp/library/cc429224.aspx)→「FindClose」 //------------------------------------------------------------------------------ // @URL(http://blog.goo.ne.jp/masaki_goo_2006/e/bfaf314985c0e4a5b4cb94a29df75fab)→「ファイル名の検索」 // @URL(http://blog.goo.ne.jp/masaki_goo_2006/e/6c6aecf0b48c4ecdbc91e48ce415c4dd)→「ファイル名の再帰検索」 // @URL(http://www.tvg.ne.jp/menyukko/cauldron/hmfileinfo.html)→「HSP用 ファイル情報取得モジュール - 略して仮。」 // @URL(http://chokuto.ifdef.jp/urawaza/struct/WIN32_FIND_DATA.html)→「WIN32_FIND_DATA」 //------------------------------------------------------------------------------ #include "Kernel32.as" //-------------------------------------- // 記号定数(API定数) //-------------------------------------- #const global MAX_PATH 260 #const global INVALID_HANDLE_VALUE $FFFFFFFF # #const global ERROR_NO_MORE_FILES $00000012 #const global ERROR_MORE_DATA $000000EA //-------------------------------------- // 列挙定数(WIN32_FIND_DATA) //-------------------------------------- #enum global fd_dwFileAttributes=0 #enum global fd_ftCreationTimeL #enum global fd_ftCreationTimeH #enum global fd_ftLastAccessTimeL #enum global fd_ftLastAccessTimeH #enum global fd_ftLastWriteTimeL #enum global fd_ftLastWriteTimeH #enum global fd_nFileSizeHigh #enum global fd_nFileSizeLow #enum global fd_dwReserved0 #enum global fd_dwReserved1 #enum global fd_cFileName #enum global fd_cAlternateFileName=(fd_cFileName+260/4) #enum global DIM_WIN32_FIND_DATA=(fd_cAlternateFileName+16/4) #enum global SIZE_WIN32_FIND_DATA=(DIM_WIN32_FIND_DATA*4) //-------------------------------------- // メイン部 //-------------------------------------- *Init dim hFind dim fdFile,DIM_WIN32_FIND_DATA dupptr fdFileName,varptr(fdFile.fd_cFileName),MAX_PATH,2 ;文字列型 *Main screen 0,640,480,SCREEN_NORMAL title "WIN32_FIND_DATAのサンプル(中断されない)" ;エディット・ボックスの配置 sdim sBuff mesbox sBuff,ginfo_winX,ginfo_winY,5 ;検索 FindFirstFile "F:\\壁紙\\*.*",varptr(fdFile):hFind=stat if(hFind!=INVALID_HANDLE_VALUE){ repeat sBuff+=fdFileName+"\n" FindNextFile hFind,varptr(fdFile) ; if(stat==0):GetLastError:if(stat==ERROR_NO_MORE_FILES):break if(stat==0){ GetLastError if(stat==ERROR_NO_MORE_FILES):break if(stat==ERROR_MORE_DATA):logmes strf("No.%d:ERROR_MORE_DATA=[%s]",cnt+1,fdFileName) } loop FindClose hFind } objprm 0,sBuff stop //------------------------------------------------------------------------------ // End of sample127b.hsp //------------------------------------------------------------------------------

GetLastError 命令で ERROR_NO_MORE_FILES のときだけ繰り返しを抜ける。
この方法だとすべてファイル名を取得可能です。

【メモ】 ファイル名の長さが 260 バイトを超えると FindNextFile 命令は 0 を返し、 さらに GetLastError 命令で ERROR_MORE_DATA を返します。 Windows OS は Unicode 文字でファイル名を管理してるため HSP がシフトJIS文字で ファイル名を取得しようとすると場合によっては 260 バイトを超えます。 これにより FindNextFile 命令が 0 を返して検索ルーチンが中断されます。 この仕様を踏まえると FindNextFile 命令の戻り値だけで繰り返し中止にしないで GetLastError 命令で ERROR_NO_MORE_FILES が戻った時に繰り返し終了にします。

HSPの作者の方に次のバージョン時に修正して欲しいです。
お待ちしてまぁ〜す!!!



この記事に返信する


ONION software Copyright 1997-2018(c) All rights reserved.