jjccx

jjccx's blog
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C# 3.0 in a Nutshell - Code Listings(转)

Posted on 2008-07-15 22:20  jjccx  阅读(585)  评论(0)    收藏  举报

转自http://www.albahari.com/nutshell/ch13.html

Chapter 13: Streams and I/O

 

Basic use of a stream:

using System;

using System.IO;

 

class Program

{

  static void Main()

  {

    // Create a file called test.txt in the current directory:

    using (Stream s = new FileStream ("test.txt", FileMode.Create))

    {

      Console.WriteLine (s.CanRead);       // true

      Console.WriteLine (s.CanWrite);      // true

      Console.WriteLine (s.CanSeek);       // true

 

      s.WriteByte (101);

      s.WriteByte (102);

      byte[] block = { 1, 2, 3, 4, 5 };

      s.Write (block, 0, block.Length);     // Write block of 5 bytes

 

      Console.WriteLine (s.Length);         // 7

      Console.WriteLine (s.Position);       // 7

      s.Position = 0;                       // Move back to the start

 

      Console.WriteLine (s.ReadByte());     // 101

      Console.WriteLine (s.ReadByte());     // 102

 

      // Read from the stream back into the block array:

      Console.WriteLine (s.Read (block, 0, block.Length));   // 5

 

      // Assuming the last Read returned 5, we'll be at

      // the end of the file, so Read will now return 0:

      Console.WriteLine (s.Read (block, 0, block.Length));   // 0

    }

  }

}

Reading a 1000 bytes from a stream:

byte[] data = new byte [1000];

 

// bytesRead will always end up at 1000, unless the stream is

// itself smaller in length:

 

int bytesRead = 0;

int chunkSize = 1;

while (bytesRead < data.Length && chunkSize > 0)

  bytesRead +=

    chunkSize = s.Read (data, bytesRead, data.Length - bytesRead);

An easier way:

byte[] data = new BinaryReader (s).ReadBytes (1000);

Reading into a MemoryStream:

static MemoryStream ToMemoryStream (Stream input, bool closeInput)

{

  try

  {                                         // Read and write in

    byte[] block = new byte [0x1000];       // blocks of 4K.

    MemoryStream ms = new MemoryStream();

    while (true)

    {

      int bytesRead = input.Read (block, 0, block.Length);

      if (bytesRead == 0) return ms;

      ms.Write (block, 0, bytesRead);

    }

  }

  finally { if (closeInput) input.Close(); }

}

Named pipes:

// Server:

