powerbuilder匯入(讀取)檔案時的注意技巧
先看看下面一段程式碼:
這是一個讓客戶用FTP上傳檔案後,並讀取檔案內容,處理後便把檔案刪除的作業,邏輯上是合理的,絕大多數的情況下也是沒有問題的。
但是偶爾發生了客戶資料沒有處理的問題,客戶也說明明就上傳成功了,FTP傳輸日誌有出現傳輸成功的指令,但,為什麼卻沒有處理到資料?
這段程式碼持續使用迴圈檢查檔案是否生成,只要檔案出現就進行讀取。
這看起來沒有錯,但是卻常常發生檔案讀出空白或是不完整的情況。
為什麼會這樣?
最大問題出在『時間差』,也就是檔案名稱產生的時間和檔案內容產生的時間有時間差異存在。檔案越大這個問題越明顯!
因為檔案系統會先生成檔案名稱並賦予記憶體指標(檔案內容緩衝區),當檔案指標被應用程式Close時,OS才會把檔案內容緩衝區的內容,寫到磁碟機上。
這個動作是作業系統為了加快檔案處理的速度而設計,緩衝區大小預設為磁碟sector大小,也就是說你的磁碟如果 sector 是 512K ,預設緩衝區就是 512K,若是sector 為 4096K,緩衝區就是 4096K。然而這個緩衝區可以依照應用程式去要求作業系統調整的,基本的原則是sector的倍數。
相關參考:微軟檔案緩存、資料緩存定義
因此,要如何判斷得知檔案是否已經寫入完成,並且可以讀取呢?
目前我測試有兩種方法可以使用:
一、檔案大小法:如果運作的磁碟機 Sector 是 512K,而你非常肯定你的檔案大小絕對不會超過512K,那很好,除了取得檔案名稱外另外加判斷檔案大小,只要取得的檔案大小超過0,就代表檔案已經從緩衝區 Flush或Close 了,這樣就可以讀取了。
二、檔案鎖定法:利用獨佔式開啟檔案方式,確認該檔案是否已經被FTP釋放(Close)掉。
請注意,範例裡的測試檔案存在的迴圈沒有停止機制,如果您要實作,記得要加上停止機制以免當檔案一直不出現就會出現的無限迴圈
ls_path = "C:\inetpub\ftproot\upload\custOrder.txt"
do while FileExists(ls_path)
yield()
loop
dw_1.importFile(text!,ls_path)
// next , processing dw1 row data
FileDelete(ls_path)
這是一個讓客戶用FTP上傳檔案後,並讀取檔案內容,處理後便把檔案刪除的作業,邏輯上是合理的,絕大多數的情況下也是沒有問題的。
但是偶爾發生了客戶資料沒有處理的問題,客戶也說明明就上傳成功了,FTP傳輸日誌有出現傳輸成功的指令,但,為什麼卻沒有處理到資料?
這段程式碼持續使用迴圈檢查檔案是否生成,只要檔案出現就進行讀取。
這看起來沒有錯,但是卻常常發生檔案讀出空白或是不完整的情況。
為什麼會這樣?
最大問題出在『時間差』,也就是檔案名稱產生的時間和檔案內容產生的時間有時間差異存在。檔案越大這個問題越明顯!
因為檔案系統會先生成檔案名稱並賦予記憶體指標(檔案內容緩衝區),當檔案指標被應用程式Close時,OS才會把檔案內容緩衝區的內容,寫到磁碟機上。
這個動作是作業系統為了加快檔案處理的速度而設計,緩衝區大小預設為磁碟sector大小,也就是說你的磁碟如果 sector 是 512K ,預設緩衝區就是 512K,若是sector 為 4096K,緩衝區就是 4096K。然而這個緩衝區可以依照應用程式去要求作業系統調整的,基本的原則是sector的倍數。
相關參考:微軟檔案緩存、資料緩存定義
因此,要如何判斷得知檔案是否已經寫入完成,並且可以讀取呢?
目前我測試有兩種方法可以使用:
一、檔案大小法:如果運作的磁碟機 Sector 是 512K,而你非常肯定你的檔案大小絕對不會超過512K,那很好,除了取得檔案名稱外另外加判斷檔案大小,只要取得的檔案大小超過0,就代表檔案已經從緩衝區 Flush或Close 了,這樣就可以讀取了。
ls_path = "C:\inetpub\ftproot\upload\custOrder.txt"
do while FileExists(ls_path)
yield()
loop
if FileLength(ls_path) > 0 tehn
dw_1.importFile(text!,ls_path)
// next , processing dw1 row data
FileDelete(ls_path)
else
//go next perpare reading loop cycle
end if
二、檔案鎖定法:利用獨佔式開啟檔案方式,確認該檔案是否已經被FTP釋放(Close)掉。
ls_path = "C:\inetpub\ftproot\upload\custOrder.txt"
do while FileExists(ls_path)
yield()
loop
/*利用R/W lock來開啟檔案,開啟成功就代表檔案已經釋放,開啟失敗,代表檔案還被FTP使用中*/
li_file = FileOpen(ls_path,StreamMode,Read!,LockReadWrite!)
if li_file > 0 tehn
// 這裡使用pb10版本提供的ReadEx比較方便,若是舊版,請記得使用迴圈讀取檔案全部內容
ll_byte = FileReadEx(li_file,ls_data)
FileClose(li_file)
// 改用ImportString
dw_1.importString(text!,ls_data)
// next , processing dw1 row data
FileDelete(ls_path)
else
//go next perpare reading loop cycle
end if
請注意,範例裡的測試檔案存在的迴圈沒有停止機制,如果您要實作,記得要加上停止機制以免當檔案一直不出現就會出現的無限迴圈
留言