|
|
2014/11/25(Tue) 17:27:44|NO.66174
いつもお世話になっております。
特定のフォルダをdirlistで監視し、
ファイル数が変動あると次のステップに進む命令を作っているのですが
dirlistの対象フォルダにたくさんファイルがある場合どうやってもCPU使用率が高くなってしまいます。
folder="C:\\"
mes folder+"をチェック中..."
*start
chdir folder
notesel list1
dirlist list1,"*.*",0 : list1size=notemax
notesel list2
repeat
wait 10
dirlist list2,"*.*",0 : list2size=notemax
if list1size ! list2size : dialog "ファイル数に変動がありました。" : break
loop
goto *start
実際には別のフォルダが対象ですが
もっと動作の軽いスマートなファイルのチェックの仕方はないでしょうか?
|
|
2014/11/25(Tue) 17:38:48|NO.66176
wait 10ではなく精度の高いawaitを使うおよびawaitで1000以上waitで100以上を使う。
何のために使うかは知りませんが毎秒監視していれば十分な気がします。
頻度を下げればその分下がります。
waitは1で1/100秒なのでそんなに早く保存されるはずがないし
2〜3秒に一回どころか数十秒に1回くらいで十分な気がします。
ちなみにdirlist自体がかなり重い処理です。
|
|
2014/11/25(Tue) 19:42:03|NO.66182
>SOU1さん
HSPでAPIを実装する時どういう風に記入したらいいかよく分からず
自分でAPIの登録(?)をやったことがありません。
こんな感じに使うのでしょうか?
#uselib "KERNEL32.DLL"
#func global ReadDirectoryChangesW "ReadDirectoryChangesW" wptr,wptr,wptr,wptr,wptr,wptr,wptr,wptr
folder="C:\\"
repeat
wait 10
ReadDirectoryChangesW folder,folcheck,buf,0,FILE_NOTIFY_CHANGE_FILE_NAME
if folcheck!0 : break
loop
dialog "ファイル数に変動がありました"
>skyblueさん
小容量のファイルがたくさん入る場所なのでwaitを短めにやっています。
標準命令ではdirlistでしか増減したファイルを判別する方法が思いつかずお手上げ状態でした。
|
|
2014/11/25(Tue) 20:59:30|NO.66183
ReadDirectoryChangesWはまずCreateFileでディレクトリのハンドルを取得する必要があります。
最後の2つのパラメータはNULLで構いません。
|
|
2014/11/25(Tue) 21:07:56|NO.66184
引数には
http://chokuto.ifdef.jp/urawaza/datatype.html
ここを参考に適切なデータ型を
SOU1さんがおっしゃっていたサイト( http://nienie.com/~masapico/api_ReadDirectoryChangesW.html)に乗っている
BOOL bResult;
HANDLE hDir;
BYTE Buf[10000];
DWORD RetBytes;
FILE_NOTIFY_INFORMATION *pInfo;
DWORD i = 0;
WCHAR FileName[1000];
hDir = CreateFile(
L"c:\\doc\\",
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
bResult = ReadDirectoryChangesW(
hDir,
Buf,
10000,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME,
&RetBytes,
NULL,
NULL);
この部分をHSP用に書き直します。
|
|
2014/11/26(Wed) 07:27:19|NO.66190
>小容量のファイルがたくさん入る場所なのでwaitを短めにやっています。
容量ではなく更新頻度で間隔をとって下さい。
|
|
2014/11/26(Wed) 22:39:37|NO.66201
>catsさん
APIを扱ったことがないため今の所
CreateFileでディレクトリのハンドルを取得の意味が理解できませんが覚えておきます。
ありがとうございました。
>nepisatさん
参考サイトありがとうございます。
サイトを見ながら調べたらここまではわかったのですが
HANDLE hDirectory, // オブジェクトハンドル
LPVOID lpBuffer, // あらゆる型のデータへのポインタ
DWORD nBufferLength, // 32ビット符号なし整数(unsigned long型 )
BOOL bWatchSubtree, // TRUE(1と定義)またはFALSE(0と定義)のブール値。通常はFALSEであるかFALSE以外であるかで識別する。
DWORD dwNotifyFilter, // 32ビット符号なし整数(unsigned long型 )
LPDWORD lpBytesReturned, // DWORD型へのポインタ
この2つがどういう型なのか分かりませんでした。
LPOVERLAPPED lpOverlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
まだ1割ほどしか理解出来ていませんが参考サイトをじっくりみながら
トライアンドエラーでやってみます。ありがとうございました。
>skyblueさん
説明不足で申し訳ありません。
小さい容量のファイルの書き換えが頻繁にあるフォルダのため
ファイル作成、削除されたら最速で動作させたいためこのようなwaitになっています。
|
|
2014/11/27(Thu) 01:11:48|NO.66203
だいぶ前にフォルダ監視用にとメモ取ってたやつを。
・フォルダサイズの監視
pathname = dir_exe
onexit *exit
s = 0
newcom oFS, "Scripting.FileSystemObject"
repeat
if oFS("FolderExists", pathname) {
oFolder = oFS("GetFolder", pathname)
if xxx ! oFolder("Size") : s ++
xxx = oFolder("Size")
title "" + s + " / " + oFolder("Size") ;/1024 + "KB"
}
wait 10
loop
stop
*exit
delcom oFS
end
元となったものを探したけれど見つけられなかったです。
的外れだったらゴメンね。
|
|
2014/11/27(Thu) 01:37:26|NO.66204
単純にファイル数を数えるとか
#uselib "kernel32"
#func global FindFirstFile "FindFirstFileA" sptr,sptr
#func global FindNextFile "FindNextFileA" sptr,sptr
#func global FindClose "FindClose" sptr
sdim lpFindFileData, $140
Dir = dir_exe
chdir Dir
gosub *Search
mes n
bak = n
repeat
gosub *Search
if bak != n : dialog "ファイル数に変動がありました。", 0, str (n) : break
wait 10
loop
end
*Search
lpFileName = "*"
FindFirstFile lpFileName, varptr (lpFindFileData)
hFile = stat
n = 0
repeat
FindNextFile hFile, varptr (lpFindFileData)
if stat = 0 {
FindClose hFile
break
}
memcpy flg, lpFindFileData, 4, 0, 0
flg And $10
if flg = 0 : n++
await
loop
return
|
|
2014/11/27(Thu) 16:34:57|NO.66207
>小容量のファイルがたくさん入る場所なのでwaitを短めにやっています。
そんなに頻繁に作成と削除とか起こりますか?
起こるのでしたらプログラムの作りが悪いだけです。
そんなに頻繁にファイルの作成と削除をするのはHDDやSDDに良くないプログラムです。
|
|
2014/11/27(Thu) 20:29:06|NO.66212
>mamoさん
その発想は思いつきませんでした!目から鱗です!
容量チェックが必要なプログラムの時ぜひ使わせて下さい。
>Himさん
自分の用途にぴったりのものでした!ありがとうございます!
こちらのソースを参考にAPIの勉強させてもらいますね。
>skyblueさん
確かにそうかもしれませんね・・・
自分のプログラムにはそういうことがないように気をつけていきたいものです。
皆さんありがとうございました!
自分でもAPIが使えるように勉強してみます。
|
|
2014/11/27(Thu) 22:01:18|NO.66215
ファイル名の長さとファイル数どの程度ですか?
dirlist(で使われてるstrbuf.cpp)の実装上、同一フォルダに数千〜数万のファイルがあると
あまり効率的じゃありません。
|
|
2014/11/27(Thu) 22:03:37|NO.66216
もう解決してるけど
ファイル数の変化だけ分かれば良いなら(ファイル名の変更も感知するが・・・)
#module
#uselib "kernel32"
#cfunc global _FindFirstChangeNotification "FindFirstChangeNotificationA" sptr,int,int
#func global FindNextChangeNotification "FindNextChangeNotification" int
#func global FindCloseChangeNotification "FindCloseChangeNotification" int
#cfunc global WaitForSingleObject "WaitForSingleObject" int,int
#define global FILE_NOTIFY_CHANGE_FILE_NAME $1
#define global FILE_NOTIFY_CHANGE_DIR_NAME $2
#define global FILE_NOTIFY_CHANGE_ATTRIBUTES $4
#define global FILE_NOTIFY_CHANGE_SIZE $8
#define global FILE_NOTIFY_CHANGE_LAST_WRITE $10
#define global FILE_NOTIFY_CHANGE_SECURITY $100
#define global WAIT_OBJECT_0 0 //指定したオブジェクトがシグナル状態になったことを意味します。
#define global WAIT_ABANDONED $80 //放棄されたミューテックスオブジェクトでした
#define global WAIT_TIMEOUT $102 //タイムアウト時間が経過し、指定されたオブジェクトが非シグナル状態であったことを意味します。
#define global WAIT_FAILED $FFFFFFFF
//変更通知ハンドルを作成
//[ 変数 = FindFirstChangeNotification(pn, ws ,filter) ]
//pn = 監視するディレクトリの名前
//ws = ディレクトリやディレクトリツリーの監視用のフラグ
//filter = 監視のためのフィルタ条件
#defcfunc FindFirstChangeNotification str pn,int ws ,int filter
if h>0 {FindCloseChangeNotification h}
h=_FindFirstChangeNotification(pn,ws,filter)
return h
//終了時に自動で呼ばれる
#deffunc fccn onexit
FindCloseChangeNotification h
return
#global
PathName=dir_cur
//パスを指定、サブフォルダは対象外(1にするとサブフォルダも含む)、ファイル名又はファイル数変更を監視
handle=FindFirstChangeNotification( PathName,0,FILE_NOTIFY_CHANGE_FILE_NAME)
if handle>0 {mes PathName +" を監視します"}else{dialog "ハンドルが取得できません":end}
repeat
wait 0
//待機時間100msで監視(変更があれば即座に抜ける)
if WaitForSingleObject(handle,100) = WAIT_OBJECT_0 {dialog "ファイル名又はファイル数に変化有り"}
//次の変更を監視(これが無いと一度変更されたフラグがクリアされず次も感知してしまう)
FindNextChangeNotification handle
loop
| |
|
2014/11/27(Thu) 22:17:54|NO.66217
>zakkiさん
7000程ありました。
確かに100程度なら問題なかったですが数千行ったらかなり重くなりましたね。
>暇人さん
サブディレクトリまで感知出来るのはすごいですね!
サブディレクトリを読み込むのはdirlist使ってrepeatして読み込んでしか思いつかなかったので
今後使わせていただくかもしれません!ありがとうございました!
|
|