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


HSPTV!掲示板


未解決 解決 停止 削除要請

2022
0127
めぼしテキストファイルの書き換えを検知2解決


めぼし

リンク

2022/1/27(Thu) 14:01:00|NO.95205

特定のテキストファイルが書き換えられたら処理をするということをしたいのですが、
現状ではタイムスタンプをループでチェックする方法しか思いつきません。
ファイルの書き換えが終わった瞬間をループを使わず検知する方法ってありませんでしょうか?



この記事に返信する


とあるプログラマ

リンク

2022/1/29(Sat) 14:32:55|NO.95235

FindFirstChangeNotificationで監視して変更があったらシグナルを受け取ることでできますが、ファイル自体を監視することはできなくディレクトリの監視しかできないようです。

なので対象ファイルのタイムスタンプをあらかじめ確保しておき、監視対象のディレクトリに変更があったときにその時点でのファイルのタイムスタンプと比較して変更を検知します。

すなわちファイルスタンプが変わらない変更に関しては検知できませんが、通常の使用であればそんなことはないと思うので、この方法で実装してみました。

詳しいことはソースにコメントしてあります。

#include "user32.as" #include "kernel32.as" #module #include "hspext.as" #define TRUE 1 #define FALSE 0 #define FILE_NOTIFY_CHANGE_FILE_NAME $00000001 #define FILE_NOTIFY_CHANGE_DIR_NAME $00000002 #define FILE_NOTIFY_CHANGE_ATTRIBUTES $00000004 #define FILE_NOTIFY_CHANGE_SIZE $00000008 #define FILE_NOTIFY_CHANGE_LAST_WRITE $00000010 #define FILE_NOTIFY_CHANGE_SECURITY $00000100 #define INVALID_HANDLE_VALUE $FFFFFFFF #define INFINITE $FFFFFFFF #define QS_ALLINPUT $000000FF #define WAIT_OBJECT_0 $00000000 #define GENERIC_READ $80000000 #define FILE_SHARE_DELETE $00000004 #define FILE_SHARE_READ $00000001 #define FILE_SHARE_WRITE $00000002 #define OPEN_EXISTING $00000003 #define FILE_ATTRIBUTE_NORMAL $00000080 /* モジュール内共用変数 pathFile : 監視対象ファイルのパス pathDir : 監視対象ファイルがあるディレクトリ hObj : 監視対象ディレクトリのシェルオブジェクト fileInfo : 監視対象ファイルのタイムスタンプ情報 observing : 監視が進行中であるかのフラグ */ sdim pathFile sdim pathDir dim hObj dim fileInfo dim observing // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // ディレクトリの監視を開始する // (ファイルそのものの監視はできないっぽい?) // // 戻り値 // 0 : 失敗 // 1 : 成功 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #deffunc StartObservingFile str f sdim pathFile, strlen(f) sdim pathDir pathFile = f pathDir = getpath(pathFile, 32) // 比較するためにファイルのタイムスタンプをとっておく UpdateFileInfo // 監視オブジェクト作成 dim hObj hObj = FindFirstChangeNotification(pathDir, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SECURITY) if (hObj == INVALID_HANDLE_VALUE) : return 0 observing == TRUE return 1 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // ファイルが変更されるまで待機する // // 第1引数 : ファイルが変更されたときのジャンプ先 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #deffunc stopEx label changed, \ local arr, local _stat dim arr, 1 arr(0) = hObj *@ // ウィンドウメッセージがくるかファイルが変更されるまで待機 if (observing == FALSE) { _stat = MsgWaitForMultipleObjects(0, 0, FALSE, INFINITE, QS_ALLINPUT) }else { _stat = MsgWaitForMultipleObjects(length(arr), varptr(arr), FALSE, INFINITE, QS_ALLINPUT) } // MsgWaitForMultipleObjects が制御を返したら内容に応じた処理を行う if (observing == TRUE && _stat == WAIT_OBJECT_0) { // 監視対象ファイルが変更されたのかどうかを確認 CheckIfFileUpdated FindNextChangeNotification hObj // もし変更されたのであればあらかじめ指定されたラベルにジャンプ if (stat == 1) : gosub changed } // ウィンドウメッセージはawaitで処理させる // (DispatchMessageとかはHSP3だと不具合を起こす) await 0 goto *@b return // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // 監視対象ファイルが変更されたのかを確認する // // 戻り値 // -1 : エラー // 0 : ファイルは変更されていない // 1 : ファイルは変更された // 2 : ファイルは削除済み // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #deffunc local CheckIfFileUpdated \ local time if (length(fileInfo) < 24) : return -1 exist pathFile if (strsize == -1) : return 2 // 要素を24以上確保しないとクラッシュするので注意! dim time, 24 fxtget time, pathFile // タイムスタンプを比較して違っていた = ファイルは変更された // (かなりの荒業だけど一番手っ取り早い) if (time(8) != fileInfo(8)) : UpdateFileInfo : return 1 if (time(9) != fileInfo(9)) : UpdateFileInfo : return 1 if (time(10) != fileInfo(10)) : UpdateFileInfo : return 1 if (time(11) != fileInfo(11)) : UpdateFileInfo : return 1 if (time(12) != fileInfo(12)) : UpdateFileInfo : return 1 if (time(13) != fileInfo(13)) : UpdateFileInfo : return 1 if (time(14) != fileInfo(14)) : UpdateFileInfo : return 1 if (time(15) != fileInfo(15)) : UpdateFileInfo : return 1 return 0 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // 比較のためにとっておくファイルスタンプを更新 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #deffunc local UpdateFileInfo exist pathFile if (strsize == -1) : return -1 // 要素を24以上確保しないとクラッシュするので注意! dim fileInfo, 24 fxtget fileInfo, pathFile return 1 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // 監視を一時中断する // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #deffunc SuspendObserving observing = FALSE return // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // 監視を再開する // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #deffunc ResumeObserving observing = TRUE return // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // 監視を終了する // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #deffunc QuitObserving if (hObj != 0 || hObj != INVALID_HANDLE_VALUE) : FindCloseChangeNotification hObj hObj = 0 observing = FALSE return // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // 終了時処理 (自動で呼び出されます) // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #deffunc local TermObj onexit QuitObserving return #global // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% screen 0 dialog "txt", 16 if (stat == 0) : dialog "ファイルが指定されませんでした" : stop file = refstr // 監視開始 StartObservingFile file if (stat == 0) : dialog "監視を開始するための処理に失敗しました" : stop objsize 100, 30 pos 0, 0 button gosub "監視を一時停止", *suspendob pos 100, 0 button gosub "監視を再開", *resumeob pos 200, 0 button gosub "監視対象を変更", *changeob sdim buf pos 0, 30 mesbox buf, ginfo_winx, ginfo_winy - 30, 4, 0 idMesbox = stat gosub *readtext title "ファイルの変更を監視中です" // ---------------- // stopEx *hoge // // ・普段はHSP3のstopと同じ動作です // ・ファイルが変更されたときに指定したラベルにジャンプします // ---------------- stopEx *filechanged stop // ←ねんのため // 一時停止 *suspendob title "監視は一時停止しています" SuspendObserving return // 再開 *resumeob title "監視は再開しました" ResumeObserving return // 変更 *changeob dialog "txt", 16 if (stat == 0) : return file = refstr title "監視対象が変更されました" QuitObserving StartObservingFile file gosub *readtext return // ------------------ // ファイルが変わったとき // ------------------ *filechanged title "(" + gettime(4) + ":" + gettime(5) + ":" + gettime(6) + ") ファイルは変更されました" /* Fall Through */ *readtext exist file if (strsize == -1) : dialog "ファイルが見つかりません" : return sdim buf, strsize notesel buf noteload file objprm idMesbox, buf return // ---------------------- // 必ず return !!!!!!!!!! // ----------------------



めぼし

リンク

2022/1/30(Sun) 22:44:09|NO.95254

>とあるプログラマさん
ソースまで書いていただきありがとうございます。
説明文が書いてあるので非常に分かりやすくて助かりました。



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