C# IO操作(四)大檔案拷貝(檔案流的使用)、檔案編碼

來源:互聯網
上載者:User

標籤:des   winform   style   blog   http   color   使用   os   

     大檔案拷貝(檔案流的使用)、檔案編碼

首先說一下大檔案拷貝和檔案流,因為電腦的記憶體資源是有限的,面對幾個G甚至更大的檔案,需要通過程式來完成拷貝,就需要用到檔案流(因為我們無法做到把檔案一次性載入到記憶體中;事實上,記憶體也不允許這麼幹),所以在C#中出現了記憶體流這個東西。先看下面的內容,File類中的常用讀取檔案方法會將檔案內容一次性全部載入到記憶體中

1             string sPath = @"C:\Users\Chens-PC\Desktop\Nginx.txt";2             //File類的ReadAllBytes()方法會將常值內容一次性讀取到記憶體中,然後以byte數組返回(同時關閉檔案)。3             byte[] bteData = File.ReadAllBytes(sPath);4             //File類的ReadAllLines()方法會將常值內容一次性逐行讀取到記憶體中,然後以string數組返回(同時關閉檔案),它的重載能指定讀取時使用的編碼。5             string[] strData = File.ReadAllLines(sPath);6             //File類的ReadAllText()方法會將常值內容一次性讀取到記憶體中,然後以string字串返回(同時關閉檔案),它的重載能指定讀取時使用的編碼。7             string sData = File.ReadAllText(sPath);

註:上面的代碼,在傳參時為Encoding.Default(表示與當前作業系統編碼一致,一般是簡體中文ANSI),而DotNet建立文字檔編碼為UTF-8.

在進行大檔案拷貝之前,先說一下,如果使用檔案流(FileStream):

 1            #region 通過檔案流寫檔案 2             string sMsg = "風兒吹來了童年的一幅畫 你陪著我在那過家家 竹林是我們的家 竹葉是你送我的花 抬頭見你笑得那麼的無暇"; 3             using (FileStream fsWrite = new FileStream("msg.txt", FileMode.Create, FileAccess.Write)) 4             { 5                 byte[] bteData = System.Text.Encoding.UTF8.GetBytes(sMsg); 6                 fsWrite.Write(bteData, 0, bteData.Length); 7                 fsWrite.Flush(); 8             } 9             Console.WriteLine("檔案寫入完畢!");10             #endregion
 1             #region 通過檔案流讀檔案 2             using (FileStream fsRead = new FileStream("msg.txt", FileMode.Open, FileAccess.Read)) 3             { 4                 byte[] bteData = new byte[fsRead.Length]; 5                 fsRead.Read(bteData, 0, bteData.Length); 6                 //將byte[]數群組轉換成字串時才需要指定編碼。 7                 string s = System.Text.Encoding.UTF8.GetString(bteData); 8                 Console.WriteLine(s); 9             }10             #endregion

1.大檔案拷貝:

     思路:考慮到大檔案的拷貝要邊讀邊寫,故要建立2個檔案流(一個讀,一個寫),案例的代碼如下(winform照樣適用):

1              #region 大檔案拷貝2             string sSource = @"F:\系統\cn_windows_7_ultimate_with_sp1_x86_dvd_618763.iso";3             string sTarget = @"E:\C#練習第一天\windows_7.iso";4 5             CopyBigFile(sSource, sTarget);6             Console.ReadKey();7             #endregion
View Code
 1 private static void CopyBigFile(string sSource, string sTarget) 2         { 3             using (FileStream fsRead=new FileStream(sSource,FileMode.Open,FileAccess.Read)) 4             { 5                 using (FileStream fsWrite=new FileStream(sTarget,FileMode.Create,FileAccess.Write)) 6                 { 7                     //定義緩衝區 8                     byte[] bteData = new byte[12 * 1024 * 1024]; 9                     int r = fsRead.Read(bteData, 0, bteData.Length);10                     while (r>0)11                     {12                         fsWrite.Write(bteData, 0, r);13                         double d = 100 * (fsWrite.Position / (double)fsRead.Length);14                         Console.WriteLine("{0}%", d);15                         r = fsRead.Read(bteData, 0, bteData.Length);16                     }17                     Console.WriteLine("複製大檔案成功");18                 }19             }20         }
View Code

說明:

快速建立檔案流的方式:(不要在迴圈中建立檔案流,放在迴圈外,效率問題)
     FileStream fsRead=File.OpenRead(sPath);    //快速建立讀取流
     FileStream fsWrite=File.OpenWrite(sPath);         //快速建立寫入流
     FileStream fs=File.Open(sPath,FileMode.OpenOrCreate);    //建立檔案流

上面的3個方法只是微軟對(大檔案拷貝中建立檔案流方法的封裝,簡化代碼編寫的方式)。

最後再來討論檔案讀寫亂碼的問題(檔案編碼):

下面是常用的文字檔編碼:

     1.GB2312編碼:相容ASCII碼錶,英文字元用1個位元組表示(位元組用正數來表示),中文用2個位元組表示(位元組用負數來表示)。
     2.GBK編碼:相容GB2312編碼。中文用2個位元組表示(第1個位元組用負數,第2個位元組用緊跟其後的正數)。
     3.Unicode:國際碼錶,中英文都佔2個位元組。
     4.UTF-8:國際碼錶,英文佔1個位元組,中文佔3個位元組。
因為各種編碼儲存資料格式不一致,如果讀寫編碼不同就會亂碼,解決亂碼的途徑就是讓讀寫操作時保證編碼一致即可

檔案編碼的BOM頭:

     時常在讀取檔案時用檔案的編碼,有時前面會多一個問號,這是因為BOM頭造成的File.ReadAllBytes().(不準確,有的編碼帶BOM頭,有的則不帶)

2.StreamReader與StreamWriter
 應用情境:在使用FileStream進行大檔案拷貝的時候,因為中文佔2個位元組,那麼有可能產生讀漢字讀一半的情況,進而產生亂碼。
 StreamReader,逐行讀取文字檔。ReadLine()、EndOfStream. 注意:指定編碼!

            ReadToEnd用於從當前位置一直讀到最後,內容大的話會佔記憶體;每次調用都往下走,不能無意中調用了兩次.

            ReadLine讀取一行,如果到了末尾,則返回null.


 StreamWriter,逐行寫入文字檔。

      WriteLine,將字串寫入檔案中的當前行。

3.壓縮流GZipStream:

1>壓縮:     1.建立讀取流File.OpenRead()     2.建立寫入流File.OpenWrite();     3.建立壓縮流new GZipStream();將寫入流作為參數與。     4.每次通過讀取流讀取一部分資料,通過壓縮流寫入。
 1             //GZipStream就是對FileStream的又一個封裝 2             //將文字檔1.txt壓縮 3             //1.建立讀取文字檔的流 4             using (FileStream fsRead = File.OpenRead("1.txt")) 5             { 6                 //2.建立寫入文字檔的流 7                 using (FileStream fsWrite = File.OpenWrite("yasuo.txt")) 8                 { 9                     //3.建立壓縮流10                     using (GZipStream zipStream = new GZipStream(fsWrite, CompressionMode.Compress))11                     {12                         //4.每次讀取1024byte13                         byte[] byts = new byte[1024];14                         int len = 0;15                         while ((len = fsRead.Read(byts, 0, byts.Length)) > 0)16                         {17                             //通過壓縮流寫入檔案18                             zipStream.Write(byts, 0, len);19                         }20                     }21                 }22             }23             Console.WriteLine("ok");24             Console.ReadKey();

2>解壓:

       1.建立讀取流:File.OpenRead()       2.建立壓縮流:new GZipStream();將讀取流作為參數       3.建立寫入流File.OpenWrite();       4.每次通過壓縮流讀取資料,通過寫入流寫入資料。
 1  using (FileStream fsRead = File.OpenRead("yasuo.txt")) 2             { 3  4                 using (GZipStream gzipStream = new GZipStream(fsRead, CompressionMode.Decompress)) 5                 { 6                     using (FileStream fsWrite = File.OpenWrite("jieya.txt")) 7                     { 8  9                         byte[] byts = new byte[1024];10                         int len = 0;11                         while ((len = gzipStream.Read(byts, 0, byts.Length)) > 0)12                         {13                             fsWrite.Write(byts, 0, len);14                         }15 16                     }17                 }18             }19             Console.WriteLine("ok");20             Console.ReadKey();

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.