使用 .NET的IO(2)

向字符串写入字符

下面的代码示例把从字符数组中指定位置开始的一定数目的字符写入现有的字符串。使用 StringWriter 完成此操作,如下所示。

 [C#]


using System;


using System.IO;


using System.Text;


 


public class CharsToStr


{


   public static void Main(String[] args)


   {


   // Create a StringBuilder object that can then be modified.


   StringBuilder sb = new StringBuilder("Some number of characters");


   // Define and initialize a character array from which characters


   // will be read into the StringBuilder object.


   char[] b = {' ','t','o',' ','w','r','i','t','e',' ','t','o','.'};


   // Create a StringWriter and attach it to the StringBuilder object.


   StringWriter sw = new StringWriter(sb);


   // Write three characters from the array into the StringBuilder object.


   sw.Write(b, 0, 3);


   // Display the output.


   Console.WriteLine(sb);


   // Close the StringWriter.


   sw.Close();


   }


}

此示例阐释了使用 StringBuilder 来修改现有的字符串。请注意,这需要一个附加的 using 声明,因为 StringBuilder 类是 System.Text 命名空间的成员。另外,这是一个直接创建字符数组并对其进行初始化的示例,而不是定义字符串然后将字符串转换为字符数组。

此代码产生以下输出:

Some number of characters to

构成流

后备存储器是一个存储媒介,例如磁盘或内存。每个不同的后备存储器都实现其自己的流作为 Stream 类的实现。每个流类型也都从其给定的后备存储器读取字节并向其给定的后备存储器写入字节。连接到后备存储器的流叫做基流。基流具有的构造函数具有将流连接到后备存储器所需的参数。例如,FileStream 具有指定路径参数(指定进程如何共享文件的参数)等的构造函数。

System.IO 类的设计提供简化的流构成。可以将基流附加到一个或多个提供所需功能的传递流。读取器或编写器可以附加到链的末端,这样便可以方便地读取或写入所需的类型。

下面的代码示例在现有 MyFile.txt 的周围创建 FileStream 对象,以缓冲 MyFile.txt 。(请注意,默认情况下缓冲 ** FileStreams ** 。)然后,创建 StreamReader 以读取 FileStream 中的字符, FileStream 被作为 StreamReader 的构造函数参数传递到 StreamReader 。ReadLine 进行读取,直到 Peek 发现不再有字符为止。

 [C#]


using System;


using System.IO;


public class CompBuf {


   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;


      }


      FileStream fsIn = new FileStream(FILE_NAME, FileMode.Open,


         FileAccess.Read, FileShare.Read);


      // Create a reader that can read characters from the FileStream.


      StreamReader sr = new StreamReader(fsIn); 


      // While not at the end of the file, read lines from the file.


      while (sr.Peek()>-1) {


         String input = sr.ReadLine();


         Console.WriteLine (input);


      }


      sr.Close();


   }


}

下面的代码示例在现有 MyFile.txt 的周围创建 FileStream 对象,以缓冲 MyFile.txt 。(请注意,默认情况下缓冲 ** FileStreams ** 。)然后,创建 ** BinaryReader ** 以读取 FileStream 中的字节, FileStream 被作为 BinaryReader 的构造函数参数传递到 BinaryReader 。ReadByte 进行读取,直到 PeekChar 发现不再有字节为止。

 [C#]


using System;


using System.IO;


public class ReadBuf {


   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;


      }


      FileStream f = new FileStream(FILE_NAME, FileMode.Open,


         FileAccess.Read, FileShare.Read);


      // Create a reader that can read bytes from the FileStream.


      BinaryReader sr = new BinaryReader(f); 


      // While not at the end of the file, read lines from the file.


      while (sr.PeekChar()>-1) {


         byte input = sr.ReadByte();


         Console.WriteLine (input);


      }


      sr.Close();


   }


}

创建编写器

