程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#讀取二進制文件辦法剖析

C#讀取二進制文件辦法剖析

編輯:C#入門知識

C#讀取二進制文件辦法剖析。本站提示廣大學習愛好者:(C#讀取二進制文件辦法剖析)文章只能為提供參考,不一定能成為您想要的結果。以下是C#讀取二進制文件辦法剖析正文


本文較為具體的剖析了C#讀取二進制文件辦法。分享給年夜家供年夜家參考。詳細剖析以下:

當想到一切文件都轉換為 XML時,確切是一件功德。然則,這並不是現實。仍然還有年夜量的文件格局不是XML,乃至也不是ASCII。二進制文件依然在收集中流傳,貯存在磁盤上,在運用法式之間傳遞。比擬之下,在處置這些成績方面,它們比文本文件顯得更有用率些。

在 C 和 C++ 中,讀取二進制文件照樣很輕易的。除一些開端符(carriage return)和停止符(line feed)的成績,每個讀到C/C++中的文件都是二進制文件。現實上,C/C++ 只曉得二進制文件,和若何讓二進制文件像文本文件一樣。當我們應用的說話愈來愈籠統時,我們最初應用的說話就不克不及直接、輕易的讀取創立的文件了。這些說話想要用它們本身奇特的方法來主動處置輸入數據。

成績的地點:

在很多盤算機迷信范疇,C 和 C++ 仍然直接按照數據構造來貯存和讀取數據。在C和C++中,按照內存中的數據構造來讀取和寫文件,是非常簡略的。在C中,你只須要應用fwrite()函數,並供給以下參數:一個指向你的數據的指針,告知它有若干個數據,一個數據有多年夜。如許,就直接用二進制格局把數據寫成文件了。

如上所述的那樣把數據寫成文件,同時假如你也曉得其准確的數據構造的話,那末也就意味著讀取文件也很輕易。你只需應用 fread() 函數,並供給以下參數:一個文件句柄,一個指向數據的指針,讀取若干個數據,每個數據的長度。 fread() 函數幫你把其他的事都做了。忽然,數據又回到了內存中。沒有采取解析和也沒有對象模子的方法,它只是把文件直接的讀到內存中。

在C和C++中,最年夜的兩個成績就是數據對齊(structure alignment)和字節交流(byte swapping)。數據對齊指的是有時編譯器會跳過數據中央的字節,由於假如處置器拜訪到那些字節,就不再處於最優化狀況下了,要消費更多的時光(普通情形,處置器拜訪未對齊數據消費的時光是拜訪對齊數據的兩倍),消費更多的指令。是以,編譯器要為了履行速度而停止優化,跳過了那些字節偏重新停止排序。另外一方面,字節交流指的是:因為分歧處置器對字節排序的方法分歧,須要對數據的字節從新排序的進程。

數據對齊

由於處置器可以或許一次處置更多的信息(在一個時鐘周期內),所以它們願望它們所處置的信息能以一種肯定的方法分列。年夜多半的 Intel 處置器使整數類型(32位的)的貯存首地址能被4除盡(即:從能被4除盡的地址上開端貯存)。假如內存中的整數不是貯存在4的倍數的地址上的話,它們是不會任務的。編譯器曉得這些。是以當編譯器碰到一個能夠惹起這類成績的數據時,它們就有上面三種選擇。

第一種,它們可以選擇在數據中添加一些無用的白空格符,如許可使整數的開端地址能被4除盡。這是一種最廣泛的做法。第二種,它們可以對字段從新排序,以便使整數處於4位的界限上。由於如許會形成其它風趣的成績,是以,這類方法較少應用。第三種選擇是,許可數據中的整數不處於4位的界限上,然則把代碼復制到一個適合的處所從而使那些整數處於4位的界限上。這類方法須要一些額定的時光消費,然則,假如必需緊縮的話,那末它就很有效了。

以上所說的這些年夜都是編譯器的細節成績,你用不著過量的擔憂。假如你對寫數據的法式和讀數據的法式應用異樣的編譯器,異樣的設定,那末,這些就不成其為成績了。編譯器用異樣的辦法來處置異樣的數據,一切都OK。然則當你觸及到跨平台文件轉換成績時,用准確的方法來分列一切數據就顯得很主要了,如許能力包管信息能被轉換。別的,一些法式員還懂得如何讓編譯器不消理會他們的數據。
字節交流(byte swapping):高位優先(big endians)和低位優先(little endians)
 
高位優先和低位優先,指的是兩種分歧的方法,把整數貯存在盤算機中的的方法。由於整數是多於一個字節的,那末,成績在於:最主要的字節能否應當起首被讀寫。最不主要的字節是變更的最頻仍的。這就是,假如你赓續給一個整數加一,最不主要的字節要轉變256次,次不主要的字節才只變更一次。

分歧的處置器用分歧的方法貯存整數。Intel 處置器普通用低位優先方法來貯存整數,換句話說,低位起首被讀寫。年夜多半其它處置器用高位優先方法來貯存整數。是以,當二進制文件在分歧平台上讀寫時,你就有能夠不能不對字節從新排序以便獲得准確的次序。

在 UNIX 平台上,還有一種特別的成績,由於UNIX可以在Sun Sparc處置器、HP處置器、IBM Power PC、Inter的芯片等多種處置器上運轉。當從一種處置器轉移到另外一種處置器上時,就意味著那些變量的字節分列次序必需翻轉,以便於它們能知足新處置器所請求的次序。

