随笔- 121  评论- 18  文章- 0 

資料讀寫:Binary模式


●在高階的程式語言,把資料寫入檔案或是從檔案讀出資料的這個部份,可以說是很難理解,因為資料寫入檔案後,我們無法從外觀上去判別有什麼變化,大家也只能靠熟練,小瓜瓜也盡量說清處、講明白。

●前面說到Input、Append與Output模式,基本上它們是對純文書檔做存取的動作,用Write寫入、用Input讀取,而Binary則是把資料以0、1組成位元組的方式寫入檔案,而且存取的方式與Output、Input、Append不一樣。
●在Binary模式裡,Put是寫入、Get是讀出,我們先用Put來試著把資料寫入,Put #檔案編號,第幾筆,資料:

Private Sub Command1_Click() 
  Open 
"G:\test1.txt" For Binary As #1 
    Put #
1, , 1 
    Put #
1, , 2 
    Put #
1, , 3 
    Put #
1, , 4 
    Put #
1, , 5 
    Put #
1, , 6 
    Put #
1, , 7 
    Put #
1, , 8 
    Put #
1, , 9 
    Put #
1, , 0 
  Close #
1 
End Sub

●然後用記事本開起這個檔案,結果內容是一黑一白一黑一白......,因為1,2,3,4,5,6,7,8,9,0等變成了電腦的二進數,這些變成電腦二進數再轉成ASCII後,變成Windows的非列印字元,所以看不到文字。

 

●然後我們用純文字寫入:

Private Sub Command1_Click() 
  Open 
"G:\test2.txt" For Binary As #1 
    Put #
1, , "1" 
    Put #
1, , "2" 
    Put #
1, , "3" 
    Put #
1, , "4" 
    Put #
1, , "5" 
    Put #
1, , "6" 
    Put #
1, , "7" 
    Put #
1, , "8" 
    Put #
1, , "9" 
    Put #
1, , "0" 
  Close #
1 
End Sub

●然後用記事本開起這個檔案,結果內容是1234567890,因為這些數轉二進制後再轉回ASCII剛好是1234567890。

 

 ●然後利用Get來讀檔:

Private Sub Command1_Clcik() 
Dim A As Integer 
Open 
"G:\test1.txt" For Binary As #1 
  
