以Record讀二進位檔案,無法獲得正確結果 |
答題得分者是:ccchen
|
godspeedx10
一般會員 發表:9 回覆:25 積分:6 註冊:2002-04-22 發送簡訊給我 |
諸位前輩大家好:
生產資訊Sensor.Dat有480 Bytes,依順序只有2或4 Bytes的區分,之前是用VB程式將它分解,現在想換Delphi來做。
我分別以三種方式來讀取並分解Sensor.Dat,程式運作正常,可是以Single定義的Array內的值都不對,都是一些如2.14123582666E-41、1.35455698855E38之類的。VB分解的都正常,為何Delphi會錯呢? Help上說Single的有效位數有6、7位,但我將它顯示在Label上時,小數點後都有十幾位,為何會如此?請前輩們協助。程式如下:
unit Sensor; interface uses windows, sysutils, classes; type //AB PLC 產生之SENSOR.DAT 總共480 bytes 參考HFFH01.H TSensor = record D01: Word; D11: Word; D12: Word; D21: Word; D22: Word; D31: Word; D32: Word; D41: Word; D42: Word; D51: Word; D52: Word; AI11: Word; AI12: Word; AI21: Word; AI22: Word; AI31: Word; AI32: Word; AI41: Word; AI42: Word; FA1: array[1..16] of Single; FA2: array[1..16] of Single; FA3: array[1..8] of Single; FA4: array[1..16] of Single; D61: Word; D62: Word; D71: Word; D72: Word; FA5: array[1..16] of Single; FA6: array[1..16] of Single; FA7: array[1..16] of Single; AI51: Word; AI52: Word; AI61: Word; AI62: Word; AI71: Word; AI72: Word; D08: Word; D09: Word; D10: Word; end; procedure ReadSensor; procedure GetRollingVars; var HP, OldHP: TSensor; //UR 變數 dUR_H_Force, dUR_HDS_Force, dUR_HWS_Force, dUR_V_Force, dUR_VDS_Force, dUR_VWS_Force, dUR_H_Gap, dUR_V_Gap, dUR_Current: single; iUR_TotalPass, iUR_CurrentPass: integer; implementation uses Main; //-------------------------------------------------------------------------- procedure ReadSensor; var fsSensor: TFileStream; Sensor: file of TSensor; iNum: integer; iFileHandle: Integer; iBytesRead: Integer; begin { //--第一種方式----------------------------- try AssignFile(Sensor, sNetDrive 'Sensor.dat'); Reset(Sensor); try Read(Sensor, HP); except end; finally CloseFile(Sensor); end; //--第二種方式----------------------------- iFileHandle := FileOpen(sNetDrive 'Sensor.dat', fmOpenRead or fmShareDenyNone); iBytesRead := FileRead(iFileHandle, HP, sizeof(HP)); FileClose(iFileHandle); } //--第三種方式----------------------------- fsSensor := TFileStream.Create(sNetDrive 'Sensor.dat', fmOpenRead or fmShareDenyNone); fsSensor.ReadBuffer(HP, 480); fsSensor.Free; GetRollingVars; end; //-------------------------------------------------------------------------- procedure GetRollingVars; begin dUR_H_Force := HP.FA1[14]; dUR_HDS_Force := HP.FA5[5]; dUR_HWS_Force := HP.FA5[6]; dUR_VDS_Force := HP.FA5[7]; dUR_VWS_Force := HP.FA5[8]; dUR_V_Force := (dUR_VDS_Force dUR_VWS_Force) / 2; dUR_H_Gap := HP.FA1[15]; dUR_Current := HP.FA2[2]; iUR_TotalPass := Round(HP.FA5[4]); iUR_CurrentPass := Round(HP.FA5[14]); end; end. |
ccchen
版主 發表:61 回覆:940 積分:1394 註冊:2002-04-15 發送簡訊給我 |
|
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
|
ccchen
版主 發表:61 回覆:940 積分:1394 註冊:2002-04-15 發送簡訊給我 |
packed record 與 reocrd 之間有何異何呢?
Delphi為了執行效率, 對一般宣告之變數配置記憶體均採用Natural Boundaries. 以32bit的系統來說即使你宣告Word, 由於Register為32bits, 因此實際配置之記憶體為4bytes, 只是只使用2bytes, 這對大多數程式沒什麼問題, 但對資料擷取或傳輸系統須精確掌握bytes數之程式來說就有問題了. 宣告為packed使所有宣告之變數依其應有size配置記憶體, 不再為aligned而補入任何空白
|
godspeedx10
一般會員 發表:9 回覆:25 積分:6 註冊:2002-04-22 發送簡訊給我 |
引言: packed record 與 reocrd 之間有何異何呢? Delphi為了執行效率, 對一般宣告之變數配置記憶體均採用Natural Boundaries. 以32bit的系統來說即使你宣告Word, 由於Register為32bits, 因此實際配置之記憶體為4bytes, 只是只使用2bytes, 這對大多數程式沒什麼問題, 但對資料擷取或傳輸系統須精確掌握bytes數之程式來說就有問題了. 宣告為packed使所有宣告之變數依其應有size配置記憶體, 不再為aligned而補入任何空白我一早來依前輩的指示改成 TSensor = packed record ,一切O.K了,真是太感謝了,這問題試了二天,本來宣告為Smallint,又改為Word。 也謝謝Hanger前輩為大家深入的追問,如此又多了解一些。 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |