------- Windows Phone 7手機開發、.Net培訓、期待與您交流! -------
至今已是我寫的第十篇技術博文,通過看老楊的視頻與自己在大學裏所學的相結合,寫出這十篇博文還是很輕鬆的,但我從寫技術日記的過程中領悟到,任何知識通過第一次的短期記憶還是很不靠譜的,需要我們中加以思考,並提煉成文,這樣才能形成長期記憶,亦或是檢驗自己到底學到多少的一個標杆。
一、文件和流操作概述
文件可以看作是數據的集合,一般保存在磁盤或其他存儲介質上。文件I/O(數據的輸入/輸出)通過流(Stream)來實現;流提供一種向後備存儲寫入字節和從後備存儲讀取字節的方式。對於流有5 種基本的操作:打開、讀取、寫入、改變當前位置、關閉。
2.1磁盤的基本操作
DriveInfo類提供方法和屬性以查詢驅動器信息。使用DriveInfo類可以確定可用的驅動器及其類型;確定驅動器的容量和可用空閒空間等。下面是磁盤的基本操作示例。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class DriverInfoTest
{
static void Main()
{
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
Console.WriteLine("驅動器 {0}", d.Name);
Console.WriteLine(" 類型: {0}", d.DriveType);
if (d.IsReady == true)
{
Console.WriteLine(" 卷標: {0}", d.VolumeLabel);
Console.WriteLine(" 文件系統: {0}", d.DriveFormat);
Console.WriteLine(" 當前用戶可用空間: {0, 15}字節",d.AvailableFreeSpace);
Console.WriteLine(" 可用空間: {0, 15}字節",d.TotalFreeSpace);
Console.WriteLine(" 磁盤總大小: {0, 15}字節",d.TotalSize);
Console.ReadLine();
}
}
}
}
}
2.2目錄的基本操作
Directory類和DirectoryInfo類提供用於目錄基本操作的方法,包括創建、複製、移動、重命名和刪除目錄;獲取和設置目錄的創建、訪問及寫入的時間戳信息等。
Directory所有方法都是靜態的,調用時需要傳入目錄路徑參數。DirectoryInfo類提供實例方法,需要針對要操作的目錄路徑創建DirectoryInfo類的實例,然後調用相應的實例方法,適用於對目錄路徑執行多次操作。
Directory類的靜態方法可以直接調用,而無需構建對象實例,故適用於對目錄路徑執行一次操作;然而Directory類的靜態方法對所有方法都執行安全檢查,如果需要多次重用某個對象,建議使用DirectoryInfo的相應實例方法。下面是DirectoryInfo類對目錄的基本操作。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class DirectoryInfoTest
{
// 將源目錄複製到目標目錄.
static public void CopyDirectory(string SourceDirectory, string TargetDirectory)
{
DirectoryInfo source = new DirectoryInfo(SourceDirectory);
DirectoryInfo target = new DirectoryInfo(TargetDirectory);
//如果源目錄不存在,返回主程序.
if (!source.Exists)
return;
//如果目標目錄不存在,則創建之.
if (!target.Exists)
target.Create();
//文件複製.
FileInfo[] sourceFiles = source.GetFiles();
for (int i = 0; i < sourceFiles.Length; ++i)
File.Copy(sourceFiles[i].FullName, target.FullName + "\\" + sourceFiles[i].Name, true);
//目錄複製.
DirectoryInfo[] sourceDirectories = source.GetDirectories();
for (int j = 0; j < sourceDirectories.Length; ++j)
CopyDirectory(sourceDirectories[j].FullName, target.FullName + "\\" + sourceDirectories[j].Name);
}
static void Main()
{
string path = @"c:\MyDir";
try
{
//利用DirectoryInfo類創建、刪除目錄
// 指定要操作的目錄.
DirectoryInfo di = new DirectoryInfo(path);
// 確定目錄是否存在.
if (di.Exists)
{
Console.WriteLine("目錄{0}已經存在!", path);
return;
}
// 創建目錄.
di.Create();
Console.WriteLine("目錄{0}已經成功創建!", path);
// 刪除目錄.
di.Delete();
Console.WriteLine("\n目錄{0}已經成功刪除!", path);
//調用子程序,將源目錄SourceDirectory複製到目標目錄TargetDirectory
string SourceDirectory = @"c:\SrcDir";
string TargetDirectory = @"c:\TarDir";
CopyDirectory(SourceDirectory, TargetDirectory);
Console.WriteLine("\n源目錄{0}所有內容已經成功複製到目標目錄{1}中!", SourceDirectory, TargetDirectory);
}
catch (Exception e)
{
Console.WriteLine("\n操作失敗: {0}", e.ToString());
}
finally { }
Console.ReadLine();
}
}
}
2.3文件的基本操作
File類和FileInfo類提供用於文件基本操作的方法,包括創建、複製、移動、重命名和刪除文件;打開文件,讀取文件內容和追加內容到文件;獲取和設置文件的創建、訪問及寫入的時間戳信息等。
File所有方法都是靜態的,調用時需要傳入目錄路徑參數。FileInfo類提供實例方法,需要針對要操作的目錄路徑創建FileInfo類的實例,然後調用相應的實例方法,適用於對目錄路徑執行多次操作。
File類的靜態方法可以直接調用,而無需構建對象實例,故適用於對文件執行一次操作;然而File類的靜態方法對所有方法都執行安全檢查,如果需要多次重用某個對象,建議使用FileInfo的相應實例方法。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class FileInfoTest
{
static void Main()
{
//string path = Path.GetTempFileName();
string path = @"c:\temp\SrcFile.txt";
FileInfo fi1 = new FileInfo(path);
if (!fi1.Exists)
{
//創建文件以寫入內容.
using (StreamWriter sw = fi1.CreateText())
{
sw.WriteLine("Hello");
sw.WriteLine("And");
sw.WriteLine("Welcome");
}
}
//打開文件讀取內容.
Console.WriteLine("源文件內容爲:");
using (StreamReader sr = fi1.OpenText())
{
string s = "";
while ((s = sr.ReadLine()) != null) Console.WriteLine(s);
}
try
{
//string path2 = Path.GetTempFileName();
string path2 = @"c:\temp\DesFile.txt";
FileInfo fi2 = new FileInfo(path2);
//刪除目標文件,確保成功複製.
fi2.Delete();
//文件複製.
fi1.CopyTo(path2);
Console.WriteLine("源文件 {0} 成功複製至目標文件 {1}.", path, path2);
//刪除目標文件.
fi2.Delete();
Console.WriteLine("目標文件{0} 成功刪除.", path2);
// 打開已存在的文件,或者創建新文件.
FileInfo fi = new FileInfo(path);
// 獲取文件完整路徑.
DirectoryInfo di = fi.Directory;
// 獲取文件所在目錄中所有文件和子目錄信息.
FileSystemInfo[] fsi = di.GetFileSystemInfos();
Console.WriteLine("\n目錄 '{0}' 包含以下文件和子目錄:", di.FullName);
// 打印文件所在目錄中所有文件和子目錄信息.
foreach (FileSystemInfo info in fsi) Console.WriteLine(info.Name);
}
catch (Exception e)
{
Console.WriteLine("\n操作失敗: {0}", e.ToString());
}
finally { }
Console.ReadLine();
}
}
}
三、文本文件的讀取和寫入
StreamReader類和 StreamWriter類分別以一種特定的編碼從字節流中讀取字符和向流中寫入字符
StringReader類和 StringWriter類分別實現字符串的讀取和寫入操作
1.StreamReader和StreamWriter
StreamReader類實現一個 TextReader,使其以一種特定的編碼從字節流中讀取字符。StreamReader主要用於讀取標準文本文件的各行信息
StreamWriter類實現一個 TextWriter,使其以一種特定的編碼向流中寫入字符。StreamWriter主要用於寫入標準文本文件信息
下面使用StreamReader類和StreamWriter類讀寫文本文件。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class StreamReaderWriterTest
{
private const string FILE_NAME = @"c:\temp\TestFile.txt";
public static void Main(String[] args)
{
// 創建StreamWriter實例以在文件中添加文本.
using (StreamWriter sw = new StreamWriter(FILE_NAME))
{
// 在文件中添加文本.
sw.Write("文本文件");
sw.WriteLine("的寫入/讀取示例:");
sw.WriteLine("----------------------------------");
// Arbitrary objects can also be written to the file.
sw.WriteLine("寫入整數 {0} 或浮點數 {1}", 1, 4.2);
bool b = false; char grade = 'A'; string s = "Multiple Data Type!";
sw.WriteLine("寫入Boolean 值、字符、字符串、日期:");
sw.WriteLine(b);
sw.WriteLine(grade);
sw.WriteLine(s);
sw.Write("當前日期爲: ");
sw.WriteLine(DateTime.Now);
}
try
{
// 創建StreamReader實例以從文本文件中讀取內容.
using (StreamReader sr = new StreamReader(FILE_NAME))
{
String line;
// 讀取文本文件每一行的內容,直至文件結束.
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
catch (Exception e)
{ // 異常處理.
Console.WriteLine("該文件不能正常讀取,原因如下:");
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
}
}
2.StringReader和StringWriter
StringReader類實現從字符串進行讀取的 TextReader;StringWriter類實現一個用於將信息寫入字符串的 TextWriter;使用StringReader類和StringWriter類讀寫字符串。
using System;
using System.IO;
namespace CSharpPractice.IO{
class StringReaderWriterTest
{
public static void Main(String[] args)
{
string textReaderText = "本段爲第一段內容.\n\n" +
"第二段內容從這裏開始.\n\n" +
"第三段內容也很簡潔,只是示例而已.\n\n";
Console.WriteLine("原始文本內容如下:");
Console.WriteLine("-------------------------------------------\n{0}", textReaderText);
// 將原始文本textReaderText用一組雙倍間距的句子創建一個連續的段落
// 每個句子以字符“.”結束
string aLine, aParagraph = null;
StringReader strReader = new StringReader(textReaderText);
while (true)
{
aLine = strReader.ReadLine();
if (aLine != null)
{
aParagraph = aParagraph + aLine + " ";
}
else
{
aParagraph = aParagraph + "\n";
break;
}
}
Console.WriteLine("修改後的文本(連續的段落aParagraph)內容如下:");
Console.WriteLine("-------------------------------------------\n{0}", aParagraph);
// 從連續的段落aParagraph恢復原始文本內容textReaderText.
int intCharacter;
char convertedCharacter;
StringWriter strWriter = new StringWriter();
strReader = new StringReader(aParagraph);
while (true)
{
intCharacter = strReader.Read();
// 轉換成character前,檢查字符串是否結束.
if (intCharacter == -1) break;
convertedCharacter = Convert.ToChar(intCharacter);
if (convertedCharacter == '.') //一個句子後加入2個回車換行
{
strWriter.Write(".\n\n");
// 忽略句子間的空格.
strReader.Read();
strReader.Read();
}
else
{
strWriter.Write(convertedCharacter);
}
}
Console.WriteLine("\n還原後的原始文本內容textReaderTex:");
Console.WriteLine("-------------------------------------------\n{0}", strWriter.ToString());
Console.ReadLine();
}
}
}
四、二進制文件的讀取和寫入
FileStream類支持通過其 Seek 方法隨機訪問文件;
BinaryReader類和 BinaryWriter類在 Streams 中讀取和寫入編碼的字符串和基元數據類型.
1.FileStream類
FileStream類提供對文件進行打開、讀取、寫入、關閉等操作,既支持同步讀寫操作,也支持異步讀寫操作。FileStream支持使用Seek方法對文件進行隨機訪問,Seek通過字節偏移量將讀取/寫入位置移動到文件中的任意位置,字節偏移量是相對於查找參考點(文件的開始、當前位置或結尾,分別對應於SeekOrigin.Begin、SeekOrigin.Current和SeekOrigin.End)。下面是使用FileStream類對二進制文件進行隨機訪問。
using System;
using System.IO;
using System.Text;
namespace CSharpPractice.IO
{
class FileStreamTest
{
static void Main()
{
string path = @"c:\temp\MyTest.txt";
// 如果文件存在,則刪除之.
if (File.Exists(path)) File.Delete(path);
// 創建文件.
using (FileStream fs = File.Create(path))
{
AddText(fs, "This is some text。");
AddText(fs, "This is some more text,");
AddText(fs, "\r\nand this is on a new line");
AddText(fs, "\r\n\r\n以下是字符子集:\r\n");
for (int i = 32; i < 127; i++)
{
AddText(fs, Convert.ToChar(i).ToString());
// 每行10字符.
if (i % 10 == 0) AddText(fs, "\r\n");
}
}
// 打開流,讀取並顯示其內容.
using (FileStream fs = File.OpenRead(path))
{
byte[] b = new byte[1024];
UTF8Encoding temp = new UTF8Encoding(true);
while (fs.Read(b, 0, b.Length) > 0)
{
Console.WriteLine(temp.GetString(b));
}
}
Console.ReadLine();
}
private static void AddText(FileStream fs, string value)
{
byte[] info = new UTF8Encoding(true).GetBytes(value);
fs.Write(info, 0, info.Length);
}
}
}
2.BinaryReader和BinaryWriter
BinaryReader類用特定的編碼將基元數據類型讀作二進制值,BinaryWriter類以二進制形式將基元類型寫入流,並支持用特定的編碼寫入字符串。下面是使用BinaryWriter類和BinaryReader類讀寫二進制數據文件。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class BinaryReaderWriterTest
{
private const string FILE_NAME = @"c:\temp\Test.data";
public static void Main(String[] args)
{
// 創建一個新的、空的數據文件.
if (File.Exists(FILE_NAME))
{
Console.WriteLine("文件 {0} 已經存在,刪除之!", FILE_NAME);
File.Delete(FILE_NAME);
}
FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew);
// 創建BinaryWriter.
BinaryWriter w = new BinaryWriter(fs);
// 寫數據到新的、空的數據文件中.
for (int i = 0; i < 11; i++)
{
w.Write((int)i);
}
w.Close();
fs.Close();
// 創建BinaryReader.
fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// 數據文件中讀取數據.
for (int i = 0; i < 11; i++)
{
Console.WriteLine(r.ReadInt32());
}
r.Close();
fs.Close();
Console.ReadLine();
}
}
}
五、通用I/O流類
BufferedStream 是向另一個 Stream(例如 NetworkStream)添加緩衝的 Stream;CryptoStream 將數據流鏈接到加密轉換;MemoryStream 是一個非緩衝的流,可以在內存中直接訪問它的封裝數據。該流沒有後備存儲,可用作臨時緩衝區;NetworkStream 表示網絡連接上的 Stream。
MemoryStream類
MemoryStream創建其支持存儲區爲內存的流,使用MemoryStream流類:通過將內存用作備份來讀取和寫入數據。
using System;
using System.IO;
using System.Text;
namespace CSharpPractice.IO
{
class MemoryStreamTest
{
static void Main()
{
int count;
byte[] byteArray;
char[] charArray;
UnicodeEncoding uniEncoding = new UnicodeEncoding();
// 創建要寫入的數據(2個字符串).
byte[] firstString = uniEncoding.GetBytes("常用的ASCII字符包括:");
char[] chars = new char[127];
for (int i = 65; i < 127; i++) chars[i] = (char)i;
byte[] secondString = uniEncoding.GetBytes(chars);
using (MemoryStream memStream = new MemoryStream(100))
{ // 將第1個字符串寫入內存流.
memStream.Write(firstString, 0, firstString.Length);
// 將第2個字符串一個字節一個字節地寫入內存流.
count = 0;
while (count < secondString.Length)
{
memStream.WriteByte(secondString[count++]);
}
// 將內存流的有關屬性:
// “分配給流的字節數、流長度、流當前位置”輸出到控制檯.
Console.WriteLine(
"Capacity = {0}, Length = {1}, Position = {2}\n",
memStream.Capacity.ToString(),
memStream.Length.ToString(),
memStream.Position.ToString());
// 將當前內存流中的位置設置到內存流的開始.
memStream.Seek(0, SeekOrigin.Begin);
// 從內存流中讀取20個字節的內容.
byteArray = new byte[memStream.Length];
count = memStream.Read(byteArray, 0, 20);
// 一個字節一個字節地讀取內存流中剩下的字節.
while (count < memStream.Length)
{
byteArray[count++] = Convert.ToByte(memStream.ReadByte());
}
// 將字節數組轉換爲字符數組,並輸出到控制檯.
charArray = new char[uniEncoding.GetCharCount(byteArray, 0, count)];
uniEncoding.GetDecoder().GetChars(byteArray, 0, count, charArray, 0);
Console.WriteLine(charArray);
Console.ReadLine();
}
}
}
}
------- Windows Phone 7手機開發、.Net培訓、期待與您交流! -------