小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

二進(jìn)制文件讀寫(xiě)(寫(xiě)給新手)

 千里之外yh 2011-05-02

二進(jìn)制文件讀寫(xiě)(寫(xiě)給新手)Fortran

Fortran 二進(jìn)制文件讀寫(xiě)【給新手】
  一).一般問(wèn)題
  二進(jìn)制文件與我們通常使用的文本文件儲(chǔ)存方式有根本的不同。這樣的不同很難用言語(yǔ)表達(dá),自己親自看一看,理解起來(lái)會(huì)容易得多。因此,我推薦學(xué)習(xí)二進(jìn)制文件讀寫(xiě)的朋友安裝一款十六進(jìn)制編輯器。這樣的編輯器有很多,在我們的 CVF 附帶的集成開(kāi)發(fā)環(huán)境下就可以(將二進(jìn)制文件拖動(dòng)到 IDE 窗口后松開(kāi))。Visual Studio 2005 也是可以的。(不過(guò)需要在 File 菜單下 Open,F(xiàn)ile)
  另外推薦一款使用較多的軟件,叫做 UltraEdit(以下簡(jiǎn)稱(chēng) UE)。是很不錯(cuò)的文本編輯器,也能做十六進(jìn)制編輯器使用。
  為什么要用十六進(jìn)制編輯器?而不用 2 進(jìn)制呢?因?yàn)?nbsp;2 進(jìn)制實(shí)在太小,書(shū)寫(xiě)起來(lái)會(huì)很長(zhǎng),很不直觀。而我們的計(jì)算機(jī)把 8 位作為一個(gè)字節(jié)。剛好 2 ** 8 = 256 = 16 ** 2。用 8 位 2 進(jìn)制表達(dá)的數(shù),我們用 2 個(gè)十六進(jìn)制數(shù)據(jù)來(lái)表達(dá),更直觀和方便。
二).文件格式
  所有文件,籠統(tǒng)意義上將可以區(qū)分為兩類(lèi),一類(lèi)是文本文件,一類(lèi)是二進(jìn)制文件
1).文本文件
  文本文件用記事本等文本編輯器打開(kāi),我們可以看懂上面的信息。所以使用比較廣泛。通常一個(gè)文本文件分為很多很多行,作為數(shù)據(jù)儲(chǔ)存時(shí),還有列的概念。實(shí)際上,儲(chǔ)存在硬盤(pán)或其他介質(zhì)上,文件內(nèi)容是線一樣儲(chǔ)存的,列是用空格或 Tab 間隔,行是用回車(chē)和換行符間隔。
  以 ANSI 編碼(使用較多)的文本文件來(lái)說(shuō),例如我們儲(chǔ)存如下信息:
10
11
12
  需要的空間是:3 行 × 每行 2 個(gè)字符 + 2 個(gè)回車(chē)符 + 2 個(gè)換行符 = 10 字節(jié)。文本文件儲(chǔ)存數(shù)據(jù)是有格式,無(wú)數(shù)據(jù)類(lèi)型的。比如 10 這個(gè)數(shù)據(jù),并不指定是整型還是實(shí)型還是字符串。它有長(zhǎng)度,就是 2,兩個(gè)字節(jié)。儲(chǔ)存時(shí)計(jì)算機(jī)儲(chǔ)存它的 ASCII 碼:31h,30h。(十六進(jìn)制表示)?;剀?chē)符是:0Dh,換行符:0Ah。
    因此,這個(gè)數(shù)據(jù)儲(chǔ)存是這樣的:
31 30 0D 0A 31 31 0D 0A 31 32
  (紅色為回車(chē)符和換行符) 31h 30h 就是 10,31h 31h 就是 11,31h 32h 就是 12。因此我們也可以認(rèn)為文本文件是特殊的二進(jìn)制文件。
2).二進(jìn)制文件
  二進(jìn)制文件,是無(wú)格式有數(shù)據(jù)類(lèi)型的。比如上面的 10 11 12 三個(gè)數(shù)。但二進(jìn)制文件沒(méi)有行的概念。我們要緊湊地儲(chǔ)存他們。(當(dāng)然也可以中間加入一些空白的字節(jié))
  從數(shù)據(jù)類(lèi)型上來(lái)說(shuō),我們首先考慮整型。如果把 10 11 12 當(dāng)作 2 字長(zhǎng)的整型。則 10 表示為:0Ah 00h。因?yàn)?nbsp;0Ah 對(duì)應(yīng)十進(jìn)制 10。而后面的 00h 是空白位。2 字長(zhǎng)的整型如果不足 FFh,也就是不足 255,則需要一個(gè)空白位。類(lèi)似的:11 表示為 0Bh 00h,12 表示為 0Ch 00h。
  當(dāng)整型數(shù)據(jù)超過(guò) 255 時(shí),我們需要 2 個(gè)字節(jié)來(lái)儲(chǔ)存。比如 2748(ABCh),則表示為:BCh 0Ah。要把低位寫(xiě)在前面(BCh),高位寫(xiě)在后面(0Ah)。
  當(dāng)整型數(shù)據(jù)超過(guò) 65535 時(shí),我們就需要 4 個(gè)字節(jié)來(lái)儲(chǔ)存。比如 439041101(1A2B3C4Dh),則表示成:4Dh 3Ch 2Bh 1Ah。當(dāng)數(shù)據(jù)再大時(shí),我們就需要 8 字節(jié)儲(chǔ)存了。
  二進(jìn)制文件的實(shí)型數(shù)據(jù)也有字節(jié)長(zhǎng)度的區(qū)分,比如 4 字長(zhǎng),8 字長(zhǎng)。但實(shí)型數(shù)據(jù)的長(zhǎng)度并不僅僅代表它的表達(dá)的范圍,更多的代表精度。所以,8 字長(zhǎng)的我們又稱(chēng)為雙精度。關(guān)于實(shí)型數(shù)據(jù)如何儲(chǔ)存為 2 進(jìn)制。則有很多套規(guī)則?,F(xiàn)在都廣泛使用的是 IEEE 標(biāo)準(zhǔn)浮點(diǎn)格式。關(guān)于這樣的規(guī)則,我還正在了解,比較麻煩。就不多說(shuō)了。在這里也沒(méi)有必要了解。
  二進(jìn)制文件也可以?xún)?chǔ)存字符型數(shù)據(jù),儲(chǔ)存方法和文本文件一樣。都是使用 ASCII 編碼儲(chǔ)存的。所以我們用記事本打開(kāi)某些二進(jìn)制文件時(shí),也能看到一些有意義的字符串。(無(wú)意義的亂碼我們可以認(rèn)為是整型或?qū)嵭?,不過(guò)記事本程序當(dāng)作字符來(lái)解釋?zhuān)虼嗽斐闪藖y碼)
三).使用二進(jìn)制文件的好處
  為什么要使用二進(jìn)制文件。原因大概有三個(gè):
  第一是二進(jìn)制文件比較節(jié)約空間,這兩者儲(chǔ)存字符型數(shù)據(jù)時(shí)并沒(méi)有差別。但是在儲(chǔ)存數(shù)字,特別是實(shí)型數(shù)字時(shí),二進(jìn)制更節(jié)省空間,比如儲(chǔ)存 Real*4 的數(shù)據(jù):3.1415927,文本文件需要 9 個(gè)字節(jié),分別儲(chǔ)存:3 . 1 4 1 5 9 2 7 這 9 個(gè) ASCII 值,而二進(jìn)制文件只需要 4 個(gè)字節(jié)(DB 0F 49 40)
  第二個(gè)原因是,內(nèi)存中參加計(jì)算的數(shù)據(jù)都是用二進(jìn)制無(wú)格式儲(chǔ)存起來(lái)的,因此,使用二進(jìn)制儲(chǔ)存到文件就更快捷。如果儲(chǔ)存為文本文件,則需要一個(gè)轉(zhuǎn)換的過(guò)程。在數(shù)據(jù)量很大的時(shí)候,兩者就會(huì)有明顯的速度差別了。
  第三,就是一些比較精確的數(shù)據(jù),使用二進(jìn)制儲(chǔ)存不會(huì)造成有效位的丟失。