下面的代码示例创建了一个编写器,编写器是一个可以获取某些类型的数据并将其转换成可传递到流的字节数组的类。

 [C#]


using System;


using System.IO;


public class MyWriter {


   private Stream s;


   public MyWriter(Stream stream) {


      s = stream;


   } 


   public void WriteDouble(double myData) {


      byte[] b = BitConverter.GetBytes(myData);


      // GetBytes is a binary representation of a double data type.


      s.Write(b, 0, b.Length);


   } 


   public void Close() {


      s.Close();


   }


}

在本示例中,您创建了一个具有构造函数的类,该构造函数带有流参数。从这里,您可以公开任何需要的 ** Write ** 方法。您必须将编写的所有内容都转换为 byte[]。在您获得 byte[] 之后, Write 方法将其写入流。

异步文件 I/O

同步 I/O 意味着在 I/O 操作完成之前,方法被阻塞,I/O 操作完成后,方法返回其数据。使用异步 I/O,用户可以调用 BeginRead 或 BeginWrite。主线程可以继续进行其他工作,稍后,用户将能够处理数据。另外,多个 I/O 请求可以被同时挂起。

要在此数据可用时得到通知,您可以调用 EndRead 或 EndWrite,传入与您发出的 I/O 请求对应的 IAsyncResult。您还可以提供回调方法,该回调方法应调用 EndReadEndWrite 以计算出读取或写入了多少字节。当许多 I/O 请求被同时挂起时,异步 I/O 可以提供较好的性能,但通常要求对您的应用程序进行一些重要的调整以使其正常工作。

Stream 类支持在同一个流上混合使用同步和异步读取及写入,而不管操作系统是否允许。 Stream 根据其同步实现提供默认的异步读取和写入操作的实现,而根据其异步实现提供默认的同步读取和写入操作的实现。

当实现 ** Stream ** 的派生类时,必须为同步或异步 Read 和 Write 方法之一提供实现。虽然允许重写 ReadWrite ,并且异步方法( BeginReadEndReadBeginWriteEndWrite )的默认实现将和同步方法的实现一起工作,但这不能提供最有效的性能。与之相似,如果您提供了一个异步方法的实现,同步 ReadWrite 方法也将正常工作,但是,如果您专门实现同步方法,性能通常会更好。ReadByte 和 WriteByte 的默认实现调用带有一个元素字节数组的同步 ReadWrite 方法。当从 Stream 派生类时,如果有内部字节缓冲区,强烈建议重写这些方法以访问内部缓冲区,这样性能将得到显著提高。

连接到后备存储器的流重写同步或异步 ** Read ** 和 Write 方法之一,以获取默认情况下另一种方法的功能。如果流不支持异步或同步操作,实施者只需让适当的方法引发异常即可。

下面的示例是一个假设的批量图像处理器的异步实现,其后是同步实现的示例。本代码用于在目录中的每个文件上执行耗费 CPU 资源的操作。有关更多信息,请参阅 .NET 框架开发人员规范中的“.NET 异步编程模型”主题。

[C#]


using System;


using System.IO;


using System.Threading;


using System.Runtime.InteropServices;


 


public class BulkImageProcAsync


{


public const String ImageBaseName = "tmpImage-";


public const int numImages = 200;


public const int numPixels = 512*512;


 


// ProcessImage has a simple O(N) loop, and you can vary the number


// of times you repeat that loop to make the application more CPU-bound


// or more IO-bound.


public static int processImageRepeats = 20;


 


// Threads must decrement NumImagesToFinish, and protect


// their access to it through a mutex.


public static int NumImagesToFinish = numImages;


public static Object NumImagesMutex = new Object[0];


// WaitObject is signalled when all image processing is done.


public static Object WaitObject = new Object[0];


public class ImageStateObject


{


public byte[] pixels;


public int imageNum;


public FileStream fs;


}


 


public static void MakeImageFiles()


{


int sides = (int) Math.Sqrt(numPixels);


Console.Write("Making "+numImages+" "+sides+"x"+sides+" images...  ");


byte[] pixels = new byte[numPixels];


for(int i=0; i
  1<numpixels; !="numPixels)" ");="" "+(asyncresult.completedsynchronously="" "+bytesread);="" "+imagenum);="" "+imagenum+"="" "+state.imagenum+"="" "asynchronously"));="" "synchronously"="" (bytesread="" (numimagesmutex)="" (numimagestofinish="" +="1;" 0,="" 1,="" 4096,="" 8192,="" :="" ?="" a="" all="" an="" appears="" application="" are="" as="" asynccallback="" asynccallback(readinimagecallback);="" asynchronous="" asyncresult)="" asyncresult.asyncobject;="" asyncresult.asyncstate;="" be="" being="" best="" block="" blocked="" bool="" buffer="" byte[numpixels];="" bytes="" bytesread="stream.EndRead(asyncResult);" can="" console.writeline("done.");="" console.writeline("image="" console.writeline("processimage="" console.writeline("processing="" cpu-intensive="" determine="" do="" done="" done.");="" ends="" especially="" exception("in="" false);="" file="" fileaccess.read,="" fileaccess.write,="" filemode.create,="" filemode.open,="" fileshare.none,="" fileshare.read,="" filestream="" filestream(imagebasename+i+".tmp",="" filestream(imagebasename+state.imagenum+".done",="" finished.="" flushfilebuffers(fs.handle);="" for(int="" from="" fs="new" fs.beginread(state.pixels,="" fs.close();="" fs.write(pixels,="" fs.write(state.pixels,="" global="" good="" got="" got:="" here="" i="0;" i++)="" i;="" i<numimages;="" i<processimagerepeats;="" idea,="" if="" image="" image!="" image.="" imagenum)="" images="" images...="" imagestateobject="" imagestateobject();="" int="" io="" is="" it="" items="" j="0;" j++)="" j<numpixels;="" just="" large="" lock="" lock(numimagesmutex)="" long="" make="" memory="" memory.="" model="" monitor.enter(waitobject);="" monitor.exit(waitobject);="" monitor.pulse(waitobject);="" much="" mustblock="false;" new="" not="" not,="" now="" now.="" number="" numimagestofinish="numImages;" numimagestofinish--;="" numpixels);="" numpixels,="" of="" on="" once,="" only="" operation="" out="" pixels,="" pixels.length);="" pixels[i]="(byte)" pixels[j]="" possible="" practice.="" processed.="" processimage(byte[]="" processimage(state.pixels,="" processimagesinbulk()="" public="" queued="" read="" readimagecallback="new" readimagecallback,="" readinimagecallback(iasyncresult="" readinimagecallback,="" record="" releasing="" requests="" save="" since="" small="" so="" some="" soon="" state="new" state);="" state.="" state.fs="fs;" state.imagenum="i;" state.imagenum);="" state.pixels="new" static="" stream="" stream.close();="" swamping="" t0="Environment.TickCount;" that="" the="" this="" threadpool="" threadpool,="" threadpool.="" threads="" throw="" to="" too="" true);="" until="" up="" uses="" using="" very="" void="" was="" we've="" whether="" write="" wrong="" you="" {="" }=""> 0)
  2    
  3    
  4          mustBlock = true;
  5    
  6    
  7    }
  8    
  9    
 10       if (mustBlock) 
 11    
 12    
 13    {
 14    
 15    
 16    Console.WriteLine("All worker threads are queued... Blocking until they 
 17    
 18    
 19       complete.  numLeft: "+NumImagesToFinish);
 20    
 21    
 22    Monitor.Enter(WaitObject);
 23    
 24    
 25    Monitor.Wait(WaitObject);
 26    
 27    
 28    Monitor.Exit(WaitObject);
 29    
 30    
 31    }
 32    
 33    
 34     
 35    
 36    
 37    long t1 = Environment.TickCount;
 38    
 39    
 40    Console.WriteLine("Total time processing images: {0} ms", (t1-t0));
 41    
 42    
 43    }
 44    
 45    
 46     
 47    
 48    
 49    public static void Cleanup()
 50    
 51    
 52    {
 53    
 54    
 55       for(int i=0; i&lt;numImages; i++) 
 56    
 57    
 58       {
 59    
 60    
 61          File.Delete(ImageBaseName+i+".tmp");
 62    
 63    
 64          File.Delete(ImageBaseName+i+".done");
 65    
 66    
 67       }
 68    
 69    
 70    }
 71    
 72    
 73     
 74    
 75    
 76    public static void TryToClearDiskCache()
 77    
 78    
 79    {
 80    
 81    
 82    // Try to force all pending writes to disk, and  clear the
 83    
 84    
 85    // disk cache of any data.
 86    
 87    
 88    byte[] bytes = new byte[100*(1&lt;&lt;20)];
 89    
 90    
 91    for(int i=0; i&lt;bytes.Length; i++)
 92    
 93    
 94    bytes[i] = 0;
 95    
 96    
 97    bytes = null;
 98    
 99    
100    GC.Collect();
101    
102    
103    Thread.Sleep(2000);
104    
105    
106    }
107    
108    
109     
110    
111    
112       public static void Main(String[] args)
113    
114    
115       {
116    
117    
118          Console.WriteLine("Bulk image processing sample application, using 
119    
120    
121             async IO");
122    
123    
124          Console.WriteLine("Simulates applying a simple transformation to 
125    
126    
127             "+numImages+" \"images\"");
128    
129    
130          Console.WriteLine("(ie, Async FileStream &amp; Threadpool benchmark)");
131    
132    
133          Console.WriteLine("Warning - this test requires "+(numPixels * 
134    
135    
136             numImages * 2)+" bytes of tmp space");
137    
138    
139     
140    
141    
142          if (args.Length==1) 
143    
144    
145          {
146    
147    
148             processImageRepeats = Int32.Parse(args[0]);
149    
150    
151             Console.WriteLine("ProcessImage inner loop - 
152    
153    
154                "+processImageRepeats);
155    
156    
157          }
158    
159    
160     
161    
162    
163          MakeImageFiles();
164    
165    
166          TryToClearDiskCache();
167    
168    
169          ProcessImagesInBulk();
170    
171    
172          Cleanup();
173    
174    
175       }
176    
177    
178       [DllImport("KERNEL32", SetLastError=true)]
179    
180    
181       private static extern void FlushFileBuffers(IntPtr handle);
182    
183    
184    }
185
186  
187
188
189以下是同一假设的同步示例。 
190    
191    
192    [C#]
193    
194    
195    using System;
196    
197    
198    using System.IO;
199    
200    
201    using System.Threading;
202    
203    
204    using System.Runtime.InteropServices;
205    
206    
207     
208    
209    
210    public class BulkImageProcSync
211    
212    
213    {
214    
215    
216    public const String ImageBaseName = "tmpImage-";
217    
218    
219    public const int numImages = 200;
220    
221    
222    public const int numPixels = 512*512;
223    
224    
225     
226    
227    
228    // ProcessImage has a simple O(N) loop, and you can vary the number
229    
230    
231    // of times you repeat that loop to make the application more CPU-bound or
232    
233    
234    // more IO-bound.
235    
236    
237    public static int processImageRepeats = 20;
238    
239    
240     
241    
242    
243    public static void MakeImageFiles()
244    
245    
246    {
247    
248    
249    int sides = (int) Math.Sqrt(numPixels);
250    
251    
252    Console.Write("Making "+numImages+" "+sides+"x"+sides+" images...  ");
253    
254    
255    byte[] pixels = new byte[numPixels];
256    
257    
258    for(int i=0; i&lt;numPixels; i++)
259    
260    
261    pixels[i] = (byte) i;
262    
263    
264     
265    
266    
267    for(int i=0; i&lt;numImages; i++) {
268    
269    
270    FileStream fs = new FileStream(ImageBaseName+i+".tmp", FileMode.Create, FileAccess.Write, FileShare.None, 8192, false);
271    
272    
273    fs.Write(pixels, 0, pixels.Length);
274    
275    
276    FlushFileBuffers(fs.Handle);
277    
278    
279    fs.Close();
280    
281    
282    }
283    
284    
285    Console.WriteLine("Done.");
286    
287    
288    }
289    
290    
291     
292    
293    
294    public static void ProcessImage(byte[] pixels, int imageNum)
295    
296    
297    {
298    
299    
300    Console.WriteLine("ProcessImage "+imageNum);
301    
302    
303     
304    
305    
306    // Do some CPU-intensive operation on the image
307    
308    
309    for(int i=0; i&lt;processImageRepeats; i++)
310    
311    
312    for(int j=0; j&lt;numPixels; j++)
313    
314    
315    pixels[j] += 1;
316    
317    
318     
319    
320    
321    Console.WriteLine("ProcessImage "+imageNum+" done.");
322    
323    
324    }
325    
326    
327     
328    
329    
330    public static void ProcessImagesInBulk()
331    
332    
333    {
334    
335    
336    Console.WriteLine("Processing images...  ");
337    
338    
339    long t0 = Environment.TickCount;
340    
341    
342     
343    
344    
345    byte[] pixels = new byte[numPixels];
346    
347    
348    for(int i=0; i&lt;numImages; i++) 
349    
350    
351    {
352    
353    
354    FileStream input = new FileStream(ImageBaseName+i+".tmp", FileMode.Open,
355    
356    
357       FileAccess.Read, FileShare.Read, 4196, false);
358    
359    
360    input.Read(pixels, 0, numPixels);
361    
362    
363    input.Close();
364    
365    
366    ProcessImage(pixels, i);
367    
368    
369    FileStream output = new FileStream(ImageBaseName+i+".done", 
370    
371    
372       FileMode.Create, FileAccess.Write, FileShare.None, 4196, false);
373    
374    
375    output.Write(pixels, 0, numPixels);
376    
377    
378    output.Close();
379    
380    
381    }
382    
383    
384     
385    
386    
387    long t1 = Environment.TickCount;
388    
389    
390    Console.WriteLine("Total time processing images: {0} ms", (t1-t0));
391    
392    
393    }
394    
395    
396     
397    
398    
399    public static void Cleanup()
400    
401    
402    {
403    
404    
405       for(int i=0; i&lt;numImages; i++) 
406    
407    
408       {
409    
410    
411          File.Delete(ImageBaseName+i+".tmp");
412    
413    
414          File.Delete(ImageBaseName+i+".done");
415    
416    
417       }
418    
419    
420    }
421    
422    
423     
424    
425    
426    public static void TryToClearDiskCache()
427    
428    
429    {
430    
431    
432    byte[] bytes = new byte[100*(1&lt;&lt;20)];
433    
434    
435    for(int i=0; i&lt;bytes.Length; i++)
436    
437    
438    bytes[i] = 0;
439    
440    
441    bytes = null;
442    
443    
444    GC.Collect();
445    
446    
447    Thread.Sleep(2000);
448    
449    
450    }
451    
452    
453     
454    
455    
456    public static void Main(String[] args)
457    
458    
459    {
460    
461    
462    Console.WriteLine("Bulk image processing sample application, using synchronous IO");
463    
464    
465    Console.WriteLine("Simulates applying a simple transformation to "+numImages+" \"images\"");
466    
467    
468    Console.WriteLine("(ie, Sync FileStream benchmark)");
469    
470    
471    Console.WriteLine("Warning - this test requires "+(numPixels * numImages * 2)+" bytes of tmp space");
472    
473    
474     
475    
476    
477    if (args.Length==1) {
478    
479    
480    processImageRepeats = Int32.Parse(args[0]);
481    
482    
483    Console.WriteLine("ProcessImage inner loop - "+processImageRepeats);
484    
485    
486    }
487    
488    
489     
490    
491    
492    MakeImageFiles();
493    
494    
495    TryToClearDiskCache();
496    
497    
498    ProcessImagesInBulk();
499    
500    
501    Cleanup();
502    
503    
504    &lt;FONT face=宋体</numpixels;>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus