C#知識點:I/O

来源:http://www.cnblogs.com/DingKing/archive/2017/12/20/8067335.html
-Advertisement-
Play Games

一.什麼是I/0流? 英文翻譯:Inout/Output,在程式里簡單的理解為讀寫數據操作數據的意思。流操作是為瞭解決體積大數據占用太多的記憶體,就是分段進行操作。就跟我們吃飯一樣,一口一口的吃,還沒見過誰直接一口吃完的。流就是細水長流。 在我們強大的Net中,就是微軟為了簡化我們的工作,為了我們能對 ...


一.什麼是I/0流?

  英文翻譯:Inout/Output,在程式里簡單的理解為讀寫數據操作數據的意思。流操作是為瞭解決體積大數據占用太多的記憶體,就是分段進行操作。就跟我們吃飯一樣,一口一口的吃,還沒見過誰直接一口吃完的。流就是細水長流。

  在我們強大的Net中,就是微軟為了簡化我們的工作,為了我們能對一系列的對象進行行操作,讀寫。NetFrameWork為我們.Net程式員提供了各種各樣的類方便我們操作。他們都在Sytem.IO這個命 名空間,我們下麵的內容就是要對這些類做詳細的說明。

二. Directory DirectoryInfo 和File Fileinfo Path的作用,有什麼區別?

  File類和FileInfo類兩個的類的功能是差不多,都是操作文件的。可以對文件進行增刪該查讀寫,但是File類是靜態類不需要創建,所以他們的不同的應用場景就出現了,如果對文件進行單次操作的話,就用File類就好了。因為File類是靜態類不需要創建對象也不需要銷毀對象,可以減少性能開銷。

  這裡不明白的同學可能會和我之前一樣疑惑,既然靜態類不需要創建對象,比Fileinfo類好那麼多。那還要Fileinfo還幹嘛?那就直接用File類不就好了。其實不然,因為File類每次調用的時候都要去進行安全檢查,占用Cup,File每次都會去尋找文件性能浪費。但是FileInfo類在只會在創建的時候去尋找一次,所以顯而易見,對文件進行單步操作的時候,就是操作的一次的時候,適合使用File類。但是進行多次操作的時候,就是FileInfo更適合了,因為FileInfo雖然需要創建對象和銷毀,但是減少了每次操作要去尋找文件的消耗。所以這裡的適合與否主要是看性能。

  Directory和DirectoryInfo同理,原理一樣。(詳細介紹下次寫)

  Path類是對路徑的操作。(詳細介紹下次在寫)


三.有幾種流,這幾種流的區別是什麼,怎麼用?

1.常用的流

               文件流 FileStream

               記憶體流MemoryStream

               網路流NetworkStream

                           這個三個流都是從Stream繼承下來的。

2.Stream介紹

可以看到Stream類是應該抽象類,定義了流的聲明,具體實現由繼承它的具體子類流實現。

屬性說明:

    Position 表示流的位置,

    Length 表示流的長度。

         CanWrite表示當前流是否可以寫入。

    CanTimeOut表示當前的流是否可以超時。

    CanSeek表示 獲取指示當前流是否支持查找功能的值。

    CanRead表示當前流是否支持讀取操作。

    ReadTimeout 設置讀取操作時候的超時時間。

    WriteTimeout 設置寫入操作的時候超時的時間。

方法說明下:

  Synchronized MSDN 上解釋是指定的 Stream 對象周圍創建線程安全(同步)包裝。這個解釋我也不是很明白。應該就是給流包裝一下。返回值還是一個流。

  BeginRead:開始非同步讀操作,參數1:是一個byte數組,作為流的緩衝區,參數2是開始讀取的位置,第三個參數是讀取的讀取的長度。第四個參數是一個回調用委托參數,這個參數的作用,是在流讀取完成之後執行某些操作,第五個參數就是一個自定義的對象狀態。用與其他的流區分。這個參數不管它,占時我也不知道有啥用。

  BeginWrite同理我就不說了。

  Close()我就不說了。

  CoptyToStream():從當前流中讀取位元組並將其寫入到另一流中。

  CoptyToAsync():從名字就可以看出區別的和上面的功能一樣,只是非同步讀取。

  Read:開始讀取操作,和第一個方法一樣,但是不是非同步操作,返回值是讀到的位元組數字,返回0代表,到達流的結尾,讀完了。

  Write :同理。

  ReadAsync:取代了BeginRead

  ReadByte:讀取一個位元組,並將流的位置提升一個位元組,意思就是從你讀完的地方接著讀,不會從頭讀。

  Seek:設置當前流的位置。

  SetLength:設置當前流的長度。

Stream定義的基礎方法就這麼多,各種方法還有幾個重載版本。詳細瞭解的可以去看看MSDD官方文檔。Stream類是一個抽象類,只定義方法在聲明,具體實現由派生其的子類去實現。也就是接下來要要講解的:

  文件流FileStream

  記憶體流 MemoryStream

  和網路流NetWorkStream(System.Net.Sockets命名空間下,不同於之前兩個)

3.FileStream流

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOTest
{
    class Program
    {
        static void Main(string[] args)
        {

            //創建流實例。
            FileStream filestrem = new FileStream(@"d:\一小時小超人.txt", FileMode.Create);
            string message = "我的名字叫:一小時小超人啊";
            byte[] bytes = Encoding.UTF8.GetBytes(message);

            //寫入字元串
            filestrem.Write(bytes, 0, bytes.Length);
            
        }
    }
}

這是時候我們去D盤可以發現我們已經成功寫入了。但是這個地方有一個問題,首先我們將代碼稍微改變一下。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOTest
{
    class Program
    {
        static void Main(string[] args)
        {

            //創建流實例。
            FileStream filestream = new FileStream(@"d:\一小時小超人.txt", FileMode.Create);
            string message = "我的名字叫:一小時小超人啊";
            byte[] bytes = Encoding.UTF8.GetBytes(message);

            //寫入字元串
            filestream.Write(bytes, 0, bytes.Length);
            Console.ReadKey();
            
        }
    }
}