四).二進(jìn)制文件的儲(chǔ)存方式
    列舉一個(gè)二進(jìn)制文件如下:
00000000h: 0F 01 00 00 0F 03 00 00 12 53 21 45 58 62 35 34 ; .........S!EXb54
00000010h: 41 42 43 44 45 46 47 48 49 47 4B 4C 4D 4E 4F 50 ; ABCDEFGHIGKLMNOP

  這里列出的是在 UltraEdit(UE) 里看到的東西。其實(shí)只有紅色部分是文件內(nèi)容。前面的是 UE 加入的行號(hào)。后面的是 UE 嘗試解釋為字符型的參考。
  這個(gè)文件一共有 32 字節(jié)長(zhǎng)。顯示為兩列,每列 16 個(gè)字節(jié)。實(shí)際上,這僅僅是 UE 的顯示而已。真實(shí)的文件并不分行。僅僅知道這個(gè)文件的內(nèi)容,如果我們沒(méi)有任何說(shuō)明的話,是不能看出任何有用信息的。
  下面我規(guī)定一下說(shuō)明:我們認(rèn)為,前 4 個(gè)字節(jié)是一個(gè) 4 字節(jié)的整型數(shù)據(jù)(0F 01 00 00 十六進(jìn)制:10Fh 十進(jìn)制:271)。這 4 個(gè)字節(jié)之后的 4 個(gè)字節(jié)是另一個(gè) 4 字節(jié)的整型數(shù)據(jù)(0F 03 00 00 十六進(jìn)制:30Fh 十進(jìn)制:783)。其后的 4 個(gè)字節(jié)(12 53 21 45 )表示一個(gè) 4 字節(jié)的實(shí)型數(shù)據(jù):2.5811919E+3。再其后的 4 個(gè)字節(jié)(58 62 35 34)表示另一個(gè) 4 字節(jié)的實(shí)行數(shù)據(jù):1.6892716E-7。而只后的 16 個(gè)字節(jié)(41 42 43 44 45 46 47 48 49 47 4B 4C 4D 4E 4F 50)我們認(rèn)為是 16 個(gè)字節(jié)的字符串(ABCDEFGHIGKLMNOP)
  實(shí)際上,二進(jìn)制文件只是儲(chǔ)存數(shù)據(jù),并不寫(xiě)明數(shù)據(jù)類(lèi)型,比如上面的第 9 字節(jié)到第 16 字節(jié)(12 53 21 45 58 62 35 34),我們剛才認(rèn)為是 2 個(gè) 4 字節(jié)的實(shí)型,其實(shí)也可以認(rèn)為是 8 個(gè)字節(jié)的字符型( S!EXb54)。而后面的 16 個(gè)字節(jié)的字符串(ABCDEFGHIGKLMNOP),我們也可以認(rèn)為是 2 個(gè) 8 字節(jié)的整型,或者 4 個(gè) 4 字節(jié)的整型,甚至 2 個(gè) 8 字節(jié)的實(shí)型,4 個(gè) 4 字節(jié)的實(shí)型,等等等等。
  因此,面對(duì)一個(gè)二進(jìn)制文件,我們不能準(zhǔn)確地知道它的含義,我們需要他的數(shù)據(jù)儲(chǔ)存方式的說(shuō)明。這個(gè)說(shuō)明告訴我們第幾個(gè)字節(jié)到第幾個(gè)字節(jié)是什么類(lèi)型的數(shù)據(jù),儲(chǔ)存的數(shù)據(jù)是什么含義。否則的話,我們只能猜測(cè),或者無(wú)能為力。
五).如何使用語(yǔ)句操作二進(jìn)制文件
  我們將上面的那個(gè)二進(jìn)制文件保存為:TestBin.Bin 來(lái)舉例。
  讀取和寫(xiě)入二進(jìn)制其實(shí)是兩個(gè)很類(lèi)似的操作,了解了其中之一,另一個(gè)也就不難了。
  二進(jìn)制文件我們通常使用直接讀取方式,Open 語(yǔ)句可以寫(xiě)為:
