C 部落格第八周

2022-05-22 01:54:07 字數 2764 閱讀 6608

io操作基本上需要用到stream相關的子類,因此這類問題在csdn問得也是比較多。其實對於stream來說,操作起來比較簡單,只要對細節的處理稍微注意一下,相信在使用它的時候也會得心應手。對於stream相關的問題,大致分如下幾類。問題一,基本操作的問題;問題二,編碼的問題;問題三,尾部處理問題;問題四,stream快取問題;問題五,資源釋放問題;最後乙個問題,說說如何使用stream來更新大檔案部分資料。

對於問題一,基本操作的問題,主要是讀寫問題,主要是出現在檔案資料比較大,需要迴圈寫或者讀的時候。此時正確讀的形式如下。

using ( filestream fs = new filestream  ( yourfile, filemode.open,fileaccess.read,fileshare.none ) )

filemode.open,fileaccess.read,fileshare.none ) )

while( nrealread == 1024 );

可是大多數人第一次完成這樣操作的時候,都會在「nrealread = fs.read( bbuffer, 0, 1024 );」這一句犯錯誤。認為第二個引數的偏移量對於stream而設的,所以認為應該用累加的值,也就是目前總共讀了多少的位元組數。這裡需要理解一下stream的操作,當進行讀或者寫操作的時候,stream的游標會根據所讀或者所寫得位元組而自動向前跟進;其次stream.read或者stream.write這兩個方法中第二個引數是針對第乙個buffer引數而言的,而不是對於stream的,因此不要在這個地方犯錯誤。

基本問題還牽扯的就是檔案開啟的方式。有人經常問,如何同時用兩個stream開啟同乙個檔案。其實預設的stream開啟方式是獨享的,因此當不指明檔案為訪問共享的時候,後開啟檔案操作就會出現異常,因此需要向我上面所寫的那樣。還有,如果需要指定當前stream的起始位置,可以通過seek方法或者設定position屬性來完成。

對於問題二,編碼問題。有人使用stream的子類,例如streamreader之類來開啟乙個文字檔案,發現讀出來的資料是亂碼,造成這個原因大多數由於檔案中含有中文字元,同時開啟檔案的時候沒有指明編碼方式。由於英文和中文的編碼方式不同,因此在不指明編碼的時候有時會造成讀取中文錯誤。此時只要使用streamreader型別中含有encoding引數的建構函式即可,例如:using( streamreader sr = new streamreader( yourfile, encoding.default ) )

這裡只是採用系統預設的編碼方式,但有可能不太適合你檔案的編碼方式,因此需要在實際應用去除錯和變換這個引數。

問題三是,stream尾部處理問題。此類問題所展現的現象如,複製檔案的時候檔案會增大。因此在使用stream.read和stream.write的時候,要通過方法的返回值,來標明真正讀和寫的位元組數,就像前面所寫的那樣。

nrealread = fs.read( bbuffer, 0, 1024 );  // read data

debug.writeline( encoding.default.getstring( bbuffer, 0, nrealread ) );

此時在輸出的時候用的不是「1024」,而是「nrealread」做為位元組有效標示。

對於問題四,stream快取的問題,這主要表現在寫的時候。為了避免頻繁操作io而降低效率,大多數stream採用非同步寫的方式,也就是stream物件要配備有一定的快取,來暫時儲存寫的資料。但快取是有限的,當快取已滿後會造成後續寫的資料不能寫入,從而導致資料丟失。那麼此時需要顯示的呼叫stream.flush方法,來把快取的資料寫入到檔案中並清空快取。其實這並不是唯一方法,在一些stream的子類中還提供了設定buffersize的方法,或者提供了設定autoflush屬性來實現自動寫入等等,因此這裡大家可以根據不同需要而選擇不同方法來完成。

對於stream的釋放問題,這可能不單單是使用stream的問題,可能是使用c#程式設計而造成的不良習慣。雖說c#的資源是受託管的,但是對於stream來說,如果不及時釋放,那麼當其他執行緒或者程序使用此檔案的時候就會造成無法開啟的現象(由於stream大多數都是以獨享方式開啟),而且沒有及時關閉,所占用的buffer無法及時釋放。因此養成乙個好的習慣至關重要。其實釋放stream很簡單,要麼顯示的呼叫其的close和dispose這兩個方法,要麼使用using程式塊,就像我前面所寫的那樣。

最後乙個就是如何使用stream來更新大檔案。比較常見的就是,當檔案比較大,但是需要修改的部分很少,因此想要通過stream直接在某個位置進行類似於刪除、插入或者替換等操作。對於乙個檔案的更新操作,大致分為三種,這裡主要是考慮更新的位置和更新資料長度。

第一種對於檔案尾擴充套件的操作,內容長度不限;

第二種等位元組的替換操作,位置不限;

最後一種就是位置不固定,位元組數不確定。

而最後乙個,是最麻煩的。比較簡單的解決方式,建立乙個臨時檔案,然後一邊讀一邊寫,遇到需要修改的,先讀出來再修改最後再寫入。等全部寫完了,刪除舊檔案,修改臨時檔案的名稱為原來名字。比較麻煩的解決方式,就是通過share方式,用乙個讀stream和乙個寫stream直接操縱原始檔。這裡需要注意的是,為了保證新寫的資料不要沖掉還沒讀出來的資料,也就是說要控制寫stream所寫的位置不要超過要讀的位置。舉例說,目前需要讀的位置是檔案的800位元組處,也就是說800位元組以後還沒讀出來處理,此時寫stream在寫完資料後,stream的位置不能超過800位元組,如果寫採用的是快取,那麼超過800位置的資料不要立刻通過flush進行提交。總的來說,通過兩個stream來操作同乙個檔案,對於這一點要特別注意,處理不好要造成死迴圈。

stream的問題相對比較簡單,大多數人操作的時候不注意細節。所以我這裡只是稍加說明,不做特別細的說明。

第八周學習進度部落格

所花時間 5小時 量 少於100行 部落格量 兩篇 了解到的新知識 敏捷開發原則 1 盡早並持續地交付有價值的軟體以滿足顧客需求。2 敏捷流程歡迎需求的變化,並利用這種變化來提高使用者的競爭優勢。3 經常發布可用的軟體,發布間隔可以從幾周到幾個月,能短則短。4 業務人員和開發人員在專案開發過程中應該...

《結構 C 第八周》

對任務及求解方法的描述部分 問題描述 結構是一種對資料及功能進行封裝的資料結構,是比類更簡單的物件。結構也可以實現介面。程式頭部的注釋結束 using system using system.collections.generic using system.linq using system.tex...

馬哥部落格作業第八周

1 對稱加密過程由那三部分組成 答 1 傳送方將明文經過對稱金鑰進行加密形成密文。2 密文經過公網傳輸傳送到接收方。3 接收方收到密文後用加密用過的對稱金鑰進行解密產生明文。2 使用 openssl 中的 aes 對稱加密演算法對檔案 file.txt 進行加密,然後解密 加密 openssl en...