註意:

  這個地方標註紅色的代碼是我添加的,這時候我們再次運行時候控制台界面不會一閃而過,這個時候我們手動關閉控制台程式,然後在去D盤看我們創建的文件。  您會發現這個時候,字元沒有被寫進來。這是因為流的寫入有一個緩衝區的概念。因為I0操作是很耗時的,如果讀到一個位元組,就寫一個位元組。那這樣整個過程就很慢。

  這個原理就和網站一樣。一個操作要多次請求服務端一樣。將多次請求併為一次。這樣做節約了很多性能。IO流也是一樣。它將讀取的位元組先寫到緩衝區裡面。然後一次性寫入文件。這樣節約了很大的性能。所以Write操作只是將位元組寫入緩衝區,而不是真正的寫入文件。那麼真正的寫入文件的操作是什麼呢?

  FileStrem為了我們提供了Flush這個方法將緩衝區的內容寫入文件,清除緩衝區。所以剛剛我們手動關閉控制台。導致發生異常。寫入失敗。這時候聰明的同學可能會有疑問,第一次的時候也沒有調用Flush這個方法,也成功的寫入了。這是因為什麼呢?這是因為程式正常執行結束的時候,銷毀這個對象的時候,系統會為了保證緩衝區的文件寫入文件中,會自動幫我們調用這個Flush方法,FileStream中很多地方都調用了Flush。例如:Close()和Dispose()。

  說到 FileStream的讀寫就不得不說到StreamRead和StreamWrite這個兩個是通用讀寫器類。對流的操作都可以用它。

  之前一直沒搞清楚這個與FileStream區別,感覺這個兩個差不多,但是還是有一點區別的。

  兩者最大的區別:FileStream只要操作位元組和位元組數組,可以操作任何類型的文件,但是StreamRead主要操作的是字元串。

  敘述結束,從下麵掏一手代碼說話!

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOTest
{
    class Program
    {
        static void Main(string[] args)
        {

            //創建流實例。
            FileStream filestrem = new FileStream(@"d:\一小時小超人.txt", FileMode.Create);
            //string message = "我的名字叫:一小時小超人啊";
            //byte[] bytes = Encoding.UTF8.GetBytes(message);
            ////寫入字元串
            //filestrem.Write(bytes, 0, bytes.Length);
            //Console.ReadKey();

            StreamWriter streamwriter = new StreamWriter(filestrem);
            streamwriter.WriteLine("我是帥帥的一小時小超人!");
            streamwriter.Close();


        }
    }
}

  從代碼可以很明顯在看出來,FileStream寫入的時候是操作的是byte數組,StreamWrite操作的就是字元串。這就是這兩個類的最大區別。

  StreamWrite類操作字元/字元串比較方便,但是有些場景下使用FileStream對象更合適,操作位元組都是用FileStream比較合適,StreamRead是同樣的道理占時不想詳細在說了,下次補上。

  未完待續。。。

  太晚了,還沒寫完,明天補充,有點困,還要收拾東西。

  PS:知識點會都持續補充的,作為本人複習,學習,整理知識用。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在這裡我有先把page的設置做成了一個函數getpage,將這個方法放到Application\Common\Common\function.php(註意function不是類)中方便其他地方調用,代碼如下: 控制器中使用的代碼如下: 接下來在View中的使用 自行處理 其中設置分頁的樣式mypag ...
  • 想要爬取動態網頁,很莫名的click失效。被這個問題困擾了很久,基本上把網上提到的所有方法試遍了,最終終於有個方法成功了,在這裡總結一下。 這是我想要點擊的網頁,初始時實在0.5km上,它的class屬性是‘on’,想要點擊到2km 方法一:直接用webdriver的click方法,失效。 text ...
  • spring boot 裡面用攔截器好像比用過濾器多一點. 在過濾器中, 並不能獲取到action的相關信息, 會造成很多的麻煩和功能欠缺. 那, 這裡就用過濾器做一個小慄子, 實際使用過程中, 不會這麼做的. 用過濾器做一個不完善的登錄許可權判斷. 一. 過濾器 在這裡慄子里, 應該在過濾器裡面加個 ...
  • pycharm常用快捷鍵 1、編輯(Editing) Ctrl + Space 基本的代碼完成(類、方法、屬性)Ctrl + Alt + Space 快速導入任意類Ctrl + Shift + Enter 語句完成Ctrl + P 參數信息(在方法中調用參數) Ctrl + Q 快速查看文檔 F1 ...
  • let mview = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)) //獲取delegate let delegate = UIAp ...
  • 用JdbcTemplate的方法完成, 查詢資料庫表,把用戶表sw_user所有數據以List<User>集合返回 在JdbcTemplateDemo類中增加查詢返回所有對象集合的方法queryAllObject() 數據源DriverManagerDataSource不變 jdbcTemplate ...
  • 在EF 中使用mysql關聯取數據時,如果當前實體中包含另一個實體的list成員,而這個成員為空的話,在json序列化的時候就會報錯: '((System.Data.Entity.DynamicProxies.T_Module_FA775BC9946D7E533F86AFE9B59A3A33C411 ...
  • 1.中文亂碼問題 利用ef更新數據到mysql資料庫中,中文就會變成亂碼"???",就算把mysql的資料庫的編碼設置為"utf8"也會變成亂碼,從網上查詢了下, 在數據連接字元串後面加上:Character Set=utf8;即可,這樣插入mysql的中文就不會變成亂碼了。 2.HTML文本亂碼問 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...