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


HSPTV!掲示板


未解決 解決 停止 削除要請

2008
0712
DoubleQuotegetpathで260バイト以上の文字列を処理させると最後まで文字列が表示されない8解決


DoubleQuote

リンク

2008/7/12(Sat) 12:33:49|NO.17246

最初にスクリプト失礼いたします。

dialog getpath(fname,8)

このように記述すればfname変数に代入されているファイル名のディレクトリ情報を取り除く
事ができます。

しかしながら、このfnameが260バイトを超えると最後まで文字列が表示されません。
例えば、

fname = "c:\\aaaaa(66バイト)aa\\aaaaaaaaaaaaaaaa(200バイト)aaaaaaaa.txt
となっていると、結果として

aaaaaaaaaaaaaaaaaaaaaaaaaaaa
となってしまいます。
MAX_PATHで定義されているとかどうとか聞きました。

これを回避する為に考えた方法として、APIを駆使してこれと同じものを作る。
fxshortで対応する

という対応策を考えました。
一つ目のAPIを使う奴に関してですが、どのAPIを使えばいいのかわからず、また実装できる
かもわからず行き詰まっております。
二つ目は、動作させる環境上なるべくフルパスで表示したいのでこれは無しで考えて
居ます。


解決策があれば教えて下さい。よろしくお願いいたします。



この記事に返信する


hDA

リンク

2008/7/12(Sat) 13:27:13|NO.17247

instr と strmid ではだめですか??


#module #deffunc _getpath var fullpath, var ret idx =0 repeat i = instr( fullpath, idx, "\\" ) if i == -1 : break idx += (i + 1) loop ret = strmid( fullpath, idx, strlen(fullpath)-idx ) return #global a="c:\\difdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffsk\\test.bmp" _getpath a, b print b



flory

リンク

2008/7/12(Sat) 17:30:31|NO.17258

>APIを駆使してこれと同じものを作る。
に関してですが、「ちょくとのページ」の「Win32 API 関数リスト」で、Path〜から始まるものを参照してください。
たとえば、ディレクトリ情報を取り除くにはPathFindFileName関数を用います。
ただし、PathFindFileName関数の説明(http://msdn.microsoft.com/en-us/library/bb773589.aspx)を見ると、

>Parameters
>pPath
>[in] A pointer to a null-terminated string of maximum length MAX_PATH that contains the path to search.

となっており、APIでもMAX_PATHで制限されている模様……。当たり前と言えば当たり前なんですが。

でも、ダメ元でやってみると、なぜかうまくいってしまったり。

#uselib "shlwapi.dll" #cfunc PathFindFileName "PathFindFileNameA" int path = "c:\\aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllllmmmmmmmmmm\\nnnnnnnnnnooooooooooppppppppppqqqqqqqqqqrrrrrrrrrrssssssssssttttttttttuuuuuuuuuuvvvvvvvvvvwwwwwwwwwwxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz.txt" mes "入力パス" input path, 640, 24 mes "getpathによる結果" result1 = getpath(path,8) input result1, 640, 24 mes "PathFindFileName関数による結果" spath = strlen(path) ppath = varptr(path) pname = PathFindFileName(ppath) ; 本来なら引数の型はstr型でよいが、下のファイル名の長さの計算のためにアドレスを引数にしている dupptr result2, pname, spath-(pname-ppath)+1, 2 ; ファイル名の長さをパスの長さとアドレスから計算している input result2, 640, 24
一応、この通り動作しましたが、安全性は保障できません。そもそも、自分の環境では動作しましたが、他の環境で動作するのかもわかりません。
hDAさんの言うように自前で実装するのもひとつの手かと。

ちなみに、Unicode版の関数(〜W)を用いてMAX_PATHを突破する方法もあるらしいです。下のMaximum Path Lengthあたりを参考にしてみては?
http://msdn.microsoft.com/en-us/library/aa365247.aspx

「MAX_PATH 超える」あたりをキーワードにググってみれば、他の方法も見つかるかもしれません。


それか、いっそ「260バイトを超えるパスには対応していません」とするか。多くのアプリケーションがそうですし。



DoubleQuote

リンク

2008/7/12(Sat) 23:42:16|NO.17266

関数化してまとめてみました。


#module #uselib "shlwapi.dll" #cfunc PathFindFileName "PathFindFileNameA" int #defcfunc _getpath str _path path = _path dupptr result, PathFindFileName(varptr(path)), strlen(path)-(pname-varptr(path))+1, 2 return result #global path = "c:\\aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllllmmmmmmmmmm\\nnnncccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccnnnnnnooooooooooppppppppppqqqqqqqqqqrrrrrrrrrrssssssssssttttttttttuuuuuuuuuuvvvvvvvvvvwwwwwwwwwwxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz.txt" dialog "入力パス:"+path+"\ngetpath結果:"+getpath(path,8)+"\n_getpath結果:"+_getpath(path)+"長さは"+strlen(_getpath(path)) end

ディレクトリ情報を削除するだけでこれだけ骨が折れるのは大変ですww
getpathでやってちゃんと拡張子があるか確認して、なければこの手の命令にしようかな
と考えていますが・・・

とりあえず解決印は押さず、書き込んでみます。



DoubleQuote

リンク

2008/7/12(Sat) 23:43:39|NO.17267

書き忘れました。すみません、


path = _path
はやはり必須なんですよね?memcpyでやってみましたが、出来ませんでした。
memcpy path,_path,strlen(_memcpy)
モジュール空間では出来ないのかと



flory

リンク

2008/7/13(Sun) 15:45:38|NO.17273

あー、すいません。適当なこと書いてました。

細かいことなんですが、NO.17258にて挙げたサンプル内の
>本来なら引数の型はstr型でよいが
は間違ってます。よくないです。きちんと変数のアドレスを渡す必要があります。
たしか引数をstr型にすると、メモリを新しく確保してその中に文字列を入れてるんだったと思います。
そうなると期待した結果が得られません。


話を戻して。


ディレクトリ情報の削除なんですが、よく探してみるとそのものズバリなAPIがありました。
PathStripPath関数というもので、読んで字のごとく「パスからパスをはぎ取る」んですね。
これなら面倒臭いことをしなくても一発でできます。

以下に関数化したモジュールを置いておきますね。

#module #uselib "shlwapi.dll" #func PathStripPath "PathStripPathA" var #defcfunc _getpath str _path path = _path PathStripPath path return path #global


何度も言うようですが、PathFindFileName関数やPathStripPath関数に渡すパスは、MAX_PATHで制限されています。

>Parameters
>pPath
>[in] A pointer to a null-terminated string of maximum length MAX_PATH that contains the path to search.

ってのを簡単に訳すと、

>引数
>pPath
>[入力] 検索するパスを含む、最大でMAX_PATHの長さまでの、nullで終わる文字列へのポインタ。

となります。
NO.17258のサンプルや上のサンプルはそれを思いっきり無視しているので、もしかすると何らかの不具合が起こるかもしれません。


>path = _pathはやはり必須なんですよね?
おそらくユーザ定義命令(関数)にstr型で引数を渡した場合、変数に入った文字列ではなく、純粋な文字列として渡されるんだと思います。
ユーザ定義命令(関数)内において、str型引数に対してmemcpy、dupptr、varptrなどのメモリアドレスが関わる命令や関数などを使うと
「変数名が指定されていません」
というエラーになるので。
だから、path = _pathのようにして一度変数に格納する必要があるのでしょう。
引数をvar型にすればその必要はなくなりますが、ユーザ定義命令(関数)に渡す前に自分で変数に格納しておくことになります。



DoubleQuote

リンク

2008/7/13(Sun) 16:43:39|NO.17276

flory様、回答誠にありがとうございます。

書いてある内容理解する事が出来ました。
使用しているDLL"shlwapi.dll"
こちらのDLL、調べてみたところ、IEのおまけとして入っているようですね?
っとなるとIEのバージョンいくつ以上入っている事が前提条件という事に
成るのでしょうか??



flory

リンク

2008/7/13(Sun) 18:38:54|NO.17278

PathStripPath関数の解説ページ(http://msdn.microsoft.com/en-us/library/bb773756.aspx)を見てください。
一番下のほうにMinimum operating systemsというのがありますね?
これによると、PathStripPath関数はWindows95以上プラスIE4.0以上なら動作するようです。
つまり、PathStripPath関数が使えるshlwapi.dllはIE4.0以上に付属しているということになります。

APIの動作に必要な環境などはMSDNを見ればきちんと載っています。覚えておきましょう。
日本語のページがないこともありますが、英語のページでもだいたいの意味はわかると思います。



DoubleQuote

リンク

2008/7/13(Sun) 21:47:50|NO.17282

なるほどです。

見方まで教えて頂き、誠にありがとうございました。



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