using (var s = new NamedPipeServerStream ("pipedream")

{

  s.WaitForConnection();

  s.WriteByte (100);

  Console.WriteLine (s.ReadByte());

}

// Client:

using (var s = new NamedPipeClientStream ("pipedream"))

{

  s.Connect();

  Console.WriteLine (s.ReadByte());

  s.WriteByte (200);                 // Send the value 200 back.

}

Message transmission mode:

static byte[] ReadMessage (PipeStream s)

{

  MemoryStream ms = new MemoryStream();

  byte[] buffer = new byte [0x1000];      // Read in 4KB blocks

 

  do    { ms.Write (buffer, 0, s.Read (buffer, 0, buffer.Length)); }

  while (!s.IsMessageComplete);

 

  return ms.ToArray();

}

// Server:

using (var s = new NamedPipeServerStream ("pipedream", PipeDirection.InOut,

                                          1, PipeTransmissionMode.Message))

{

  s.WaitForConnection();

 

  byte[] msg = Encoding.UTF8.GetBytes ("Hello");

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

 

  Console.WriteLine (Encoding.UTF8.GetString (ReadMessage (s)));

}

// Client:

using (var s = new NamedPipeClientStream ("pipedream"))

{

  s.Connect();

  s.ReadMode = PipeTransmissionMode.Message;

 

  Console.WriteLine (Encoding.UTF8.GetString (ReadMessage (s)));

 

  byte[] msg = Encoding.UTF8.GetBytes ("Hello right back!");

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

}

Anonymous pipes server:

string clientExe = "d:\PipeDemo\ClientDemo.exe";

 

HandleInheritability inherit = HandleInheritability.Inheritable;

 

using (var tx = new AnonymousPipeServerStream (PipeDirection.Out, inherit))

using (var rx = new AnonymousPipeServerStream (PipeDirection.In, inherit))

{

  string txID = tx.GetClientHandleAsString();

  string rxID = rx.GetClientHandleAsString();

 

  var startInfo = new ProcessStartInfo (clientExe, txID + " " + rxID);

  startInfo.UseShellExecute = false;    // Required for child process

  Process p = Process.Start (startInfo);

 

  tx.DisposeLocalCopyOfClientHandle();    // Release unmanaged

  rx.DisposeLocalCopyOfClientHandle();    // handle resources.

 

  tx.WriteByte (100);

  Console.WriteLine ("Server received: " + rx.ReadByte());

 

  p.WaitForExit();

}

Anonymous pipes client:

static void Main (string[] args)

{

  string rxID = args[0];    // Note we’re reversing the

  string txID = args[1];    // receive and transmit roles.

 

  using (var rx = new AnonymousPipeClientStream (PipeDirection.In, rxID))

  using (var tx = new AnonymousPipeClientStream (PipeDirection.Out, txID))

  {

    Console.WriteLine ("Client received: " + rx.ReadByte());

    tx.WriteByte (200);

  }

}

BufferedStream:

// Write 100K to a file:

File.WriteAllBytes ("myFile.bin", new byte [100000]);

 

using (FileStream fs = File.OpenRead ("myFile.bin"))

using (BufferedStream bs = new BufferedStream (fs, 20000))  //20K buffer

{

  bs.ReadByte();

  Console.WriteLine (fs.Position);         // 20000

}

StreamReader and StreamWriter:

using (FileStream fs = File.Create ("test.txt"))

using (TextWriter writer = new StreamWriter (fs))

{

  writer.WriteLine ("Line1");

  writer.WriteLine ("Line2");

}

 

using (FileStream fs = File.OpenRead ("test.txt"))

using (TextReader reader = new StreamReader (fs))

{

  Console.WriteLine (reader.ReadLine());       // Line1

  Console.WriteLine (reader.ReadLine());       // Line2

}

using (TextWriter writer = File.CreateText ("test.txt"))

{

  writer.WriteLine ("Line1");

  writer.WriteLine ("Line2");

}

using (TextWriter writer = File.AppendText ("test.txt"))

  writer.WriteLine ("Line3");

 

using (TextReader reader = File.OpenText ("test.txt"))

  while (reader.Peek() > -1)

    Console.WriteLine (reader.ReadLine());     // Line1

                                               // Line2

                                               // Line3

using (TextWriter w = File.CreateText ("data.txt"))

{

  w.WriteLine (123);          // Writes "123"

  w.WriteLine (true);         // Writes the word "true"

}

using (TextReader r = File.OpenText ("data.txt"))

{

  int myInt = int.Parse (r.ReadLine());     // myInt == 123

  bool yes = bool.Parse (r.ReadLine());     // yes == true

}

Character encodings:

using (TextWriter w = File.CreateText ("but.txt"))    // Use default UTF-8

  w.WriteLine ("but—");                               // encoding.

 

using (Stream s = File.OpenRead ("but.txt"))

  for (int b; (b = s.ReadByte()) > -1;)

    Console.WriteLine (b);

using (Stream s = File.Create ("but.txt"))

using (TextWriter w = new StreamWriter (s, Encoding.Unicode))

  w.WriteLine ("but—");

 

foreach (byte b in File.ReadAllBytes ("but.txt"))

  Console.WriteLine (b);

Binary adapaters:

public class Person

{

  public string Name;

  public int    Age;

  public double Height;

 

  public void SaveData (Stream s)

  {

    BinaryWriter w = new BinaryWriter (s);

    w.Write (Name);

    w.Write (Age);

    w.Write (Height);

    w.Flush();         // Ensure the BinaryWriter buffer is cleared.

                       // We won't dispose/close it, so more data

  }                    // can to be written to the stream.

 

  public void LoadData (Stream s)

  {

    BinaryReader r = new BinaryReader (s);

    Name   = r.ReadString();

    Age    = r.ReadInt32();

    Height = r.ReadDouble();

  }

}

Compressing a directory:

static uint CompressFolder (string folder, bool recursive)

{

  string path = "Win32_Directory.Name='" + folder + "'";

  using (ManagementObject dir = new ManagementObject (path))

  using (ManagementBaseObject p = dir.GetMethodParameters ("CompressEx"))

  {

    p ["Recursive"] = recursive;

    using (ManagementBaseObject result = dir.InvokeMethod ("CompressEx",

                                                             p, null))

      return (uint) result.Properties ["ReturnValue"].Value;

  }

}

Determining if a volume supports compression & encryption:

using System;

using System.IO;

using System.Text;

using System.Runtime.InteropServices;

 

class SupportsCompressionEncryption

{

  const int SupportsCompression = 0x10;

  const int SupportsEncryption = 0x20000;

 

  [DllImport ("Kernel32.dll", SetLastError = true)]

  extern static bool GetVolumeInformation (string vol, StringBuilder name,

    int nameSize, out uint serialNum, out uint maxNameLen, out uint flags,

    StringBuilder fileSysName, int fileSysNameSize);

 

  static void Main()

  {

    uint serialNum, maxNameLen, flags;

    bool ok = GetVolumeInformation (@"C:\", null, 0, out serialNum,

                                    out maxNameLen, out flags, null, 0);

    if (!ok)

      throw new Exception

        ("Error: Win32 code=" + Marshal.GetLastWin32Error());

 

    bool canCompress = (flags & SupportsCompression) > 0;

    bool canEncrypt = (flags & SupportsEncryption) > 0;

  }

}

File security:

using System;

using System.IO;

using System.Security.AccessControl;

using System.Security.Principal;

 

public static void Main()

{

  FileSecurity sec = File.GetAccessControl (@"c:\temp\test.txt");

  AuthorizationRuleCollection rules = sec.GetAccessRules (true, true,

                                                       typeof (NTAccount));

  foreach (FileSystemAccessRule rule in rules)

  {

    Console.WriteLine (rule.AccessControlType);         // Allow or Deny

    Console.WriteLine (rule.FileSystemRights);          // e.g. FullControl

    Console.WriteLine (rule.IdentityReference.Value);   // e.g. MyDomain/Joe

  }

 

  FileSystemAccessRule newRule = new FileSystemAccessRule

    ("Users", FileSystemRights.ExecuteFile, AccessControlType.Allow);

  sec.AddAccessRule (newRule);

  File.SetAccessControl (@"c:\temp\test.txt", sec);

}

FileInfo and DirectoryInfo:

FileInfo fi = new FileInfo (@"c:\temp\FileInfo.txt");

Console.WriteLine (fi.Exists);         // false

 

using (TextWriter w = fi.CreateText())

  w.Write ("Some text");

 

Console.WriteLine (fi.Exists);         // false (still)

fi.Refresh();

Console.WriteLine (fi.Exists);         // true

 

Console.WriteLine (fi.Name);           // FileInfo.txt

Console.WriteLine (fi.FullName);       // c:\temp\FileInfo.txt

Console.WriteLine (fi.DirectoryName);  // c:\temp

Console.WriteLine (fi.Directory.Name); // temp

Console.WriteLine (fi.Extension);      // .txt

Console.WriteLine (fi.Length);         // 9

 

fi.Encrypt();

fi.Attributes ^= FileAttributes.Hidden;   // (Toggle hidden flag)

fi.IsReadOnly = true;

 

Console.WriteLine (fi.Attributes);    // ReadOnly,Archive,Hidden,Encrypted

Console.WriteLine (fi.CreationTime);

 

fi.MoveTo (@"c:\temp\FileInfoX.txt");

 

DirectoryInfo di = fi.Directory;

Console.WriteLine (di.Name);             // temp

Console.WriteLine (di.FullName);         // c:\temp

Console.WriteLine (di.Parent.FullName);  // c:\

di.CreateSubdirectory ("SubFolder");

Enumerating files and subdirectories:

DirectoryInfo di = new DirectoryInfo (@"e:\photos");

 

foreach (FileInfo fi in di.GetFiles ("*.jpg"))

  Console.WriteLine (fi.Name);

 

foreach (DirectoryInfo subDir in di.GetDirectories())

  Console.WriteLine (subDir.FullName);

Querying volume information:

DriveInfo c = new DriveInfo ("C");       // Query the C: drive.

 

long totalSize = c.TotalSize;            // Size in bytes.

long freeBytes = c.TotalFreeSpace;       // Ignores disk quotas.

long freeToMe  = c.AvailableFreeSpace;   // Takes quotas into account.

 

foreach (DriveInfo d in DriveInfo.GetDrives())    // All defined drives.

{

  Console.WriteLine (d.Name);             // C:\

  Console.WriteLine (d.DriveType);        // Fixed

  Console.WriteLine (d.RootDirectory);    // C:\

 

  if (d.IsReady)   // If the drive is not ready, the following two

                   // properties will throw exceptions:

  {

    Console.WriteLine (d.VolumeLabel);    // The Sea Drive

    Console.WriteLine (d.DriveFormat);    // NTFS

  }

}

Catching filesystem events:

static void Main() { Watch (@"c:\temp", "*.txt", true); }

 

static void Watch (string path, string filter, bool includeSubDirs)

{

  using (FileSystemWatcher watcher = new FileSystemWatcher (path, filter))

  {

    watcher.Created += FileCreatedChangedDeleted;

    watcher.Changed += FileCreatedChangedDeleted;

    watcher.Deleted += FileCreatedChangedDeleted;

    watcher.Renamed += FileRenamed;

    watcher.Error   += FileError;

 

    watcher.IncludeSubdirectories = includeSubDirs;

    watcher.EnableRaisingEvents = true;

 

    Console.WriteLine ("Listening for events - press <enter> to end");

    Console.ReadLine();

  }

  // Disposing the FileSystemWatcher stops further events from firing.

}

 

static void FileCreatedChangedDeleted (object o, FileSystemEventArgs e)

{

  Console.WriteLine ("File {0} has been {1}", e.FullPath, e.ChangeType);

}

 

static void FileRenamed (object o, RenamedEventArgs e)

{

  Console.WriteLine ("Renamed: {0}->{1}", e.OldFullPath, e.FullPath);

}

 

static void FileError (object o, ErrorEventArgs e)

{

  Console.WriteLine ("Error: " + e.GetException().Message);

}

Compression:

using (Stream s = File.Create ("compressed.bin"))

using (Stream ds = new DeflateStream (s, CompressionMode.Compress))

  for (byte i = 0; i < 100; i++)

    ds.WriteByte (i);

 

using (Stream s = File.OpenRead ("compressed.bin"))

using (Stream ds = new DeflateStream (s, CompressionMode.Decompress))

  for (byte i = 0; i < 100; i++)

    Console.WriteLine (ds.ReadByte());     // Writes 0 to 99

string[] words = "The quick brown fox jumps over the lazy dog".Split();

Random rand = new Random();

 

using (Stream s = File.Create ("compressed.bin"))

using (Stream ds = new DeflateStream (s, CompressionMode.Compress))

using (TextWriter w = new StreamWriter (ds))

  for (int i = 0; i < 1000; i++)

    w.Write (words [rand.Next (words.Length)] + " ");

 

Console.WriteLine (new FileInfo ("compressed.bin").Length);      // 1073

 

using (Stream s = File.OpenRead ("compressed.bin"))

using (Stream ds = new DeflateStream (s, CompressionMode.Decompress))

using (TextReader r = new StreamReader (ds))

  Console.Write (r.ReadToEnd());                 // Output below:

Compressing in memory, option 1:

byte[] data = new byte[1000];          // We can expect a good compression

                                       // ratio from an empty array!

MemoryStream ms = new MemoryStream();

using (Stream ds = new DeflateStream (ms, CompressionMode.Compress))

  ds.Write (data, 0, data.Length);

 

byte[] compressed = ms.ToArray();

Console.WriteLine (compressed.Length);       // 113

 

// Decompress back to the data array:

ms = new MemoryStream (compressed);

using (Stream ds = new DeflateStream (ms, CompressionMode.Decompress))

  for (int i = 0; i < 1000; i += ds.Read (data, i, 1000 - i));

Compressing in memory, option 2:

byte[] data = new byte[1000];

 

MemoryStream ms = new MemoryStream();

using (Stream ds = new DeflateStream (ms, CompressionMode.Compress, true))

  ds.Write (data, 0, data.Length);

 

Console.WriteLine (ms.Length);             // 113

ms.Position = 0;

using (Stream ds = new DeflateStream (ms, CompressionMode.Decompress))

  for (int i = 0; i < 1000; i += ds.Read (data, i, 1000 - i));

Reading and writing isolated storage:

// IsolatedStorage classes live in System.IO.IsolatedStorage

 

using (IsolatedStorageFile f =

       IsolatedStorageFile.GetMachineStoreForDomain())

using (var s = new IsolatedStorageFileStream ("hi.txt",FileMode.Create,f))

using (var writer = new StreamWriter (s))

  writer.WriteLine ("Hello, World");

 

// Read it back:

 

using (IsolatedStorageFile f =

       IsolatedStorageFile.GetMachineStoreForDomain())

using (var s = new IsolatedStorageFileStream ("hi.txt", FileMode.Open, f))

using (var reader = new StreamReader (s))

  Console.WriteLine (reader.ReadToEnd());        // Hello, world

Roaming user isolation:

var flags = IsolatedStorageScope.Assembly

          | IsolatedStorageScope.User

          | IsolatedStorageScope.Roaming;

 

using (IsolatedStorageFile f = IsolatedStorageFile.GetStore (flags,

                                                             null, null))

using (var s = new IsolatedStorageFileStream ("a.txt", FileMode.Create, f))

using (var writer = new StreamWriter (s))

  writer.WriteLine ("Hello, World");

Enumerating isolated storage:

using (IsolatedStorageFile f = IsolatedStorageFile.GetUserStoreForDomain())

{

  using (var s = new IsolatedStorageFileStream ("f1.x",FileMode.Create,f))

    s.WriteByte (123);

 

  using (var s = new IsolatedStorageFileStream ("f2.x",FileMode.Create,f))

    s.WriteByte (123);

 

  foreach (string s in f.GetFileNames ("*.*"))

    Console.Write (s + " ");                   // f1.x f2.x

}

Creating and removing subdirectories:

using (IsolatedStorageFile f = IsolatedStorageFile.GetUserStoreForDomain())

{

  f.CreateDirectory ("subfolder");

 

  foreach (string s in f.GetDirectoryNames ("*.*"))

    Console.WriteLine (s);                             // subfolder

 

  using (var s = new IsolatedStorageFileStream (@"subfolder\sub1.txt",

                                                 FileMode.Create, f))

    s.WriteByte (100);

 

  f.DeleteFile (@"subfolder\sub1.txt");

  f.DeleteDirectory ("subfolder");

}

Enumerating over other applications' stores:

System.Collections.IEnumerator rator =

  IsolatedStorageFile.GetEnumerator (IsolatedStorageScope.User);

 

while (rator.MoveNext())

{

  var isf = (IsolatedStorageFile) rator.Current;

 

  Console.WriteLine (isf.AssemblyIdentity);      // Strong name or URI

  Console.WriteLine (isf.CurrentSize);

  Console.WriteLine (isf.Scope);                 // User + ...

}