Open( 12 , File = 'TestBin.Bin' , Access = 'Direct' , Form = 'Unformatted' , RecL = 4 )
  上面的 Access 表示直接讀取方式,F(xiàn)orm 表示無(wú)格式儲(chǔ)存。比較重要的是 RecL 。我們讀取數(shù)據(jù)時(shí),是用記錄來(lái)描述單位的,每一次讀入或?qū)懭胧且粋€(gè)記錄。記錄的長(zhǎng)度在 Open 時(shí)就確定下來(lái),以后不能改變。如果需要改變,只能 Close 以后再此 Open。
  記錄長(zhǎng)度在某些編譯器下表示讀取的 4 字節(jié)長(zhǎng)度的倍數(shù),規(guī)定為 4 表示記錄長(zhǎng)度為 16 字節(jié)。有些編譯器下就直接表示記錄的字節(jié)數(shù),規(guī)定為 4 則表示記錄長(zhǎng)度為 4 字節(jié)。這個(gè)問(wèn)題需要參考編譯器手冊(cè)。在 VF 系列里,這個(gè)值是前面一個(gè)含義。可以通過(guò)設(shè)置工程屬性的 Fortran,Data,Use Bytes as RECL= Unit for Unformatted Files 來(lái)改變,使之成為后一個(gè)含義。在命令行模式下,則使用 /assume:byterecl 這個(gè)編譯選項(xiàng)。
  確定 RecL 大小是我們需要做的事情,一般來(lái)說(shuō),不適合太大,也不適合太小。還需要結(jié)合數(shù)據(jù)儲(chǔ)存方式來(lái)考慮。太小的話,我們需要執(zhí)行讀寫(xiě)的次數(shù)就多,太大的話,我們就不方便操作小范圍的數(shù)據(jù)。
  有時(shí)候我們甚至?xí)侄啻蝸?lái)讀取數(shù)據(jù),每一次的 RecL 都不同。對(duì)于上面的 TestBin.Bin 文件來(lái)說(shuō),它比較簡(jiǎn)單,我以 16 字節(jié)長(zhǎng)度和 8 字節(jié)長(zhǎng)度兩種讀取方式來(lái)演示,你甚至可以一次 32 個(gè)字節(jié)長(zhǎng)度全部讀完:
  (1)RecL = 4 【記錄長(zhǎng)度 16 字節(jié)】
Program main
Implicit None
Integer*4 :: iVar1 , iVar2
Real*4 :: rVar1 , rVar2
Character(Len=16) :: cStr
Open( 12 , File = 'TestBin.Bin' , Access = 'Direct' , Form = 'Unformatted' , RecL = 4 )
Read( 12 , Rec = 2 ) cStr
Read( 12 , Rec = 1 ) iVar1 , iVar2 , rVar1 , rVar2
Write( * , * ) cStr
Write( * , * ) iVar1 , iVar2 , rVar1 , rVar2
Close( 12 )
End Program main

  這里的 Open 里指定了 RecL = 4(記錄長(zhǎng)度是 16 字節(jié))。
  第一個(gè) Read 語(yǔ)句,直接讀取第二筆記錄(也就是第 17 字節(jié)到第 32 字節(jié))。讀取出的 cStr = "ABCDEFGHIGKLMNOP"。
  第二個(gè) Read 語(yǔ)句,返回來(lái)讀取第一筆記錄(也就是前面 16 個(gè)字節(jié))。讀取出的數(shù)據(jù)分別放入 4 個(gè) 4 字節(jié)的變量。(其中前面兩個(gè)是整型,后面兩個(gè)是實(shí)型)
輸出結(jié)果為:
ABCDEFGHIGKLMNOP
         271         783   2581.192      1.6892716E-07
  看到這個(gè)結(jié)果,就說(shuō)明我們成功了。
  同時(shí)我們可以看到,第一個(gè)語(yǔ)句,我們直接跳到第二條記錄讀取,并沒(méi)有讀取第一條。這就是直接讀取數(shù)據(jù)的方便。有時(shí)候我們根本不需要某些數(shù)據(jù),這時(shí)候,我們可以直接跳到某一條記錄上。這個(gè)記錄甚至可以是我們實(shí)現(xiàn)算出來(lái)的變量。比如:
 iRec = ( a + b ) / C
    Read( 12 , Rec = iRec ) cStr
    實(shí)現(xiàn)我們儲(chǔ)存了 100 天的數(shù)據(jù),我們只需要第 21 天的數(shù)據(jù),我們?cè)趺崔k?在順序讀取時(shí),我們可能會(huì)開(kāi)辟一個(gè) 100 元素的數(shù)組,或者循環(huán)執(zhí)行 20 次空白的讀取。但是在直接讀取時(shí),我們只需要執(zhí)行一句 Read( 12 , Rec = 21 )。這是多么的方便。(直接讀取和順序讀取雖然于文本文件和二進(jìn)制文件沒(méi)有直接的關(guān)聯(lián),但是文本文件通常用順序讀取,而二進(jìn)制文件通常用直接讀取。這是他們的性質(zhì)決定的。)
    (2)RecL = 2【記錄長(zhǎng)度為 8 字節(jié)】
Program main
Implicit None
Integer*4 :: iVar1 , iVar2
Real*4 :: rVar1 , rVar2
Character(Len=16) :: cStr
Open( 12 , File = 'TestBin.Bin' , Access = 'Direct' , Form = 'Unformatted' , RecL = 2 )
Read( 12 , Rec = 4 ) cStr( 9 : 16 )
Read( 12 , Rec = 3 ) cStr( 1 : 8 )
Read( 12 , Rec = 1 ) iVar1 , iVar2 
Read( 12 , Rec = 2 ) rVar1 , rVar2
Write( * , * ) cStr
Write( * , * ) iVar1 , iVar2 , rVar1 , rVar2
Close( 12 )
End Program main

  這里設(shè)定的 RecL = 2 ,意思是一筆記錄 8 個(gè)字節(jié)。所以我們不能一次讀取 cStr 這個(gè) 16 字節(jié)的字符串。我們必須分兩次讀取。第一次讀取第 4 筆記錄,放入字符串后半段。第二次讀取第 3 筆記錄,放入字符串前半段。(可以調(diào)換位置)。然后讀取第一筆記錄的兩個(gè)整型變量和第二筆記錄的兩個(gè)實(shí)型變量。
  輸出結(jié)果和(1)的方法一樣。
  (3)寫(xiě)入二進(jìn)制文件
  寫(xiě)入二進(jìn)制文件同樣需要考慮 RecL 的問(wèn)題。我們這里以 RecL = 4 來(lái)舉例。
Program main
Implicit None
Open( 12 , File = 'TestBinW.Bin' , Access = 'Direct' , Form = 'Unformatted' , RecL = 4 )
Write( 12 , Rec = 1 ) 271 , 783 , 2581.192_4 , 1.6892716E-07
Write( 12 , Rec = 2 ) "ABCDEFGHIGKLMNOP"
Close( 12 )
End Program main

  寫(xiě)入二進(jìn)制文件和讀取二進(jìn)制文件是差不多的,我就不再解釋了。需要注意的是,如果直接寫(xiě)入第 N 筆記錄,而文件沒(méi)有只有 M 筆記錄(M < N),那么,第 M+1 到第 N-1 筆記錄會(huì)用 0 填充。也就是說(shuō),二進(jìn)制文件不會(huì)出現(xiàn)斷裂。
  二進(jìn)制文件的讀寫(xiě)是比較靈活的,實(shí)際應(yīng)用中,我們使用哪種方式,我們應(yīng)該根據(jù)自己的情況來(lái)設(shè)計(jì)。如何選擇合適的記錄長(zhǎng)度 RecL,如何設(shè)計(jì)高效的儲(chǔ)存方式等。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多