用 C# 處置二進制文件

用 C# 處置二進制文件的話,就會有別的兩項新的挑釁。第一項挑釁是:一切的 .NET 說話都是強類型的。是以,你不能不從文件中的字撙節轉換為你所想要的數據類型。第二項挑釁就是:一些數據類型比它們外面上要龐雜的多,須要某種轉換。

類型損壞(type breaking)

由於 .NET 說話,包含 C#,都是強類型的,你不克不及只是隨意率性的從文件中讀取一段字節,然後塞到數據構造中就一切OK了。是以當你要損壞類型轉換規矩時,你就不能不如許做了,起首讀取你所須要的字節數到一個字節數組中,然後把它們從頭至尾的復制到數據構造中。

在 Usenet (注:世界性的消息組收集體系)的文檔中搜索,你會找到幾個構架在 microsoft.public.dotnet條理上的一組法式,它們可以允許你把任何對象轉換為一系列字節,並可以從新轉換回對象。它們可以鄙人面地址找到 Listing A

龐雜的數據類型

在 C++ 中,你明確甚麼是對象,甚麼是數組,甚麼既不是對象又不是數組。然則在 C# 中,工作其實不像看起來的那樣簡略。一個字符串(string)就是一個對象,是以也是一個數組。由於在 C# 中,既沒有真實的數組,很多對象也沒有固定尺寸,是以一些龐雜數據類型其實不合適成為固定尺寸的二進制數據。

幸虧, .NET 供給了一種方法來處理這類成績。你可以告知 C# ,你想如何處置你的字符串(string)和其它類型的數組。這將經由過程 MarshalAs 屬性來完成。上面這個例子,就是在 C# 中應用字符串,這屬性必需要在所掌握的數據應用之前被應用:

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
你想要從二進制文件中讀取,或許貯存到二進制文件中的字符串(string)的長度就決議了參數 SizeConst 的年夜小。如許就肯定了字符串長度的最年夜值。
 處理之前的成績
 
如今,你曉得了 .NET 引入的成績是如何被處理的了。那末,在前面,你便可以懂得到,處理後面所碰到的二進制文件成績是那末的輕易。

包裝(pack)

不消費事的去設定編譯器來掌握若何分列數據。你只需應用 StructLayout 屬性便可以使數據按照你的志願來分列或打包。當你須要分歧的數據有著分歧的包裝方法的時刻,這就顯得非常有效了。這就像打扮你的汽車一樣,任你的愛好。應用 StructLayout 屬性就像你很當心的決議能否把每個數據都緊湊包裝或許照樣只將它們隨意打發,只需它們可以或許被從新讀出來就好了。 StructLayout 屬性的應用以下面所示:
[StructLayout(LayoutKind.Sequential, Pack = 1)]

如許做可使數據疏忽界限對齊,讓數據盡量的緊湊包裝。這個屬性應該和你從二進制文件中讀取的任何數據的屬性都堅持分歧(即:你寫到文件中的屬性應和從文件讀出來屬性堅持不變)。

你或許會發明,即便給你的數據加上了這個屬性後,也沒有完整處理成績。在某些情形下,你能夠不能不停止活躍冗雜的重復試驗。因為分歧盤算機和編譯器在二進制條理上的有著分歧的運轉處置方法,這就是惹起上述成績的緣由。特殊是在跨平台時,我們都必需特殊當心的處置二進制數據。 .NET 是個好對象,合適其它二進制文件,然則也其實不是一個完善的對象。

字節分列次序的翻轉(endian flipping)

讀寫二進制文件的經典成績之一就是:某些盤算機起首是貯存最不主要的字節(如:Inter),而別的一些盤算機是起首貯存最主要的字節。在 C 和 C++ 中,你不能不手動處置這個成績,並且只能是一個字段一個字段的翻轉。而 .NET 框架的長處之一就是:代碼可以在運轉時拜訪類型的元數據(metadata),你也就可以夠讀守信息,並應用它來主動處理數據中每段的字節分列次序成績。在 Listing B 上可以找到源代碼,你可以懂得是若何處置的。

一旦你得知對象的類型,你可以或許取得數據裡的每一個部門,並開端檢討每個部門,並肯定其能否是一個16位或32位的無符號整數。在任何一種上述情形下,你都可以轉變字節的排序次序,並且不會損壞數據。

留意:你不是用字符串類(string)來完成一切的事。是采取高位優先照樣低位優先,其實不會影響到字符串類。那些字段是不受翻轉代碼的影響。你也只是要留意無符號整數罷了。由於,正數在分歧的體系上,其實不是應用統一種表現方法的。正數可以只用一個記號(一名字節)表現,然則更經常使用的,倒是應用兩個記號(兩位字節)表現。這使得正數在跨平台時有些更艱苦。榮幸的是,正數在二進制文件中少少應用。

這只是多說幾句了,異樣的,浮點數有時其實不是用尺度方法表現的。雖然年夜多半體系是以IEEE格局為基本來設置浮點數的,然則照樣有一小部門老的體系應用了其它的格局來設置浮點數的。

戰勝艱苦

雖然 C# 照樣有一些成績,然則你照舊可以或許應用它來讀取二進制文件。現實上,因為 C# 所應用的那種用來拜訪對象的元數據(metadata)的方法,使它成為一種可以或許更好讀取二進制文件的說話。是以, C# 可以或許主動處理全部數據的字節交流(byte swapping)成績。

願望本文所述對年夜家的C#法式設計有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved