首页 c_io学习

c_io学习

举报
开通vip

c_io学习 System.IO 命名空间包含允许在数据流和文件上进行同步和异步读取及写入的类型。 以下的区别有助于澄清文件和流的差异。文件是一些具有永久存储及特定顺序的字节组成的 一个有序的、具有名称的集合。因此,对于文件,人们常会想到目录路径、磁盘存储、文件 和目录名等方面。相反,流提供一种向后备存储器写入字节和从后备存储器读取字节的方式, 后备存储器可以为多种存储媒介之一。正如除磁盘外存在多种后备存储器一样,除文件流之 外也存在多种流。例如,还存在网络流、内存流和磁带流等。 基本的文件 I/O 抽象基类 Strea...

c_io学习
System.IO 命名空间包含允许在数据流和文件上进行同步和异步读取及写入的类型。 以下的区别有助于澄清文件和流的差异。文件是一些具有永久存储及特定顺序的字节组成的 一个有序的、具有名称的集合。因此,对于文件,人们常会想到目录路径、磁盘存储、文件 和目录名等方面。相反,流提供一种向后备存储器写入字节和从后备存储器读取字节的方式, 后备存储器可以为多种存储媒介之一。正如除磁盘外存在多种后备存储器一样,除文件流之 外也存在多种流。例如,还存在网络流、内存流和磁带流等。 基本的文件 I/O 抽象基类 Stream 支持读取和写入字节。Stream 集成了异步支持。其默认实现根据其相应 的异步方法来定义同步读取和写入,反之亦然。 所有 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 示流的类都是从 Stream 类继承的。Stream 类及其派生类提供数据源和储存库的一 般视图,使程序员不必了解操作系统和基础设备的具体细节。 流涉及三个基本操作: 可以从流读取。读取是从流到数据结构(如字节数组)的数据传输。 可以向流写入。写入是从数据结构到流的数据传输。 流可以支持查找。查找是对流内的当前位置进行查询和修改。 根据基础数据源或储存库,流可能只支持这些功能中的一部分。例如,NetworkStreams 不 支持查找。Stream 的 CanRead、CanWrite 和 CanSeek 属性及其派生类决定不同的流所支 持的操作。 从 System.Object 派生的 I/O 类 BinaryReader 和 BinaryWriter 从 Streams 读取或向 Streams 写入编码的字符串和基元数 据类型。 File 提供用于创建、复制、删除、移动和打开文件的静态方法,并协助创建 FileStream 对 象。FileInfo 类提供实例方法。 Directory 提供通过目录和子目录进行创建、移动和枚举的静态方法。DirectoryInfo 类提供 实例方法。 Path 提供以跨平台的方式处理目录字符串的方法和属性。 File、Path 和 Directory 是密封(在 Microsoft Visual Basic 中为 NotInheritable)类。可以 创建这些类的新实例,但它们可以没有派生类。 System.IO.FileSystemInfo 及其派生类 FileSystemInfo 是 FileInfo 和 DirectoryInfo 对象的抽象基类。 FileInfo 提供用于创建、复制、删除、移动和打开文件的实例方法,并协助创建 FileStream 对象。File 类提供静态方法。 DirectoryInfo 提供通过目录和子目录进行创建、移动和枚举的实例方法。Directory 类提供 静态方法。 FileInfo 和 DirectoryInfo 是密封(在 Microsoft Visual Basic 中为 NotInheritable)类。可以 创建这些类的新实例,但它们可以没有派生类。 从 System.IO.Stream 派生的类 FileStream 支持通过其 Seek 方法随机访问文件。默认情况下,FileStream 以同步方式打开 文件,但它也支持异步操作。File 包含静态方法,而 FileInfo 包含实例方法。 MemoryStream 是一个非缓冲的流,可以在内存中直接访问它的封装数据。该流没有后备存 储器,可用作临时缓冲区。 NetworkStream 表示网络连接上的 Stream。虽然 NetworkStream 是从 Stream 派生的,但 它不是 System.IO 命名空间的一部分,而是在 System.Net.Sockets 命名空间中。 CryptoStream 将数据流链接到加密转换。虽然 CryptoStream 是从 Stream 派生的,但它不 是 System.IO 命名空间的一部分,而是在 System.Security.Cryptography 命名空间中。 BufferedStream 是向另一个 Stream(例如 NetworkStream)添加缓冲的 Stream。(FileStream 内部已具有缓冲,MemoryStream 不需要缓冲)。BufferedStream 对象可以围绕某些类型的 流来构成以提高读写性能。缓冲区是内存中的字节块,用于缓存数据,从而减少对操作系统 的调用次数。 System.IO.TextReader 及其派生类 TextReader 是 StreamReader 和 StringReader 对象的抽象基类。抽象 Stream 类的实现用于 字节输入和输出,而 TextReader 的实现用于 Unicode 字符输出。 StreamReader 通过使用 Encoding 进行字符和字节的转换,从 Streams 中读取字符。 StreamReader 具有一个构造函数,该构造函数根据是否存在专用于 Encoding 的 preamble (例如一个字节顺序标记)来尝试确定给定 Stream 的正确 Encoding 是什么。 StringReader 从 Strings 中读取字符。StringReader 允许您用相同的 API 来处理 Strings, 因此您的输出可以是 String 或以任何编码表示的 Stream。 System.IO.TextWriter 及其派生类 TextWriter 是 StreamWriter 和 StringWriter 对象的抽象基类。抽象 Stream 类的实现用于 字节输入和输出,而 TextWriter 的实现用于 Unicode 字符输出。 StreamWriter 通过使用 Encoding 将字符转换为字节,向 Streams 写入字符。 StringWriter 向 Strings 写入字符。StringWriter 允许您用相同的 API 来处理 Strings,这样 您的输出可以是 String 或以任何编码表示的 Stream。 枚举数 FileAccess、FileMode 和 FileShare 枚举定义某些 FileStream 和 IsolatedStorageFileStream 构造函数及某些 File.Open 重载方法使用的常数。这些常数影响创建、打开和共享基础文件 的方式。 SeekOrigin 枚举数定义用来指定随机访问文件入口点的常数。这些常数和字节偏移量一起 使用。 I/O 和安全性 当在 System.IO 命名空间中使用类时,要使访问被允许,则必须满足诸如访问控制列表 (ACL) 等操作系统安全性要求。该要求是在所有 FileIOPermission 要求之外的要求。 警告 Internet 和 Intranet 的默认安全策略不允许访问文件。因此,如果您在编写将通过 Internet 下载的代码,则不要使用“regular”(即非隔离存储)IO 类。请改用独立存储。 警告当文件或网络流打开时,只有在构造流时才执行安全检查。因此,当将这些流分发给受 信度较低的代码或应用程序域时,请格外小心。 创建目录列表 下面的代码示例显示了如何使用 IO 类来创建目录列表。 [C#] using System; using System.IO; class DirectoryLister { public static void Main(String[] args) { DirectoryInfo dir = new DirectoryInfo("."); foreach (FileInfo f in dir.GetFiles("*.cs")) { String name = f.FullName; long size = f.Length; DateTime creationTime = f.CreationTime; Console.WriteLine("{0,-12:N0} {1,-20:g} {2}", size, creationTime, name); } } } 在本示例中,DirectoryInfo 对象是当前目录,用 (".") 表示,代码列出了当前目录中具有 .cs 扩展名的所有文件,同时还列出了这些文件的大小、创建时间和名称。假设 C:\MyDir 的 \Bin 子目录中存在多个 .cs 文件,该代码的输出可能如下所示: 953 7/20/2000 10:42 AM C:\MyDir\Bin\paramatt.cs 664 7/27/2000 3:11 PMC:\MyDir\Bin\tst.cs 403 8/8/2000 10:25 AM C:\MyDir\Bin\dirlist.cs using System; using System.Collections.Generic; using System.Text; using System.IO; namespace DirectoryLister { class DirectoryLister { static void Main(string[] args) { DirectoryInfo dir = new DirectoryInfo("."); foreach(FileInfo fi in dir.GetFiles("*.*")) { string fullName=fi.FullName; long size=fi.Length; DateTime createTime= fi.CreationTime; // FileAttributes A=fi.Attributes; Console.WriteLine("{0},{1},{2}",fullName,size.ToString(),createTime.ToLocalTime().ToString()) ; } Console.ReadLine(); } } } 如果您要另一个目录中文件的列表,例如 C:\ root 目录,请记着使用反斜杠 (\) 转义符,如 “C:\\”中的反斜杠。您也可以使用 Unix 样式的斜杠,如“C:/”中的斜杠。 对刚创建的数据文件进行读取和写入 BinaryWriter 和 BinaryReader 类用于读取和写入数据,而不是字符串。下面的代码示例示 范了向新的、空文件流 (Test.data) 写入数据及从该文件读取数据。在当前目录中创建了数 据文件之后,也就同时创建了相关的 BinaryWriter 和 BinaryReader,BinaryWriter 用于向 Test.data 写入整数 0 到 10,Test.data 在文件尾留下了一个文件指针。在将文件指针设置 回初始位置后,BinaryReader 读出指定的内容。 [C#] using System; using System.IO; class MyStream { private const string FILE_NAME = "Test.data"; public static void Main(String[] args) { // Create the new, empty data file. if (File.Exists(FILE_NAME)) { Console.WriteLine("{0} already exists!", FILE_NAME); return; } FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew); // Create the writer for data. BinaryWriter w = new BinaryWriter(fs); // Write data to Test.data. for (int i = 0; i < 11; i++) { w.Write( (int) i); } w.Close(); fs.Close(); // Create the reader for data. fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs); // Read data from Test.data. for (int i = 0; i < 11; i++) { Console.WriteLine(r.ReadInt32()); w.Close(); } } } 如果 Test.data 已存在于当前目录中,则引发一个 IOException。始终使用 FileMode.Create 创建新文件,而不引发 IOException。 打开并附加到日志文件 StreamWriter 和 StreamReader 向流写入字符并从流读取字符。下面的代码示例打开 log.txt 文件(如果文件不存在则创建文件)以进行输入,并将信息附加到文件尾。然后将文件的内 容写入标准输出,以便显示出来。 [C#] using System; using System.IO; class DirAppend { public static void Main(String[] args) { StreamWriter w = File.AppendText("log.txt"); Log("Test1", w); Log("Test2", w); // Close the writer and underlying file. w.Close(); // Open and read the file. StreamReader r = File.OpenText("log.txt"); DumpLog(r); } public static void Log(String logMessage, TextWriter w) { w.Write("\r\nLog Entry : "); w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString()); w.WriteLine(" :"); w.WriteLine(" :{0}", logMessage); w.WriteLine("-------------------------------"); // Update the underlying file. w.Flush(); } public static void DumpLog(StreamReader r) { // While not at the end of the file, read and write lines. String line; while ((line = r.ReadLine()) != null) { Console.WriteLine(line); } r.Close(); } } 下面的代码示例读取整个文件,并在检测到文件尾时发出通知。 [C#] using System; using System.IO; public class TextFromFile { private const string FILE_NAME = "MyFile.txt"; public static void Main(String[] args) { if (!File.Exists(FILE_NAME)) { Console.WriteLine("{0} does not exist!", FILE_NAME); return; } StreamReader sr = File.OpenText(FILE_NAME); String input; while ((input=sr.ReadLine())!=null) { Console.WriteLine(input); } Console.WriteLine ("The end of the stream has been reached."); sr.Close(); } } 此 代码通 过调 用 File.OpenText 创 建一个 指向 MyFile.txt 的 StreamReader 。 StreamReader.ReadLine 将每一行都返回为一个字符串。当没有要读取的字符时,一条消息 显示该情况,然后流关闭。 向文件写入文本 下面的代码示例创建一个新文本文件并向其写入一个字符串。 [C#] using System; using System.IO; public class TextToFile { private const string FILE_NAME = "MyFile.txt"; public static void Main(String[] args) { if (File.Exists(FILE_NAME)) { Console.WriteLine("{0} already exists!", FILE_NAME); return; } StreamWriter sr = File.CreateText(FILE_NAME); sr.WriteLine ("This is my file."); sr.WriteLine ("I can write ints {0} or floats {1}, and so on.", 1, 4.2); sr.Close(); } } 从字符串中读取字符 下面的代码示例允许您在现有字符串中从指定的位置开始读取一定数目的字符。使用 StringReader 完成此操作,如下所示。 代码定义字符串并将其转换为字符数组,然后,可以使用适当的 StringReader.Read 方法按 需要读取该字符数组。 [C#] using System; using System.IO; public class CharsFromStr { public static void Main(String[] args) { // Create a string to read characters from. String str = "Some number of characters"; // Size the array to hold all the characters of the string, // so that they are all accessible. char[] b = new char[24]; // Create a StringReader and attach it to the string. StringReader sr = new StringReader(str); // Read 13 characters from the array that holds the string, starting // from the first array member. sr.Read(b, 0, 13); // Display the output. Console.WriteLine(b); // Close the StringReader. sr.Close(); } } 在 C#中有 2个类 FileStream类操作的是字节数据, Stream类操作的是字符数据。 字符数据易于使用,但功能简单,某些高级功能则必须使用 FileStream 通过读取字节数据,FileStream对象可以用于读取图像和声音,代价是 FileStream对象不能 将数据直接读入字符串。 //Stream打开文件 StreamReader sr=new StreamReader(@"c:\a.txt",Encoding.UTF8); string sLine=""; StringBuilder sb=new StringBuilder(); while((sLine=sr.ReadLine())!=null) { sb.Append(sLine); } rechTextBox.Text=sb.ToString(); sr.Close(); //或者 StreamReader sr=new StreamReader(... rechTextBox.Text=sr.ReadToEnd(); sr.Close(); //FileStream打开文件 FileStream fs=new FileStream(@"c:\a.txt",FileMode.Open); byte[] bt=new byte[fs.Length]; char[] ca=new char[fa.Length]; fs.Read(bt, 0, Convert.ToInt32(fs.Length)); Decoder dc=Encoding.UTF8.GetDecoder(); dc.GetChars(bt,0,bt.Length,ca,0); StringBuilder sb2=new StringBuilder(); for(int i=0; i 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 : 使用 DirectoryInfo.GetFiles方法的重载版本,它可以接受一个过滤表达式,返回 FileInfo数 组,另外它的参数还可以指定是否对子目录进行查找。如: dir.GetFiles("*.txt", SearchOption.AllDirectories); 问题 9:如何复制、移动、重命名、删除文件和目录; 解决方案:使用 FileInfo和 DirectoryInfo类。 下面是 FileInfo类的相关方法: FileInfo.CopyTo:将现有文件复制到新文件,其重载版本还允许覆盖已存在文件; FileInfo.MoveTo:将指定文件移到新位置,并提供指定新文件名的选项,所以可以用来重命 名文件(而不改变位置); FileInfo.Delete:永久删除文件,如果文件不存在,则不执行任 何操作; FileInfo.Replace:使用当前 FileInfo对象对应文件的内容替换目标文件,而且指定另一个文 件名作为被替换文件的备份,微软考虑实在周到。 下面是DirectoryInfo类的相关方法: DirectoryInfo.Create:创建指定目录,如果指定路径中有多级目录不存在,该方法会一一创 建; DirectoryInfo.CreateSubdirectory:创建当前对象对应的目录的子目录; DirectoryInfo.MoveTo:将目录(及其包含的内容)移动至一个新的目录,也可用来重命名 目录; DirectoryInfo.Delete:删除目录(如果它存在的话)。如果要删除一个包含子目录的目录,要 使用它的重载版本,以指定递归删除。 注意到了没有?DirectoryInfo类少了一个 CopyTo方法,不过我们可以通过递归来实现这个 功能: /// /// 复制目录到目标目录 /// /// 源目录 /// 目标目录 public static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination) { // 如果两个目录相同,则无须复制 if (destination.FullName.Equals(source.FullName)) { return; } // 如果目标目录不存在,创建它 if (!destination.Exists) { destination.Create(); } // 复制所有文件 FileInfo[] files = source.GetFiles(); foreach (FileInfo file in files) { // 将文件复制到目标目录 file.CopyTo(Path.Combine(destination.FullName, file.Name), true); } // 处理子目录 DirectoryInfo[] dirs = source.GetDirectories(); foreach (DirectoryInfo dir in dirs) { string destinationDir = Path.Combine(destination.FullName, dir.Name); // 递归处理子目录 CopyDirectory(dir, new DirectoryInfo(destinationDir)); } } 问题 10:如何获得计算机的所有逻辑驱动器; 解决方案:使用DriveInfo类(需要.NET 2.0) DriveInfo.GetDrives():获得计算机的所有逻辑驱动器,返回类型为DriveInfo[]; 问题 11:如何获取指定驱动器的信息; 解决方案: DriveInfo.Name:获取驱动器的名称(如 C:\); DriveInfo.DriveType:获取驱动器的类型(如 Fixed,CDRom,Removable,Network等); DriveInfo.DriveFormat:获取驱动器的格式(如NTFS,FAT32,CDFS,UDF 等); DriveInfo.IsReady:获取驱动器是否已准备好,比如 CD是否已放入 CD驱动器,如果驱动 器没有准备好,访问其信息会引发 IOException类型异常; DriveInfo.AvailableFreeSpace:获取驱动器的可用空间; DriveInfo.TotalFreeSpace:获取驱动器总的可用空间,它与 AvailableFreeSpace的不同在于 AvailableFreeSpace会磁盘配额的设置; DriveInfo.TotalSize:获取驱动器总的空间; DriveInfo.RootDirectory:获得驱动器的根目录(DirectoryInfo类型); 至此,我们已经了解了文件和目录相关的一些基本操作。 文件读写相关类介绍: 文件读写操作涉及的类主要是: MarshalByRefObject 类:允许在支持远程处理的应用程序中跨应用程序域边界访问对象; BinaryReader 类:用特定的编码将基元数据类型读作二进制值。 BinaryWriter 类: 以二进制形式将基元类型写入流,并支持用特定的编码写入字符串。 Stream 类: 提供字节序列的一般视图。 FileStream类:公开以文件为主的 Stream,既支持同步读写操作,也支持异步读写操作。 MemoryStream 类:创建其支持存储区为内存的流。 BufferedStream 类:给另一流上的读写操作添加一个缓冲层。 TextReader 类:表示可读取连续字符系列的阅读器。 TextWriter 类:表示可以编写一个有序字符系列的编写器。 StreamReader 类:实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。 StreamWriter 类:实现一个 TextWriter,使其以一种特定的编码向流中写入字符。 StringReader 类:实现从字符串进行读取的 TextReader。 StringWriter 类:实现一个用于将信息写入字符串的 TextWriter。该信息存储在基础 StringBuilder 中。 在使用它们之前最好能了解它们的继承关系,有助于作出最合适的选择: 另外还要注意一下 FileInfo和 File类的一些方法,如 Create,CreateText,Open等,有时也 会带来方便。 这些类的内容比较繁多,更多内容还请参考MSDN。 下面是一些常见的问题及其解决方案: 问题 1:如何读写文本文件(并考虑不同的编码类型); 解决方案: 创建一个 FileStream 对象用以引用该文件。要写入文件,将 FileStream 对象封装在 StreamWriter 对象中,使用其重载了的 Write 方法;要读取文件,将 FileStream对象封装在 StreamReader 对象中,使用其 Read 或 ReadLine方法; .NET Framework允许通过 StreamWriter 和 StreamReader 类操作任何流来读写文本文件。当 使用 StreamWriter 类写入数据时,调用它的 Write方法,该方法在重载后可以支持所有常见 的 C#数据类型,包括字符串、字符、整数、浮点数以及十进制数等。但 Write方法总会将 的得到的数据转换为文本,如果希望将这些文本转换回原来的数据类型,应使用 WriteLine 方法,以确保每个值都处于单独的一行上。 字符串的表现形式取决于你使用的编码,最常见的编码类型包括下面几种:ASCII,UTF-16, UTF-7,UTF-8。 .NET Framework 在 System.Text 命名空间中为每种编码类型提供了一个类。在使用 StreamWriter 和 StreamReader类时,可以指定需要的编码类型,或者使用默认的 UTF-8。 而在读取文本文件时,则要使用 StreamReader 类的 Read 或 ReadLine方法。Read方法读取 单个字符或者指定个数的字符,返回类型为字符或字符数组;ReadLine 方法则返回包含整 行内容的字符串;ReadToEnd方法从当前位置读取至流的结尾。 (更多内容还请参考MSDN) 写入文本文件的示例: using (FileStream fs = new FileStream(fileName, FileMode.Create)) { // 创建一个 StreamWriter 对象,使用 UTF-8编码格式 using (StreamWriter writer = new StreamWriter(fs, Encoding.UTF8)) { // 分别写入十进制数,字符串和字符类型的数据 writer.WriteLine(123.45M); writer.WriteLine("String Data"); writer.WriteLine('A'); } } 读取文本文件的示例: // 以只读模式打开一个文本文件 using (FileStream fs = new FileStream(fileName, FileMode.Open)) { using (StreamReader reader = new StreamReader(fs, Encoding.UTF8)) { string text = string.Empty; while(!reader.EndOfStream) { text = reader.ReadLine(); txtMessage.Text += text + Environment.NewLine; } } } 问题 2:如何读写二进制文件(使用强数据类型); 解决方案: 创建一个 FileStream 对象用以引用该文件。要写入文件,将 FileStream 对象封装在 BinaryWriter 对象中,使用其重载了的 Write方法;要读取文件,将 FileStream对象封装在 BinaryReader对象中,使用相应数据类型的 Read方法。 .NET Framework允许通过 BinaryWriter 和 BinaryReader类操作任何流来读写二进制数据。 当使用 BinaryWriter 类写入数据时,调用它的 Write方法,该方法在重载后可以支持所有常 见的 C#数据类型,包括字符串、字符、整数、浮点数以及十进制数等,然后数据会被编码 为一系列字节写入文件,也可以配置该过程中的编码类型。 在使用二进制文件时,一定要特别注意其中的数据类型。当你读取数据时,一定要使用 BinaryReader类的某种强类型的 Read方法。例如,要读取字符串,要使用 ReadString方法。 (BinaryWriter 在写入二进制文件时总会记录字符串的长度以避免任何可能的错误) 写入文件的示例: using (FileStream fs = new FileStream(fileName, FileMode.Create)) { using (BinaryWriter writer = new BinaryWriter(fs)) { // 写入十进制数,字符串和字符 writer.Write(234.56M); writer.Write("String"); writer.Write('!'); } } 读取文件的示例: // 以只读模式打开一个二进制文件 using (FileStream fs = new FileStream(fileName, FileMode.Open)) { using (StreamReader sr = new StreamReader(fs)) { MessageBox.Show("全部数据:" + sr.ReadToEnd()); fs.Position = 0; using (BinaryReader reader = new BinaryReader(fs)) { // 选用合适的数据类型读取数据 string message = reader.ReadDecimal().ToString() + Environment.NewLine; message += reader.ReadString() + Environment.NewLine; message += reader.ReadChar().ToString(); MessageBox.Show(message); } } } 问题 3:如何异步读取文件; 解决方案: 有时你需要读取一个文件但又不希望影响程序的执行。常见的情况是读取一个存储在网络驱 动器上的文件。 FileStream提供了对异步操作的基本支持,即它的 BeginRead和 EndRead方法。使用这些方 法,可以在 .NET Framework 线程池提供的线程中读取一个数据块,而无须直接与 System.Threading命名空间中的线程类打交道。 采用异步方式读取文件时,可以选择每次读取数据的大小。根据情况的不同,你可能会每次 读取很小的数据(比如,你要将数据逐块拷贝至另一个文件),也可能是一个相对较大的数 据(比如,在程序逻辑开始之前需要一定数量的数据)。在调用 BeginRead时指定要读取数 据块的大小,同时传入一个缓冲区(buffer)以存放数据。因为 BeginRead和 EndRead需要 访问很多相同的信息,如 FileStream,buffer,数据块大小等,因此将这些内容封装一个单 独的类当中是一个好主意。 下面这个类就是一个简单的示例。AsyncProcessor类提供了 StartProcess方法,调用它开始 读取,每次读取操作结束,OnCompletedRead回调函数会被触发,此时可以处理数据,如果 还有剩余数据,则开始一个新的读取操作。默认情况下,AsyncProcessor 类每次读取 2KB 数据。 class AsyncProcessor { private Stream inputStream; // 每次读取块的大小 private int bufferSize = 2048; public int BufferSize { get { return bufferSize; } set { bufferSize = value; } } // 容纳接收数据的缓存 private byte[] buffer; public AsyncProcessor(string fileName) { buffer = new byte[bufferSize]; // 打开文件,指定参数为 true以提供对异步操作的支持 inputStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, true); } public void StartProcess() { // 开始异步读取文件,填充缓存区 inputStream.BeginRead(buffer, 0, buffer.Length, OnCompletedRead, null); } private void OnCompletedRead(IAsyncResult asyncResult) { // 已经异步读取一个 块 ,接收数据 int bytesRead = inputStream.EndRead(asyncResult); // 如果没有读取任何字节,则流已达文件结尾 if (bytesRead > 0) { // 暂停以模拟对数据块的处理 Debug.WriteLine(" 异步线程:已读取一块"); Thread.Sleep(TimeSpan.FromMilliseconds(20)); // 开始读取下一块 inputStream.BeginRead(buffer, 0, buffer.Length, OnCompletedRead, null); } else { // 结束操作 Debug.WriteLine(" 异步线程:读取文件结束"); inputStream.Close(); } } } 使用该类时可以这么写: // 开始在另一线程中异步读取文件 AsyncProcessor asyncIO = new AsyncProcessor("test.txt"); asyncIO.StartProcess(); // 在主程序中,做其它事情,这里简单地循环 10秒 DateTime startTime = DateTime.Now; while (DateTime.Now.Subtract(startTime).TotalSeconds < 10) { Debug.WriteLine("主程序:正在进行"); // 暂停线程以模拟耗时的操作 Thread.Sleep(TimeSpan.FromMilliseconds(100)); } Debug.WriteLine("主程序:已完成"); 问题 4:如何创建临时文件; 解决方案: 有时需要在特定用户的临时目录下创建一个临时文件,这要求该文件具有唯一的名称,避免 与其它程序生成的临时文件相冲突。我们会有多种选择。最简单的是,在程序所在目录内使 用 GUID或时间戳加上随机值作为文件名称。但 Path类提供的方法还是可以为你节省工作 量,这就是它的静态 GetTempFileName 方法,它在当前用户的临时目录下创建一个临时文 件(文件名称一定是唯一的),临时目录通常类似于这样: C:\Documents and Settings\[username]\Local Settings\Temp。 string tempFile = Path.GetTempFileName(); using (FileStream fs = new FileStream(tempFile, FileMode.Open)) { using (BinaryWriter writer = new BinaryWriter(fs)) { // 写入数据 writer.Write("临时文件信息"); } } // Do something // 最后删除临时文件 File.Delete(tempFile); 问题 5:如何获得随机文件名; 解决方案: 使用 Path.GetRandomFileName 方法,它与 GetTempFileName方法的不同之处在于它仅仅返 回一个字符串但不会创建文件。 问题 6:监视文件系统的变化; 解决方案: 如果指定路径内的文件发生改变(比如文件被修改或创建),你希望能对此作出反应。 如果程序与其它多个程序或业务处理相关,常常需要创建一个程序,并且只有文件系统发生 变化时它才处于活动状态。你可以创建一个这样的程序,让它定期区检测指定目录,此时会 发现有件事情让你苦恼:检测得越频繁,就会浪费越多的系统资源;而检测得越少,那么检 测到变化的时间就会越长。 这时可以使用 FileSystemWatcher组件,指定要进行监视的目录或文件,并处理其 Created, Deleted,Renamed,Changed 事件。 要使用 FileSystemWatcher组件,首先要创建它的一个实例,然后设置下列属性: Path:指定要监视的目录; Filter:指定要监视的文件类型,如”*.txt”; NotifyFilter:指定要监视的变化类型; FileSystemWatcher会引发四个关键的事件:Created,Deleted,Renamed,Changed。这些事 件都在其 FileSystemEventArgs参数中提供了相关文件的信息:如文件名,路径,改变类型, Renamed 事件中还可以了解到改变前的文件名和路径。如果要禁用这些事件,则将它的 EnableRaisingEvents属性设置为 false。Created,Deleted,Renamed三个事件比较容易处理, 但 Changed 事件就得当心了,你需要设置它的 NotifyFilter 属性以指示监视那些类型的变化。 否则,程序会在文件被修改时淹没在不断发生的事件中(缓存区溢出)。 // 设置相关属性 watcher.Path = appPath; watcher.Filter = "*.txt"; watcher.IncludeSubdirectories = true; // 添加事件处理函数 watcher.Created += new FileSystemEventHandler(OnChanged); watcher.Deleted += new FileSystemEventHandler(OnChanged); watcher.Changed += new FileSystemEventHandler(OnChanged); watcher.Renamed += new RenamedEventHandler(OnRenamed); void OnRenamed(object sender, RenamedEventArgs e) { string renamedFormat = "File: {0} 被重命名为 :{1}"; txtChangedInfo.Text = string.Format(renamedFormat, e.OldFullPath, e.FullPath); } void OnChanged(object sender, FileSystemEventArgs e) { // 显示通知信息 txtChangedInfo.Text = "文件: " + e.FullPath + "发生改变" + Environment.NewLine; txtChangedInfo.Text += "改变类型: " + e.ChangeType.ToString(); } 问题 7:如何使用独立存储文件; 解决方案: 有时你需要将数据存储在文件中,但对本地硬盘驱动器却没有必要的权限 (FileIOPermission)。这时要用到 System.IO.IsolatedStorage命名空间中的类,这些类允许你 的程序在特定用户的目录下将数据写入文件而不需要直接访问硬盘驱动器的权限: // 创建当前用户的独立存储 using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForAssembly()) { // 创建一个文件夹 store.CreateDirectory("MyFolder"); // 创建一个独立存储文件 using (Stream fs = new IsolatedStorageFileStream("MyFile.txt", FileMode.Create, store)) { StreamWriter writer = new StreamWriter(fs); writer.WriteLine("Test Line!"); writer.Flush(); } Debug.WriteLine("当前大小:" + store.CurrentSize.ToString() + Environment.NewLine); Debug.WriteLine("范围:" + store.Scope.ToString() + Environment.NewLine); string[] files = store.GetFileNames("*.*"); if (files.Length > 0) { Debug.WriteLine("当前文件:" + Environment.NewLine); foreach (string file in files) { Debug.WriteLine(file + Environment.NewLine); } } }
本文档为【c_io学习】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_456476
暂无简介~
格式:pdf
大小:256KB
软件:PDF阅读器
页数:18
分类:互联网
上传时间:2012-03-03
浏览量:36