Do Until EOF(1
    
Get #1, , A 
    
Print A 
  
Loop 
Close #
1 
End Sub
●結果印出1 2 3 4 5 6 7 8 9 0

 

●然後利用Get來讀檔:

Private Sub Command1_Clcik() 
Dim A As String * 1 
Open 
"G:\test2.txt" For Binary As #1 
  
Do Until EOF(1
    
Get #1, , A 
    
Print A 
  
Loop 
Close #
1 
End Sub
●結果印出1 2 3 4 5 6 7 8 ■

 

 
××××
●我們使用文字模式時,每一筆資料VB都會用Chr(13)來幫我們做分隔,我們用VB讀取資料時,VB也會自動分成一筆一筆的,而二進制的檔案因會把資料轉成01組成的表示資料,且每一筆資料與資料間並沒有做分格處理,因此我們在使用二進制存檔時須記得檔案資料存放的模式,再依此模式讀回資料,例:

Private Sub Command1_Click() 
Open 
"G:\test.txt" For Binary As #1 
  Put #
1, , "abcdefg" 
  Close #
1 
End Sub


●寫入字串abcdefg後

Private Sub Command2_Click() 
Dim a As Integer 
Open 
"G:\test.txt" For Binary As #1 
  
Get #1, , a 
  Close #
1 
MsgBox a 
End Sub

●用整數模式讀出的資料變成了25185,也就是( Hex(Asc("a")) & Hex(Asc("b")))16 = 25185,因為我們光用記事本開啟二進制寫入的檔案無法得知某個資料是字元型態?整數型態?或是其它型態的資料?加上如果混合了很多不同型態的資料於二進制檔後,讓其他人就更難猜測、更難解讀,資料的保秘性就更為提高了。

●假設我們要把銀行內的存款儲存在電腦裡,為了怕其他人入侵電腦而解讀,我們可以故佈疑陣:

Private Sub Command1_Click() 
   
Randomize Timer 
   
Dim A As Byte 
   
Dim B As Integer 
   
Dim C As Double 
   
Dim Bank As Single 
   A 
= Int(Rnd * 100
   B 
= Int(Rnd * 32767- 16384 
   C 
= Rnd * 50000 
   Bank 
= 200000.5 
   Open 
"G:\test.txt" For Binary As #1 
      Put #
1, , A 
      Put #
1, , B 
      Put #
1, , Bank 
      Put #
1, , C 
   Close #
1 
End Sub


●嘿嘿,我們直接用記事本將G:\test.txt檔案開啟後,結果是一堆看不懂的資料,如果沒看到上一段的程式碼,你須花一段時間來猜出這個檔案由那幾個幾種的資料來組成,我們必需按照原來的資料模式讀回資料,資料才會正確:

Private Sub Command2_Click() 
   
Dim A As Byte 
   
Dim B As Integer 
   
Dim C As Double 
   
Dim Bank As Single 
   Open 
"G:\test.txt" For Binary As #1 
      
Get #1, , A 
      
Get #1, , B 
      
Get #1, , Bank 
      
Get #1, , C 
   Close #
1 
   
MsgBox Bank 
End Sub


●讀回資料是200000.5,正確。第一章裡說過,Byte佔一個位元組、整數佔兩個位元組、單精度佔四個位元組、雙精度則佔八個位元組,因此1 + 2 + 4 + 8 = 15,其中某一段4個位元組才是正確的資料,這個就必須讓別人去猜了。
●後來讀取時按原資料型態讀取,先用Byte讀取,把第一個垃圾資訊槓掉,再用Integer讀取,再把第二個與第三個資訊槓掉,再用Single讀入第四至七個資訊,然後VB將之轉回Single型態,資料就讀出來了。
●我們把讀取順序換一下

Private Sub Command2_Click() 
   
Dim A As Byte 
   
Dim B As Integer 
   
Dim C As Double 
   
Dim Bank As Single 
   Open 
"G:\test.txt" For Binary As #1 
      
Get #1, , A 
      
Get #1, , Bank 
      
Get #1, , C 
      
Get #1, , B 
   Close #
1 
   
MsgBox Bank 
End Sub


●結果把第二至第五個資訊當成Single讀入,結果資料的值不正確。

●對於多筆資料時,我們也可以依此法並配合EOF()來讀檔:

Private Sub Command1_Click() 
   
Randomize Timer 
   
Dim A As Byte 
   
Dim B As Integer 
   
Dim C As Double 
   
Dim Bank As Single 
   Open 
"G:\test.txt" For Binary As #1 
      A 
= Int(Rnd * 100
      B 
= Int(Rnd * 32767- 16384 
      C 
= Rnd * 50000 
      Bank 
= 200000 
      Put #
1, , A 
      Put #
1, , B 
      Put #
1, , Bank 
      Put #
1, , C 

      A 
= Int(Rnd * 100
      B 
= Int(Rnd * 32767- 16384 
      C 
= Rnd * 50000 
      Bank 
= 250000 
      Put #
1, , A 
      Put #
1, , B 
      Put #
1, , Bank 
      Put #
1, , C 

      A 
= Int(Rnd * 100
      B 
= Int(Rnd * 32767- 16384 
      C 
= Rnd * 50000 
      Bank 
= 235500 
      Put #
1, , A 
      Put #
1, , B 
      Put #
1, , Bank 
      Put #
1, , C 
   Close #
1 
End Sub


●一樣用記事本開啟G:\Test.txt,結果內容還是看不懂,但我們是鈴人,知道當初的繫鈴法,我們再用VB來解鈴:

Private Sub Command2_Click() 
   
Dim A As Byte 
   
Dim B As Integer 
   
Dim C As Double 
   
Dim Bank As Single 
   Open 
"G:\test.txt" For Binary As #1 
   
Do 
      
Get #1, , A 
      
Get #1, , B 
      
Get #1, , Bank 
      
Get #1, , C 
      
MsgBox Bank 
   
Loop Until EOF(1
   Close #
1 
End Sub


●結果依依讀出的資料正確,但多了一筆0這個資料,因此在運用時,這筆資料必須省略:

Private Sub Command2_Click() 
   
Dim A As Byte 
   
Dim B As Integer 
   
Dim C As Double 
   
Dim Bank As Single 
   Open 
"G:\test.txt" For Binary As #1 
   
Do 
      
Get #1, , A 
      
Get #1, , B 
      
Get #1, , Bank 
      
Get #1, , C 
      
If Not EOF(1Then MsgBox Bank 
   
Loop Until EOF(1
   Close #
1 
End Sub

 

Private Sub Command1_Click() 

Randomize Timer 
Dim A As Byte '長度為1Byte 
Dim B As Integer '長度為2Byte 
Dim C As Double '長度為8Byte 
Dim Bank As Single '長度為4Byte 
Open "G:\test.txt" For Binary As #1 
= Int(Rnd * 100
= Int(Rnd * 32767- 16384 
= Rnd * 50000 
Bank 
= 200000 
Put #
1, , A '寫入第1Byte的位址 
Put #1, , B '寫入第2~3Byte的位址 
Put #1, , Bank '寫入第4~7Byte的位址 
Put #1, , C '寫入第8~15Byte的位址 

= Int(Rnd * 100
= Int(Rnd * 32767- 16384 
= Rnd * 50000 
Bank 
= 250000 
Put #
1, , A '寫入第16Byte的位址 
Put #1, , B '寫入第17~18Byte的位址 
Put #1, , Bank '寫入第19~22Byte的位址 
Put #1, , C '寫入第23~30Byte的位址 

= Int(Rnd * 100
= Int(Rnd * 32767- 16384 
= Rnd * 50000 
Bank 
= 235500 
Put #
1, , A '寫入第31Byte的位址 
Put #1, , B '寫入第32~33Byte的位址 
Put #1, , Bank '寫入第34~37Byte的位址 
Put #1, , C '寫入第38~45Byte的位址 
Close #1 
End Sub

●二進制檔是以一個Byte做為一個資料的當位,當我們寫入Integer,VB會自動轉成兩個Byte的資料,因此上式中,我們共存入45個1Byte的資料。

●我們可以直接讀取某個Byte的資料,我們資到我們的資料是在每一筆的第四個Byte開始讀,也就是第4、19、34個Byte位置為我們正確資料的地方,Get #檔案編號,第幾個Byte位址,資料變數:

Private Sub Command2_Click() 
   
Dim N As Byte 
   
Dim Bank As Single 
   Open 
"G:\test.txt" For Binary As #1 
   
Do 
      
Get #1, N * 15 + 4, Bank 
      
If Not EOF(1Then MsgBox Bank 
      N 
= N + 1 
   
Loop Until EOF(1
   Close #
1 
End Sub


●結果第二課的最後一個式子被減化了不少,資料也正確。

●二進制檔還有一個好處,它允許我們直接改寫第幾個Byte的資料,這個純文書檔就做不到了,假設G:\Test.txt這個檔案第二筆的金額錯誤,要改成35萬,用法是:Put #檔案編號,第幾個Byte位址,變數。

Private Sub Command1_Click() 
   
Dim Bank As Single 
   Open 
"G:\test.txt" For Binary As #1 
      Bank 
= 350000 
      Put #
119, Bank 
   Close #
1 
End Sub

 

posted on 2009-09-17 15:40  炜升  阅读(...)  评论(... 编辑 收藏