달력

4

« 2025/4 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2017. 3. 29. 13:02

Events 프로그래밍/C#2017. 3. 29. 13:02


  1. Handling and Raising Events
  2. How to: Raise and Consume Events
  3. How to: Handle Multiple Events Using Event Properties


https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx




Handling and Raising Events


Events in the .NET Framework are based on the delegate model. The delegate model follows the observer design pattern, which enables a subscriber to register with, and receive notifications from, a provider. An event sender pushes a notification that an event has happened, and an event receiver receives that notification and defines a response to it. This article describes the major components of the delegate model, how to consume events in applications, and how to implement events in your code.

For information about handling events in Windows 8.x Store apps, see Events and routed events overview (Windows store apps).

An event is a message sent by an object to signal the occurrence of an action. The action could be caused by user interaction, such as a button click, or it could be raised by some other program logic, such as changing a property’s value. The object that raises the event is called the event sender. The event sender doesn't know which object or method will receive (handle) the events it raises. The event is typically a member of the event sender; for example, the Click event is a member of the Button class, and the PropertyChanged event is a member of the class that implements the INotifyPropertyChanged interface.

To define an event, you use the event (in C#) or Event (in Visual Basic) keyword in the signature of your event class, and specify the type of delegate for the event. Delegates are described in the next section.

Typically, to raise an event, you add a method that is marked as protected and virtual (in C#) or Protected and Overridable (in Visual Basic). Name this method OnEventName; for example, OnDataReceived. The method should take one parameter that specifies an event data object. You provide this method to enable derived classes to override the logic for raising the event. A derived class should always call the OnEventName method of the base class to ensure that registered delegates receive the event.

The following example shows how to declare an event named ThresholdReached. The event is associated with the EventHandler delegate and raised in a method named OnThresholdReached.

    class Counter
    {
        public event EventHandler ThresholdReached;

        protected virtual void OnThresholdReached(EventArgs e)
        {
            EventHandler handler = ThresholdReached;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        // provide remaining implementation for the class
    }

A delegate is a type that holds a reference to a method. A delegate is declared with a signature that shows the return type and parameters for the methods it references, and can hold references only to methods that match its signature. A delegate is thus equivalent to a type-safe function pointer or a callback. A delegate declaration is sufficient to define a delegate class.

Delegates have many uses in the .NET Framework. In the context of events, a delegate is an intermediary (or pointer-like mechanism) between the event source and the code that handles the event. You associate a delegate with an event by including the delegate type in the event declaration, as shown in the example in the previous section. For more information about delegates, see the Delegate class.

The .NET Framework provides the EventHandler and EventHandler<TEventArgs> delegates to support most event scenarios. Use the EventHandler delegate for all events that do not include event data. Use the EventHandler<TEventArgs> delegate for events that include data about the event. These delegates have no return type value and take two parameters (an object for the source of the event and an object for event data).

Delegates are multicast, which means that they can hold references to more than one event-handling method. For details, see the Delegate reference page. Delegates provide flexibility and fine-grained control in event handling. A delegate acts as an event dispatcher for the class that raises the event by maintaining a list of registered event handlers for the event.

For scenarios where the EventHandler and EventHandler<TEventArgs> delegates do not work, you can define a delegate. Scenarios that require you to define a delegate are very rare, such as when you must work with code that does not recognize generics. You mark a delegate with the delegate in (C#) and Delegate (in Visual Basic) keyword in the declaration. The following example shows how to declare a delegate named ThresholdReachedEventHandler.

    public delegate void ThresholdReachedEventHandler(ThresholdReachedEventArgs e);

Data that is associated with an event can be provided through an event data class. The .NET Framework provides many event data classes that you can use in your applications. For example, the SerialDataReceivedEventArgs class is the event data class for the SerialPort.DataReceived event. The .NET Framework follows a naming pattern of ending all event data classes with EventArgs. You determine which event data class is associated with an event by looking at the delegate for the event. For example, the SerialDataReceivedEventHandler delegate includes the SerialDataReceivedEventArgs class as one of its parameters.

The EventArgs class is the base type for all event data classes. EventArgs is also the class you use when an event does not have any data associated with it. When you create an event that is only meant to notify other classes that something happened and does not need to pass any data, include the EventArgs class as the second parameter in the delegate. You can pass the EventArgs.Empty value when no data is provided. The EventHandler delegate includes the EventArgs class as a parameter.

When you want to create a customized event data class, create a class that derives from EventArgs, and then provide any members needed to pass data that is related to the event. Typically, you should use the same naming pattern as the .NET Framework and end your event data class name with EventArgs.

The following example shows an event data class named ThresholdReachedEventArgs. It contains properties that are specific to the event being raised.

    public class ThresholdReachedEventArgs : EventArgs
    {
        public int Threshold { get; set; }
        public DateTime TimeReached { get; set; }
    }

To respond to an event, you define an event handler method in the event receiver. This method must match the signature of the delegate for the event you are handling. In the event handler, you perform the actions that are required when the event is raised, such as collecting user input after the user clicks a button. To receive notifications when the event occurs, your event handler method must subscribe to the event.

The following example shows an event handler method named c_ThresholdReached that matches the signature for the EventHandler delegate. The method subscribes to the ThresholdReached event.

    class Program
    {
        static void Main(string[] args)
        {
            Counter c = new Counter();
            c.ThresholdReached += c_ThresholdReached;

            // provide remaining implementation for the class
        }

        static void c_ThresholdReached(object sender, EventArgs e)
        {
            Console.WriteLine("The threshold was reached.");
        }
    }

The .NET Framework allows subscribers to register for event notifications either statically or dynamically. Static event handlers are in effect for the entire life of the class whose events they handle. Dynamic event handlers are explicitly activated and deactivated during program execution, usually in response to some conditional program logic. For example, they can be used if event notifications are needed only under certain conditions or if an application provides multiple event handlers and run-time conditions define the appropriate one to use. The example in the previous section shows how to dynamically add an event handler. For more information, see Events and Events.

If your class raises multiple events, the compiler generates one field per event delegate instance. If the number of events is large, the storage cost of one field per delegate may not be acceptable. For those situations, the .NET Framework provides event properties that you can use with another data structure of your choice to store event delegates.

Event properties consist of event declarations accompanied by event accessors. Event accessors are methods that you define to add or remove event delegate instances from the storage data structure. Note that event properties are slower than event fields, because each event delegate must be retrieved before it can be invoked. The trade-off is between memory and speed. If your class defines many events that are infrequently raised, you will want to implement event properties. For more information, see How to: Handle Multiple Events Using Event Properties.

TitleDescription
How to: Raise and Consume EventsContains examples of raising and consuming events.
How to: Handle Multiple Events Using Event PropertiesShows how to use event properties to handle multiple events.
Observer Design PatternDescribes the design pattern that enables a subscriber to register with, and receive notifications from, a provider.
How to: Consume Events in a Web Forms ApplicationShows how to handle an event that is raised by a Web Forms control.





How to: Raise and Consume Events


The examples in this topic show how to work with events. They include examples of the EventHandler delegate, the EventHandler<TEventArgs> delegate, and a custom delegate, to illustrate events with and without data.

The examples use concepts described in the Events article.

The first example shows how to raise and consume an event that doesn't have data. It contains a class named Counter that has an event named ThresholdReached. This event is raised when a counter value equals or exceeds a threshold value. The EventHandler delegate is associated with the event, because no event data is provided.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Counter c = new Counter(new Random().Next(10));
            c.ThresholdReached += c_ThresholdReached;

            Console.WriteLine("press 'a' key to increase total");
            while (Console.ReadKey(true).KeyChar == 'a')
            {
                Console.WriteLine("adding one");
                c.Add(1);
            }
        }

        static void c_ThresholdReached(object sender, EventArgs e)
        {
            Console.WriteLine("The threshold was reached.");
            Environment.Exit(0); 
        }
    }

    class Counter
    {
        private int threshold;
        private int total;

        public Counter(int passedThreshold)
        {
            threshold = passedThreshold;
        }

        public void Add(int x)
        {
            total += x;
            if (total >= threshold)
            {
                OnThresholdReached(EventArgs.Empty);
            }
        }

        protected virtual void OnThresholdReached(EventArgs e)
        {
            EventHandler handler = ThresholdReached;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        public event EventHandler ThresholdReached;
    }
}

The next example shows how to raise and consume an event that provides data. The EventHandler<TEventArgs> delegate is associated with the event, and an instance of a custom event data object is provided.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Counter c = new Counter(new Random().Next(10));
            c.ThresholdReached += c_ThresholdReached;

            Console.WriteLine("press 'a' key to increase total");
            while (Console.ReadKey(true).KeyChar == 'a')
            {
                Console.WriteLine("adding one");
                c.Add(1);
            }
        }

        static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e)
        {
            Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold,  e.TimeReached);
            Environment.Exit(0);
        }
    }

    class Counter
    {
        private int threshold;
        private int total;

        public Counter(int passedThreshold)
        {
            threshold = passedThreshold;
        }

        public void Add(int x)
        {
            total += x;
            if (total >= threshold)
            {
                ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
                args.Threshold = threshold;
                args.TimeReached = DateTime.Now;
                OnThresholdReached(args);
            }
        }

        protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
        {
            EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
    }

    public class ThresholdReachedEventArgs : EventArgs
    {
        public int Threshold { get; set; }
        public DateTime TimeReached { get; set; }
    }
}

The next example shows how to declare a delegate for an event. The delegate is named ThresholdReachedEventHandler. This is just an illustration. Typically, you do not have to declare a delegate for an event, because you can use either the EventHandler or the EventHandler<TEventArgs> delegate. You should declare a delegate only in rare scenarios, such as making your class available to legacy code that cannot use generics.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Counter c = new Counter(new Random().Next(10));
            c.ThresholdReached += c_ThresholdReached;

            Console.WriteLine("press 'a' key to increase total");
            while (Console.ReadKey(true).KeyChar == 'a')
            {
                Console.WriteLine("adding one");
                c.Add(1);
            }
        }

        static void c_ThresholdReached(Object sender, ThresholdReachedEventArgs e)
        {
            Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached);
            Environment.Exit(0);
        }
    }

    class Counter
    {
        private int threshold;
        private int total;

        public Counter(int passedThreshold)
        {
            threshold = passedThreshold;
        }

        public void Add(int x)
        {
            total += x;
            if (total >= threshold)
            {
                ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
                args.Threshold = threshold;
                args.TimeReached = DateTime.Now;
                OnThresholdReached(args);
            }
        }

        protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
        {
            ThresholdReachedEventHandler handler = ThresholdReached;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        public event ThresholdReachedEventHandler ThresholdReached;
    }

    public class ThresholdReachedEventArgs : EventArgs
    {
        public int Threshold { get; set; }
        public DateTime TimeReached { get; set; }
    }

    public delegate void ThresholdReachedEventHandler(Object sender, ThresholdReachedEventArgs e);
}






How to: Handle Multiple Events Using Event Properties


To use event properties, you define the event properties in the class that raises the events, and then set the delegates for the event properties in classes that handle the events. To implement multiple event properties in a class, the class must internally store and maintain the delegate defined for each event. A typical approach is to implement a delegate collection that is indexed by an event key.

To store the delegates for each event, you can use the EventHandlerList class, or implement your own collection. The collection class must provide methods for setting, accessing, and retrieving the event handler delegate based on the event key. For example, you could use a Hashtable class, or derive a custom class from the DictionaryBase class. The implementation details of the delegate collection do not need to be exposed outside your class.

Each event property within the class defines an add accessor method and a remove accessor method. The add accessor for an event property adds the input delegate instance to the delegate collection. The remove accessor for an event property removes the input delegate instance from the delegate collection. The event property accessors use the predefined key for the event property to add and remove instances from the delegate collection.

To handle multiple events using event properties

  1. Define a delegate collection within the class that raises the events.

  2. Define a key for each event.

  3. Define the event properties in the class that raises the events.

  4. Use the delegate collection to implement the add and remove accessor methods for the event properties.

  5. Use the public event properties to add and remove event handler delegates in the classes that handle the events.

The following C# example implements the event properties MouseDown and MouseUp, using an EventHandlerList to store each event's delegate. The keywords of the event property constructs are in bold type.

System_CAPS_ICON_note.jpg Note

Event properties are not supported in Visual Basic 2005.

// The class SampleControl defines two event properties, MouseUp and MouseDown.
class SampleControl : Component
{
    // :
    // Define other control methods and properties.
    // :

    // Define the delegate collection.
    protected EventHandlerList listEventDelegates = new EventHandlerList();

    // Define a unique key for each event.
    static readonly object mouseDownEventKey = new object();
    static readonly object mouseUpEventKey = new object();

    // Define the MouseDown event property.
    public event MouseEventHandler MouseDown
    {
        // Add the input delegate to the collection.
        add
        {
            listEventDelegates.AddHandler(mouseDownEventKey, value);
        }
        // Remove the input delegate from the collection.
        remove
        {
            listEventDelegates.RemoveHandler(mouseDownEventKey, value);
        }
    }

    // Raise the event with the delegate specified by mouseDownEventKey
    private void OnMouseDown(MouseEventArgs e)
    {
        MouseEventHandler mouseEventDelegate =
            (MouseEventHandler)listEventDelegates[mouseDownEventKey];
        mouseEventDelegate(this, e);
    }

    // Define the MouseUp event property.
    public event MouseEventHandler MouseUp
    {
        // Add the input delegate to the collection.
        add
        {
            listEventDelegates.AddHandler(mouseUpEventKey, value);
        }
        // Remove the input delegate from the collection.
        remove
        {
            listEventDelegates.RemoveHandler(mouseUpEventKey, value);
        }
    }

    // Raise the event with the delegate specified by mouseUpEventKey
    private void OnMouseUp(MouseEventArgs e)
    {
        MouseEventHandler mouseEventDelegate =
            (MouseEventHandler)listEventDelegates[mouseUpEventKey];
        mouseEventDelegate(this, e);
    }
}






How to: Consume Events in a Web Forms Application


A common scenario in ASP.NET Web Forms applications is to populate a webpage with controls, and then perform a specific action based on which control the user clicks. For example, a System.Web.UI.WebControls.Button control raises an event when the user clicks it in the webpage. By handling the event, your application can perform the appropriate application logic for that button click.

To handle a button click event on a webpage

  1. Create a ASP.NET Web Forms page (webpage) that has a Button control with the OnClick value set to the name of method that you will define in the next step.

    <asp:Button ID="Button1" runat="server" Text="Click Me" OnClick="Button1_Click" />  
    
    
  2. Define an event handler that matches the Click event delegate signature and that has the name you defined for the OnClick value.

    protected void Button1_Click(object sender, EventArgs e)  
    {  
        // perform action  
    }  
    
    

    The Click event uses the EventHandler class for the delegate type and the EventArgs class for the event data. The ASP.NET page framework automatically generates code that creates an instance of EventHandler and adds this delegate instance to the Click event of the Button instance.

  3. In the event handler method that you defined in step 2, add code to perform any actions that are required when the event occurs.






Observer Design Pattern


The observer design pattern enables a subscriber to register with and receive notifications from a provider. It is suitable for any scenario that requires push-based notification. The pattern defines a provider (also known as a subject or an observable) and zero, one, or more observers. Observers register with the provider, and whenever a predefined condition, event, or state change occurs, the provider automatically notifies all observers by calling one of their methods. In this method call, the provider can also provide current state information to observers. In the .NET Framework, the observer design pattern is applied by implementing the generic System.IObservable<T> and System.IObserver<T> interfaces. The generic type parameter represents the type that provides notification information.

The observer design pattern is suitable for distributed push-based notifications, because it supports a clean separation between two different components or application layers, such as a data source (business logic) layer and a user interface (display) layer. The pattern can be implemented whenever a provider uses callbacks to supply its clients with current information.

Implementing the pattern requires that you provide the following:

  • A provider or subject, which is the object that sends notifications to observers. A provider is a class or structure that implements the IObservable<T> interface. The provider must implement a single method, IObservable<T>.Subscribe, which is called by observers that wish to receive notifications from the provider.

  • An observer, which is an object that receives notifications from a provider. An observer is a class or structure that implements the IObserver<T> interface. The observer must implement three methods, all of which are called by the provider:

  • A mechanism that allows the provider to keep track of observers. Typically, the provider uses a container object, such as a System.Collections.Generic.List<T> object, to hold references to the IObserver<T> implementations that have subscribed to notifications. Using a storage container for this purpose enables the provider to handle zero to an unlimited number of observers. The order in which observers receive notifications is not defined; the provider is free to use any method to determine the order.

  • An IDisposable implementation that enables the provider to remove observers when notification is complete. Observers receive a reference to the IDisposable implementation from the Subscribe method, so they can also call the IDisposable.Dispose method to unsubscribe before the provider has finished sending notifications.

  • An object that contains the data that the provider sends to its observers. The type of this object corresponds to the generic type parameter of the IObservable<T> and IObserver<T> interfaces. Although this object can be the same as the IObservable<T> implementation, most commonly it is a separate type.

System_CAPS_ICON_note.jpg Note

In addition to implementing the observer design pattern, you may be interested in exploring libraries that are built using the IObservable<T> and IObserver<T> interfaces. For example, Reactive Extensions for .NET (Rx) consist of a set of extension methods and LINQ standard sequence operators to support asynchronous programming.

The following example uses the observer design pattern to implement an airport baggage claim information system. A BaggageInfo class provides information about arriving flights and the carousels where baggage from each flight is available for pickup. It is shown in the following example.

using System;
using System.Collections.Generic;

public class BaggageInfo
{
   private int flightNo;
   private string origin;
   private int location;

   internal BaggageInfo(int flight, string from, int carousel)
   {
      this.flightNo = flight;
      this.origin = from;
      this.location = carousel;
   }

   public int FlightNumber {
      get { return this.flightNo; }
   }

   public string From {
      get { return this.origin; }
   }

   public int Carousel {
      get { return this.location; }
   }
}

BaggageHandler class is responsible for receiving information about arriving flights and baggage claim carousels. Internally, it maintains two collections:

  • observers - A collection of clients that will receive updated information.

  • flights - A collection of flights and their assigned carousels.

Both collections are represented by generic List<T> objects that are instantiated in the BaggageHandler class constructor. The source code for the BaggageHandler class is shown in the following example.

public class BaggageHandler : IObservable<BaggageInfo>
{
   private List<IObserver<BaggageInfo>> observers;
   private List<BaggageInfo> flights;

   public BaggageHandler()
   {
      observers = new List<IObserver<BaggageInfo>>();
      flights = new List<BaggageInfo>();
   }

   public IDisposable Subscribe(IObserver<BaggageInfo> observer)
   {
      // Check whether observer is already registered. If not, add it
      if (! observers.Contains(observer)) {
         observers.Add(observer);
         // Provide observer with existing data.
         foreach (var item in flights)
            observer.OnNext(item);
      }
      return new Unsubscriber<BaggageInfo>(observers, observer);
   }

   // Called to indicate all baggage is now unloaded.
   public void BaggageStatus(int flightNo)
   {
      BaggageStatus(flightNo, String.Empty, 0);
   }

   public void BaggageStatus(int flightNo, string from, int carousel)
   {
      var info = new BaggageInfo(flightNo, from, carousel);

      // Carousel is assigned, so add new info object to list.
      if (carousel > 0 && ! flights.Contains(info)) {
         flights.Add(info);
         foreach (var observer in observers)
            observer.OnNext(info);
      }
      else if (carousel == 0) {
         // Baggage claim for flight is done
         var flightsToRemove = new List<BaggageInfo>();
         foreach (var flight in flights) {
            if (info.FlightNumber == flight.FlightNumber) {
               flightsToRemove.Add(flight);
               foreach (var observer in observers)
                  observer.OnNext(info);
            }
         }
         foreach (var flightToRemove in flightsToRemove)
            flights.Remove(flightToRemove);

         flightsToRemove.Clear();
      }
   }

   public void LastBaggageClaimed()
   {
      foreach (var observer in observers)
         observer.OnCompleted();

      observers.Clear();
   }
}

Clients that wish to receive updated information call the BaggageHandler.Subscribe method. If the client has not previously subscribed to notifications, a reference to the client's IObserver<T> implementation is added to the observers collection.

The overloaded BaggageHandler.BaggageStatus method can be called to indicate that baggage from a flight either is being unloaded or is no longer being unloaded. In the first case, the method is passed a flight number, the airport from which the flight originated, and the carousel where baggage is being unloaded. In the second case, the method is passed only a flight number. For baggage that is being unloaded, the method checks whether the BaggageInfo information passed to the method exists in the flights collection. If it does not, the method adds the information and calls each observer's OnNext method. For flights whose baggage is no longer being unloaded, the method checks whether information on that flight is stored in the flights collection. If it is, the method calls each observer's OnNext method and removes the BaggageInfo object from the flights collection.

When the last flight of the day has landed and its baggage has been processed, the BaggageHandler.LastBaggageClaimed method is called. This method calls each observer's OnCompleted method to indicate that all notifications have completed, and then clears the observers collection.

The provider's Subscribe method returns an IDisposable implementation that enables observers to stop receiving notifications before the OnCompleted method is called. The source code for this Unsubscriber(Of BaggageInfo) class is shown in the following example. When the class is instantiated in the BaggageHandler.Subscribe method, it is passed a reference to the observers collection and a reference to the observer that is added to the collection. These references are assigned to local variables. When the object's Dispose method is called, it checks whether the observer still exists in the observerscollection, and, if it does, removes the observer.

internal class Unsubscriber<BaggageInfo> : IDisposable
{
   private List<IObserver<BaggageInfo>> _observers;
   private IObserver<BaggageInfo> _observer;

   internal Unsubscriber(List<IObserver<BaggageInfo>> observers, IObserver<BaggageInfo> observer)
   {
      this._observers = observers;
      this._observer = observer;
   }

   public void Dispose() 
   {
      if (_observers.Contains(_observer))
         _observers.Remove(_observer);
   }
}

The following example provides an IObserver<T> implementation named ArrivalsMonitor, which is a base class that displays baggage claim information. The information is displayed alphabetically, by the name of the originating city. The methods of ArrivalsMonitor are marked as overridable (in Visual Basic) or virtual (in C#), so they can all be overridden by a derived class.

using System;
using System.Collections.Generic;

public class ArrivalsMonitor : IObserver<BaggageInfo>
{
   private string name;
   private List<string> flightInfos = new List<string>();
   private IDisposable cancellation;
   private string fmt = "{0,-20} {1,5}  {2, 3}";

   public ArrivalsMonitor(string name)
   {
      if (String.IsNullOrEmpty(name))
         throw new ArgumentNullException("The observer must be assigned a name.");

      this.name = name;
   }

   public virtual void Subscribe(BaggageHandler provider)
   {
      cancellation = provider.Subscribe(this);
   }

   public virtual void Unsubscribe()
   {
      cancellation.Dispose();
      flightInfos.Clear();
   }

   public virtual void OnCompleted() 
   {
      flightInfos.Clear();
   }

   // No implementation needed: Method is not called by the BaggageHandler class.
   public virtual void OnError(Exception e)
   {
      // No implementation.
   }

   // Update information.
   public virtual void OnNext(BaggageInfo info) 
   {
      bool updated = false;

      // Flight has unloaded its baggage; remove from the monitor.
      if (info.Carousel == 0) {
         var flightsToRemove = new List<string>();
         string flightNo = String.Format("{0,5}", info.FlightNumber);
         
         foreach (var flightInfo in flightInfos) {
            if (flightInfo.Substring(21, 5).Equals(flightNo)) {
               flightsToRemove.Add(flightInfo);
               updated = true;
            }
         }
         foreach (var flightToRemove in flightsToRemove)
            flightInfos.Remove(flightToRemove);

         flightsToRemove.Clear();
      }
      else {
         // Add flight if it does not exist in the collection.
         string flightInfo = String.Format(fmt, info.From, info.FlightNumber, info.Carousel);
         if (! flightInfos.Contains(flightInfo)) {
            flightInfos.Add(flightInfo);
            updated = true;
         }
      }
      if (updated) {
         flightInfos.Sort();
         Console.WriteLine("Arrivals information from {0}", this.name);
         foreach (var flightInfo in flightInfos)
            Console.WriteLine(flightInfo);

         Console.WriteLine();
      }
   }
}

The ArrivalsMonitor class includes the Subscribe and Unsubscribe methods. The Subscribe method enables the class to save the IDisposable implementation returned by the call to Subscribe to a private variable. The Unsubscribe method enables the class to unsubscribe from notifications by calling the provider's Dispose implementation. ArrivalsMonitor also provides implementations of the OnNextOnError, and OnCompleted methods. Only the OnNext implementation contains a significant amount of code. The method works with a private, sorted, generic List<T> object that maintains information about the airports of origin for arriving flights and the carousels on which their baggage is available. If the BaggageHandler class reports a new flight arrival, the OnNext method implementation adds information about that flight to the list. If the BaggageHandler class reports that the flight's baggage has been unloaded, the OnNext method removes that flight from the list. Whenever a change is made, the list is sorted and displayed to the console.

The following example contains the application entry point that instantiates the BaggageHandler class as well as two instances of the ArrivalsMonitorclass, and uses the BaggageHandler.BaggageStatus method to add and remove information about arriving flights. In each case, the observers receive updates and correctly display baggage claim information.

using System;
using System.Collections.Generic;

public class Example
{
   public static void Main()
   {
      BaggageHandler provider = new BaggageHandler();
      ArrivalsMonitor observer1 = new ArrivalsMonitor("BaggageClaimMonitor1");
      ArrivalsMonitor observer2 = new ArrivalsMonitor("SecurityExit");

      provider.BaggageStatus(712, "Detroit", 3);
      observer1.Subscribe(provider);
      provider.BaggageStatus(712, "Kalamazoo", 3);
      provider.BaggageStatus(400, "New York-Kennedy", 1);
      provider.BaggageStatus(712, "Detroit", 3);
      observer2.Subscribe(provider);
      provider.BaggageStatus(511, "San Francisco", 2);
      provider.BaggageStatus(712);
      observer2.Unsubscribe();
      provider.BaggageStatus(400);
      provider.LastBaggageClaimed();
   }
}
// The example displays the following output:
//      Arrivals information from BaggageClaimMonitor1
//      Detroit                712    3
//
//      Arrivals information from BaggageClaimMonitor1
//      Detroit                712    3
//      Kalamazoo              712    3
//
//      Arrivals information from BaggageClaimMonitor1
//      Detroit                712    3
//      Kalamazoo              712    3
//      New York-Kennedy       400    1
//
//      Arrivals information from SecurityExit
//      Detroit                712    3
//
//      Arrivals information from SecurityExit
//      Detroit                712    3
//      Kalamazoo              712    3
//
//      Arrivals information from SecurityExit
//      Detroit                712    3
//      Kalamazoo              712    3
//      New York-Kennedy       400    1
//
//      Arrivals information from BaggageClaimMonitor1
//      Detroit                712    3
//      Kalamazoo              712    3
//      New York-Kennedy       400    1
//      San Francisco          511    2
//
//      Arrivals information from SecurityExit
//      Detroit                712    3
//      Kalamazoo              712    3
//      New York-Kennedy       400    1
//      San Francisco          511    2
//
//      Arrivals information from BaggageClaimMonitor1
//      New York-Kennedy       400    1
//      San Francisco          511    2
//
//      Arrivals information from SecurityExit
//      New York-Kennedy       400    1
//      San Francisco          511    2
//
//      Arrivals information from BaggageClaimMonitor1
//      San Francisco          511    2

TitleDescription
Observer Design Pattern Best PracticesDescribes best practices to adopt when developing applications that implement the observer design pattern.
How to: Implement a ProviderProvides a step-by-step implementation of a provider for a temperature monitoring application.
How to: Implement an ObserverProvides a step-by-step implementation of an observer for a temperature monitoring application.







'프로그래밍 > C#' 카테고리의 다른 글

Asynchronous Programming with async and await (C#)  (0) 2017.04.19
Developing Windows Service Applications  (0) 2017.04.02
Common I/O Tasks  (0) 2017.03.15
Thread 관련  (0) 2017.03.05
Sockets  (0) 2017.03.02
:
Posted by 지훈2
2017. 3. 15. 06:34

Common I/O Tasks 프로그래밍/C#2017. 3. 15. 06:34



Common File Tasks

  1. Create a text file
  2. Write to a text file
  3. Read from a text file
  4. Append text to a file
  5. Rename or move a file
  6. Delete a file
  7. Copy a file
  8. Get the size of a file
  9. Get the attributes of a file
  10. Set the attributes of a file
  11. Determine whether a file exists
  12. Read from a binary file
  13. Write to a binary file
  14. Retrieve the fully qualified path of a file
  15. Retrieve the file name and extension from a path
  16. Change the extension of a file

Common Directory Tasks
  1. Access a file in a special folder such as My Documents
  2. Create a directory
  3. Create a subdirectory
  4. Rename or move a directory
  5. Copy a directory
  6. Delete a directory
  7. See the files and subdirectories in a directory
  8. Find the size of a directory
  9. Determine whether a directory exists

Common I/O Tasks
  1. How to: Read Characters from a String
  2. How to: Write Characters to a String
  3. How to: Add or Remove Access Control List Entries
  4. How to: Compress and Extract Files
  5. Composing Streams
  6. How to: Convert Between .NET Framework Streams and Windows Runtime Streams







https://msdn.microsoft.com/en-us/library/ms404278(v=vs.110).aspx


Common I/O Tasks



To do this...See the example in this topic...
Create a text fileFile.CreateText method

 FileInfo.CreateText method

 File.Create method

 FileInfo.Create method
Write to a text fileHow to: Write Text to a File

 How to: Write a Text File (C++/CLI)
Read from a text fileHow to: Read Text from a File
Append text to a fileHow to: Open and Append to a Log File

 File.AppendText method

 FileInfo.AppendText method
Rename or move a fileFile.Move method

 FileInfo.MoveTo method
Delete a fileFile.Delete method

 FileInfo.Delete method
Copy a fileFile.Copy method

 FileInfo.CopyTo method
Get the size of a fileFileInfo.Length property
Get the attributes of a fileFile.GetAttributes method
Set the attributes of a fileFile.SetAttributes method
Determine whether a file existsFile.Exists method
Read from a binary fileHow to: Read and Write to a Newly Created Data File
Write to a binary fileHow to: Read and Write to a Newly Created Data File
Retrieve a file name extensionPath.GetExtension method
Retrieve the fully qualified path of a filePath.GetFullPath method
Retrieve the file name and extension from a pathPath.GetFileName method
Change the extension of a filePath.ChangeExtension method
To do this...See the example in this topic...
Access a file in a special folder such as My DocumentsHow to: Write Text to a File
Create a directoryDirectory.CreateDirectory method

 FileInfo.Directory property
Create a subdirectoryDirectoryInfo.CreateSubdirectory method
Rename or move a directoryDirectory.Move method

 DirectoryInfo.MoveTo method
Copy a directoryHow to: Copy Directories
Delete a directoryDirectory.Delete method

 DirectoryInfo.Delete method
See the files and subdirectories in a directoryHow to: Enumerate Directories and Files
Find the size of a directorySystem.IO.Directory class
Determine whether a directory existsDirectory.Exists method





File.CreateText Method (String)


Creates or opens a file for writing UTF-8 encoded text.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static StreamWriter CreateText(
	string path
)

Parameters

path
Type: System.String

The file to be opened for writing.

Return Value

Type: System.IO.StreamWriter

StreamWriter that writes to the specified file using UTF-8 encoding.

Exceptions

ExceptionCondition
UnauthorizedAccessException

The caller does not have the required permission.

ArgumentException

path is a zero-length string, contains only white space, or contains one or more invalid characters as defined by InvalidPathChars.

ArgumentNullException

path is null.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

DirectoryNotFoundException

The specified path is invalid (for example, it is on an unmapped drive).

NotSupportedException

path is in an invalid format.

Remarks

This method is equivalent to the StreamWriter(String, Boolean) constructor overload with the append parameter set to false. If the file specified by path does not exist, it is created. If the file does exist, its contents are overwritten. Additional threads are permitted to read the file while it is open.

The path parameter is permitted to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example creates a file for text writing and reading.

using System;
using System.IO;

class Test 
{
    public static void Main() 
    {
        string path = @"c:\temp\MyTest.txt";
        if (!File.Exists(path)) 
        {
            // Create a file to write to.
            using (StreamWriter sw = File.CreateText(path)) 
            {
                sw.WriteLine("Hello");
                sw.WriteLine("And");
                sw.WriteLine("Welcome");
            }	
        }

        // Open the file to read from.
        using (StreamReader sr = File.OpenText(path)) 
        {
            string s = "";
            while ((s = sr.ReadLine()) != null) 
            {
                Console.WriteLine(s);
            }
        }
    }
}





FileInfo.CreateText Method ()


Creates a StreamWriter that writes a new text file.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public StreamWriter CreateText()

Return Value

Type: System.IO.StreamWriter

A new StreamWriter.

Exceptions

ExceptionCondition
UnauthorizedAccessException

The file name is a directory.

IOException

The disk is read-only.

SecurityException

The caller does not have the required permission.

Remarks

By default, full read/write access to new files is granted to all users.

Examples

The following example demonstrates the CreateText method.

using System;
using System.IO;

class Test 
{

    public static void Main() 
    {
        string path = @"c:\temp\MyTest.txt";
        FileInfo fi = new FileInfo(path);

        if (!fi.Exists) 
        {
            //Create a file to write to.
            using (StreamWriter sw = fi.CreateText()) 
            {
                sw.WriteLine("Hello");
                sw.WriteLine("And");
                sw.WriteLine("Welcome");
            }
        }

        //Open the file to read from.
        using (StreamReader sr = fi.OpenText()) 
        {
            string s = "";
            while ((s = sr.ReadLine()) != null) 
            {
                Console.WriteLine(s);
            }
        }
    }
}
//This code produces output similar to the following; 
//results may vary based on the computer/file structure/etc.:
//
//Hello
//And
//Welcome





File.Create Method (String)


Creates or overwrites a file in the specified path.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static FileStream Create(
	string path
)

Parameters

path
Type: System.String

The path and name of the file to create.

Return Value

Type: System.IO.FileStream

FileStream that provides read/write access to the file specified in path.

Exceptions

ExceptionCondition
UnauthorizedAccessException

The caller does not have the required permission.

-or-

path specified a file that is read-only.

ArgumentException

path is a zero-length string, contains only white space, or contains one or more invalid characters as defined by InvalidPathChars.

ArgumentNullException

path is null.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

DirectoryNotFoundException

The specified path is invalid (for example, it is on an unmapped drive).

IOException

An I/O error occurred while creating the file.

NotSupportedException

path is in an invalid format.

Remarks

The FileStream object created by this method has a default FileShare value of None; no other process or code can access the created file until the original file handle is closed.

This method is equivalent to the Create(String, Int32) method overload using the default buffer size.

The path parameter is permitted to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

If the specified file does not exist, it is created; if it does exist and it is not read-only, the contents are overwritten.

By default, full read/write access to new files is granted to all users. The file is opened with read/write access and must be closed before it can be opened by another application.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example creates a file in the specified path, writes some information to the file, and reads from the file.

using System;
using System.IO;
using System.Text;

class Test
{
    public static void Main()
    {
        string path = @"c:\temp\MyTest.txt";

        try
        {

            // Delete the file if it exists.
            if (File.Exists(path))
            {
                // Note that no lock is put on the
                // file and the possibility exists
                // that another process could do
                // something with it between
                // the calls to Exists and Delete.
                File.Delete(path);
            }

            // Create the file.
            using (FileStream fs = File.Create(path))
            {
                Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
                // Add some information to the file.
                fs.Write(info, 0, info.Length);
            }

            // Open the stream and read it back.
            using (StreamReader sr = File.OpenText(path))
            {
                string s = "";
                while ((s = sr.ReadLine()) != null)
                {
                    Console.WriteLine(s);
                }
            }
        }

        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
}





FileInfo.Create Method ()


Creates a file.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public FileStream Create()

Return Value

Type: System.IO.FileStream

A new file.

Remarks

By default, full read/write access to new files is granted to all users.

This method is a wrapper for the functionality provided by File.Create.

Examples

The following example creates a reference to a file, and then creates the file on disk using FileInfo.Create().

using System;
using System.IO;

public class DeleteTest 
{
    public static void Main() 
    {
        // Create a reference to a file.
        FileInfo fi = new FileInfo("temp.txt");
        // Actually create the file.
        FileStream fs = fi.Create();
        // Modify the file as required, and then close the file.
        fs.Close();
        // Delete the file.
        fi.Delete();
    }
}

The following example creates a file, adds some text to it, and reads from the file.

using System;
using System.IO;
using System.Text;

class Test 
{

    public static void Main() 
    {
        string path = @"c:\MyTest.txt";
        FileInfo fi = new FileInfo(path);

        // Delete the file if it exists.
        if (fi.Exists) 
        {
            fi.Delete();
        }

        //Create the file.
        using (FileStream fs = fi.Create()) 
        {
            Byte[] info = 
                new UTF8Encoding(true).GetBytes("This is some text in the file.");

            //Add some information to the file.
            fs.Write(info, 0, info.Length);
        }

        //Open the stream and read it back.
        using (StreamReader sr = fi.OpenText()) 
        {
            string s = "";
            while ((s = sr.ReadLine()) != null) 
            {
                Console.WriteLine(s);
            }
        }
    }
}
//This code produces output similar to the following; 
//results may vary based on the computer/file structure/etc.:
//
//This is some text in the file.






How to: Write Text to a File


This topic shows different ways you can write text to a file for .NET Framework applications or Windows 8.x Store apps. The following classes and methods are typically used to write text to a file:

The samples have been kept simple in order to focus on the task being performed. For this reason, the samples perform minimal error checking and exception handling, if any. A real-world application generally provides more robust error checking and exception handling.

The following example shows how to synchronously write text to a new file using the StreamWriter class, one line at a time. The new text file is saved to the user's My Documents folder. Because the StreamWriter object is declared and instantiated in a using statement, the Dispose method is invoked which automatically flushes and closes the stream.

        // Create a string array with the lines of text
        string[] lines = { "First line", "Second line", "Third line" };

        // Set a variable to the My Documents path.
        string mydocpath =
            Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        // Write the string array to a new file named "WriteLines.txt".
        using (StreamWriter outputFile = new StreamWriter(mydocpath + @"\WriteLines.txt")) {
            foreach (string line in lines)
                outputFile.WriteLine(line);
        }

The following example shows how to append text to an existing file using the StreamWriter class. It uses the same text file from the previous example.

        // Set a variable to the My Documents path.
        string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        // Append text to an existing file named "WriteLines.txt".
        using (StreamWriter outputFile = new StreamWriter(mydocpath + @"\WriteLines.txt", true)) {
            outputFile.WriteLine("Fourth Line");
        }

The following example shows how to asynchronously write text to a new file using the StreamWriter class. In order to invoke the WriteAsync method, the method call needs to be within an async method. The new text file is saved to the user's My Documents folder.

    static async void WriteTextAsync(string text)
    {
        // Set a variable to the My Documents path.
        string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        // Write the text asynchronously to a new file named "WriteTextAsync.txt".
        using (StreamWriter outputFile = new StreamWriter(mydocpath + @"\WriteTextAsync.txt")) {
            await outputFile.WriteAsync(text);
        }
    }

The following example shows how to write text to a new file and append new lines of text to the same file using the File class. The WriteAllText and AppendAllLines methods open and close the file automatically. If the path you provide to the WriteAllText method already exists, the file will be overwritten.

        // Create a string array with the lines of text
        string text = "First line" + Environment.NewLine;

        // Set a variable to the My Documents path.
        string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        // Write the text to a new file named "WriteFile.txt".
        File.WriteAllText(mydocpath + @"\WriteFile.txt", text);

        // Create a string array with the additional lines of text
        string[] lines = { "New line 1", "New line 2" };

        // Append new lines of text to the file
        File.AppendAllLines(mydocpath + @"\WriteFile.txt", lines);

The following example shows how to asynchronously write user input to a text file in a Windows 8.x Store app. Because of security considerations, opening a file from a Windows 8.x Store app typically requires the use of a FileOpenPicker control. In this example, the FileOpenPicker is filtered to show text files.

<Page  
    x:Class="OpenFileWindowsStore.MainPage"  
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    xmlns:local="using:OpenFileWindowsStore"  
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
    mc:Ignorable="d">  
  
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">  
        <Button Content="save text to a file" HorizontalAlignment="Left" Margin="103,417,0,0" VerticalAlignment="Top"   
                Width="329" Height="86" FontSize="35" Click="Button_Click"/>  
        <TextBox Name="UserInputTextBox"  FontSize="18" HorizontalAlignment="Left" Margin="106,146,0,0"   
                 TextWrapping="Wrap" Text="Write some text here, and select a file to write it to." VerticalAlignment="Top"   
                 Height="201" Width="558" AcceptsReturn="True"/>  
        <TextBlock Name="StatusTextBox" HorizontalAlignment="Left" Margin="106,570,0,147" TextWrapping="Wrap" Text="Status:"   
                   VerticalAlignment="Center" Height="51" Width="1074" FontSize="18" />  
    </Grid>  
</Page>  

using System;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Storage;
using System.Text;
using Windows.Storage.Pickers;
using Windows.UI.Popups; 

namespace OpenFileWindowsStore
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        // Create a file picker to open a file. Most file access in Windows Store Apps
        // requires the use of a file picker for security purposes.
        FileOpenPicker picker = new FileOpenPicker();
        private async void Button_Click(object sender, RoutedEventArgs e)
        {
         
           // Set properties on the file picker such as start location and the type 
            // of files to display.
            picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
            picker.ViewMode = PickerViewMode.List;
            picker.FileTypeFilter.Add(".txt");

            // Show picker enabling user to pick one file.
            StorageFile result = await picker.PickSingleFileAsync();

            if (result != null)
            {
                try
                {
                    // Use FileIO to replace the content of the text file
                    await FileIO.WriteTextAsync(result, UserInputTextBox.Text);

                    // Display a success message
                    StatusTextBox.Text = "Status: File saved successfully";
                }
                catch (Exception ex)
                {
                    // Display an error message
                    StatusTextBox.Text = "Status: error saving the file - " + ex.Message;
                }
            }
            else
                StatusTextBox.Text = "Status: User cancelled save operation";
        }
    }
}





How to: Read Text from a File


The following examples show how to read text synchronously and asynchronously from a text file using .NET for desktop apps. In both examples, when you create the instance of the StreamReader class, you provide the relative or absolute path to the file. The following examples assume that the file named TestFile.txt is in the same folder as the application.

These code examples do not apply developing for Windows Store Apps because the Windows Runtime provides different streams types reading and writing to files. For an example that shows how to read text from a file within the context of a Windows Store app, see Quickstart: Reading and writing files. For examples that show how to convert between .NET Framework streams and Windows runtime streams see How to: Convert Between .NET Framework Streams and Windows Runtime Streams.

The first example shows a synchronous read operation within a console application. In this example, the text file is opened using a stream reader, the contents are copied to a string and string is output to the console.

using System;
using System.IO;

class Test
{
    public static void Main()
    {
        try
        {   // Open the text file using a stream reader.
            using (StreamReader sr = new StreamReader("TestFile.txt"))
            {
	        // Read the stream to a string, and write the string to the console.
                String line = sr.ReadToEnd();
                Console.WriteLine(line);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("The file could not be read:");
            Console.WriteLine(e.Message);
        }
    }
}

The second example shows an asynchronous read operation within a Windows Presentation Foundation (WPF) application.

using System;
using System.Windows;
using System.IO;

namespace WpfApplication
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void ReadFileButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                using (StreamReader sr = new StreamReader("TestFile.txt"))
                {
                    String line = await sr.ReadToEndAsync();
                    ResultBlock.Text = line;
                }
            }
            catch (Exception ex)
            {
                ResultBlock.Text = "Could not read the file";
            }
        }
    }
}





How to: Open and Append to a Log File


using System;
using System.IO;

class DirAppend
{
    public static void Main()
    {
        using (StreamWriter w = File.AppendText("log.txt"))
        {
            Log("Test1", w);
            Log("Test2", w);
        }
        
        using (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 ("-------------------------------");
    }

    public static void DumpLog(StreamReader r)
    {
        string line;
        while ((line = r.ReadLine()) != null)
        {
            Console.WriteLine(line);
        }
    }
}





File.AppendText Method (String)


Creates a StreamWriter that appends UTF-8 encoded text to an existing file, or to a new file if the specified file does not exist.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static StreamWriter AppendText(
	string path
)

Parameters

path
Type: System.String

The path to the file to append to.

Return Value

Type: System.IO.StreamWriter

A stream writer that appends UTF-8 encoded text to the specified file or to a new file.

Exceptions

ExceptionCondition
UnauthorizedAccessException

The caller does not have the required permission.

ArgumentException

path is a zero-length string, contains only white space, or contains one or more invalid characters as defined by InvalidPathChars.

ArgumentNullException

path is null.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

DirectoryNotFoundException

The specified path is invalid (for example, the directory doesn’t exist or it is on an unmapped drive).

NotSupportedException

path is in an invalid format.

Remarks

This method is equivalent to the StreamWriter(String, Boolean) constructor overload. If the file specified by path does not exist, it is created. If the file does exist, write operations to the StreamWriter append text to the file. Additional threads are permitted to read the file while it is open.

The path parameter is permitted to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

The path parameter is not case-sensitive.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example appends text to a file. The method creates a new file if the file doesn’t exist. However, the directory named temp on drive C must exist for the example to complete successfully.

using System;
using System.IO;

class Test 
{
    public static void Main() 
    {
        string path = @"c:\temp\MyTest.txt";
        // This text is added only once to the file.
        if (!File.Exists(path)) 
        {
            // Create a file to write to.
            using (StreamWriter sw = File.CreateText(path)) 
            {
                sw.WriteLine("Hello");
                sw.WriteLine("And");
                sw.WriteLine("Welcome");
            }	
        }

        // This text is always added, making the file longer over time
        // if it is not deleted.
        using (StreamWriter sw = File.AppendText(path)) 
        {
            sw.WriteLine("This");
            sw.WriteLine("is Extra");
            sw.WriteLine("Text");
        }	

        // Open the file to read from.
        using (StreamReader sr = File.OpenText(path)) 
        {
            string s = "";
            while ((s = sr.ReadLine()) != null) 
            {
                Console.WriteLine(s);
            }
        }
    }
}





FileInfo.AppendText Method ()


Creates a StreamWriter that appends text to the file represented by this instance of the FileInfo.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public StreamWriter AppendText()

Return Value

Type: System.IO.StreamWriter

A new StreamWriter.

Examples

The following example appends text to a file and reads from the file.

using System;
using System.IO;

class Test 
{

    public static void Main() 
    {
        FileInfo fi = new FileInfo(@"c:\MyTest.txt");

        // This text is added only once to the file.
        if (!fi.Exists) 
        {
            //Create a file to write to.
            using (StreamWriter sw = fi.CreateText()) 
            {
                sw.WriteLine("Hello");
                sw.WriteLine("And");
                sw.WriteLine("Welcome");
            }	
        }

        // This text will always be added, making the file longer over time
        // if it is not deleted.
        using (StreamWriter sw = fi.AppendText()) 
        {
            sw.WriteLine("This");
            sw.WriteLine("is Extra");
            sw.WriteLine("Text");
        }	

        //Open the file to read from.
        using (StreamReader sr = fi.OpenText()) 
        {
            string s = "";
            while ((s = sr.ReadLine()) != null) 
            {
                Console.WriteLine(s);
            }
        }
    }
}
//This code produces output similar to the following; 
//results may vary based on the computer/file structure/etc.:
//
//Hello
//And
//Welcome
//This
//is Extra
//Text

//When you run this application a second time, you will see the following output:
//
//Hello
//And
//Welcome
//This
//is Extra
//Text
//This
//is Extra
//Text

The following example demonstrates appending text to the end of a file and also displays the result of the append operation to the console. The first time this routine is called, the file is created if it does not exist. After that, the specified text is appended to the file.

using System;
using System.IO;

public class AppendTextTest 
{
    public static void Main() 
    {
        FileInfo fi = new FileInfo("temp.txt");
        // Create a writer, ready to add entries to the file.
        StreamWriter sw = fi.AppendText();
        sw.WriteLine("Add as many lines as you like...");
        sw.WriteLine("Add another line to the output...");
        sw.Flush();
        sw.Close();
        // Get the information out of the file and display it.
        // Remember that the file might have other lines if it already existed.
        StreamReader sr = new StreamReader(fi.OpenRead());
        while (sr.Peek() != -1)
            Console.WriteLine( sr.ReadLine() );
    }
}
//This code produces output similar to the following; 
//results may vary based on the computer/file structure/etc.:
//Add as many lines as you like...
//Add another line to the output..





File.Move Method (String, String)


Moves a specified file to a new location, providing the option to specify a new file name.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static void Move(
	string sourceFileName,
	string destFileName
)

Parameters

sourceFileName
Type: System.String

The name of the file to move. Can include a relative or absolute path.

destFileName
Type: System.String

The new path and name for the file.

Exceptions

ExceptionCondition
IOException

The destination file already exists.

-or-

sourceFileName was not found.

ArgumentNullException

sourceFileName or destFileName is null.

ArgumentException

sourceFileName or destFileName is a zero-length string, contains only white space, or contains invalid characters as defined in InvalidPathChars.

UnauthorizedAccessException

The caller does not have the required permission.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

DirectoryNotFoundException

The path specified in sourceFileName or destFileName is invalid, (for example, it is on an unmapped drive).

NotSupportedException

sourceFileName or destFileName is in an invalid format.

Remarks

This method works across disk volumes, and it does not throw an exception if the source and destination are the same. Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an IOException. You cannot use the Move method to overwrite an existing file.

The sourceFileName and destFileName arguments can include relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

If you try to move a file across disk volumes and that file is in use, the file is copied to the destination, but it is not deleted from the source.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example moves a file.

using System;
using System.IO;

class Test 
{
    public static void Main() 
    {
        string path = @"c:\temp\MyTest.txt";
        string path2 = @"c:\temp2\MyTest.txt";
        try 
        {
            if (!File.Exists(path)) 
            {
                // This statement ensures that the file is created,
                // but the handle is not kept.
                using (FileStream fs = File.Create(path)) {}
            }

            // Ensure that the target does not exist.
            if (File.Exists(path2))	
            File.Delete(path2);

            // Move the file.
            File.Move(path, path2);
            Console.WriteLine("{0} was moved to {1}.", path, path2);

            // See if the original exists now.
            if (File.Exists(path)) 
            {
                Console.WriteLine("The original file still exists, which is unexpected.");
            } 
            else 
            {
                Console.WriteLine("The original file no longer exists, which is expected.");
            }			

        } 
        catch (Exception e) 
        {
            Console.WriteLine("The process failed: {0}", e.ToString());
        }
    }
}





FileInfo.MoveTo Method (String)


Moves a specified file to a new location, providing the option to specify a new file name.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public void MoveTo(
	string destFileName
)

Parameters

destFileName
Type: System.String

The path to move the file to, which can specify a different file name.

Exceptions

ExceptionCondition
IOException

An I/O error occurs, such as the destination file already exists or the destination device is not ready.

ArgumentNullException

destFileName is null.

ArgumentException

destFileName is empty, contains only white spaces, or contains invalid characters.

SecurityException

The caller does not have the required permission.

UnauthorizedAccessException

destFileName is read-only or is a directory.

FileNotFoundException

The file is not found.

DirectoryNotFoundException

The specified path is invalid, such as being on an unmapped drive.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

NotSupportedException

destFileName contains a colon (:) in the middle of the string.

Remarks

This method works across disk volumes. For example, the file c:\MyFile.txt can be moved to d:\public and renamed NewFile.txt.

Examples

The following example demonstrates moving a file to a different location and renaming the file.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.IO;
using System.Reflection;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;




namespace Microsoft.Samples.MoveTo.CS 
{

	class Program 
	{
		private static string sourcePath = Environment.GetFolderPath
			(Environment.SpecialFolder.MyDocuments) + 
			@"\FileInfoTestDirectory\MoveFrom\FromFile.xml";

		private static string destPath = Environment.GetFolderPath
			(Environment.SpecialFolder.MyDocuments) + 
			@"\FileInfoTestDirectory\DestFile.xml";
		//
		// The main entry point for the application.
		//
		[STAThread()] static void Main () 
		{
			// Change Console properties to make it obvious that 
			// the application is starting.
			Console.Clear();
			// Move it to the upper left corner of the screen.
			Console.SetWindowPosition(0, 0);
			// Make it very large.
			Console.SetWindowSize(Console.LargestWindowWidth - 24,
				Console.LargestWindowHeight - 16);
			Console.WriteLine("Welcome.");
			Console.WriteLine("This application demonstrates the FileInfo.MoveTo method.");
			Console.WriteLine("Press any key to start.");
			string s = Console.ReadLine();
			Console.Write("    Checking whether ");
			Console.Write(sourcePath);
			Console.WriteLine(" exists.");
			FileInfo fInfo = new FileInfo (sourcePath);
			EnsureSourceFileExists();
			DisplayFileProperties(fInfo);
			Console.WriteLine("Preparing to move the file to ");
			Console.Write(destPath);
			Console.WriteLine(".");
			MoveFile(fInfo);
			DisplayFileProperties(fInfo);
			Console.WriteLine("Preparing to delete directories.");
			DeleteFiles();
			Console.WriteLine("Press the ENTER key to close this application.");
			s = Console.ReadLine();
		}
		//
		// Moves the supplied FileInfo instance to destPath.
		//
		private static void MoveFile(FileInfo fInfo) 
		{
			try 
			{
				fInfo.MoveTo(destPath);
				Console.WriteLine("File moved to ");
				Console.WriteLine(destPath);
			} catch (Exception ex) {
				DisplayException(ex);
			}
		}
		//
		// Ensures that the test directories 
		// and the file FromFile.xml all exist.
		// 
		private static void EnsureSourceFileExists() 
		{
			FileInfo fInfo = new FileInfo(sourcePath);
			string dirPath = fInfo.Directory.FullName;
			if (!Directory.Exists(dirPath)) 
			{
				Directory.CreateDirectory(dirPath);
			}
			if (File.Exists(destPath)) 
			{
				File.Delete(destPath);
			}
			Console.Write("Creating file ");
			Console.Write(fInfo.FullName);
			Console.WriteLine(".");
			try 
			{
				if (!fInfo.Exists) 
				{
					Console.WriteLine("Adding data to the file.");
					WriteFileContent(10);
					Console.WriteLine("Successfully created the file.");
				}
			} 
			catch (Exception ex) 
			{
				DisplayException(ex);
			} 
			finally 
			{
				dirPath = null;
			}
		}
		//
		// Creates and saves an Xml file to sourcePath.
		//
		private static void WriteFileContent(int totalElements) 
		{
			XmlDocument doc = new XmlDocument();
			doc.PreserveWhitespace = true;
			doc.AppendChild(doc.CreateXmlDeclaration("1.0", null, "yes"));
			doc.AppendChild(doc.CreateWhitespace("\r\n"));
			XmlElement root = doc.CreateElement("FileInfo.MoveTo");
			root.AppendChild(doc.CreateWhitespace("\r\n"));
			int index = 0;
			XmlElement elem;
			while (index < totalElements) 
			{

				elem = doc.CreateElement("MyElement");
				elem.SetAttribute("Index", index.ToString());
				elem.AppendChild(doc.CreateWhitespace("\r\n"));
				elem.AppendChild(doc.CreateTextNode(String.Format
					("MyElement at position {0}.", index)));
				elem.AppendChild(doc.CreateWhitespace("\r\n"));
				root.AppendChild(elem);
				root.AppendChild(doc.CreateWhitespace("\r\n"));
				index++;
			}
			doc.AppendChild(root);
			doc.AppendChild(doc.CreateWhitespace("\r\n"));
			doc.Save(sourcePath);
			elem = null;
			root = null;
			doc = null;
		}
		//
		// Displays FullName, CreationTime, and LastWriteTime of the supplied
		// FileInfo instance, then displays the text of the file.
		//
		private static void DisplayFileProperties(FileInfo fInfo) 
		{
			Console.WriteLine("The FileInfo instance shows these property values.");
			StreamReader reader = null;
			try 
			{
				Console.Write("FullName: ");
				Console.WriteLine(fInfo.FullName);
				Console.Write("CreationTime: ");
				Console.WriteLine(fInfo.CreationTime);
				Console.Write("LastWriteTime: ");
				Console.WriteLine(fInfo.LastWriteTime);
				Console.WriteLine();
				Console.WriteLine("File contents:");
				Console.WriteLine();
				reader = new StreamReader(fInfo.FullName);
				while (!reader.EndOfStream) 
				{
					Console.WriteLine(reader.ReadLine());
				}
				Console.WriteLine();
			} 
			catch (Exception ex) 
			{
				DisplayException(ex);
			} 
			finally 
			{
				if (reader != null) 
				{
					reader.Close();
				}
				reader = null;
			}
		}
		//
		// Deletes the test directory and all its files and subdirectories.
		//
		private static void DeleteFiles() 
		{
			try 
			{
				DirectoryInfo dInfo = new DirectoryInfo(Environment.GetFolderPath
					(Environment.SpecialFolder.MyDocuments) + "\\FileInfoTestDirectory");
				if (dInfo.Exists) 
				{
					dInfo.Delete(true);
					Console.WriteLine("Successfully deleted directories and files.");
				}
				dInfo = null;
			} 
			catch (Exception ex) 
			{
				DisplayException(ex);
			}
		}
		//
		// Displays information about the supplied Exception. This
		// code is not suitable for production applications.
		//
		private static void DisplayException(Exception ex) 
		{
			StringBuilder sb = new StringBuilder();
			sb.Append("An exception of type \"");
			sb.Append(ex.GetType().FullName);
			sb.Append("\" has occurred.\r\n");
			sb.Append(ex.Message);
			sb.Append("\r\nStack trace information:\r\n");
			MatchCollection matchCol = Regex.Matches(ex.StackTrace,
@"(at\s)(.+)(\.)([^\.]*)(\()([^\)]*)(\))((\sin\s)(.+)(:line )([\d]*))?");
			int L = matchCol.Count;
			string[] argList;
			Match matchObj;
			int y, K;
			for(int x = 0; x < L; x++) 
			{
				matchObj = matchCol[x];
				sb.Append(matchObj.Result("\r\n\r\n$1 $2$3$4$5"));
				argList = matchObj.Groups[6].Value.Split(new char[] { ',' });
				K = argList.Length;
				for (y = 0; y < K; y++) 
				{
					sb.Append("\r\n    ");
					sb.Append(argList[y].Trim().Replace(" ", "        "));
					sb.Append(',');
				}
				sb.Remove(sb.Length - 1, 1);
				sb.Append("\r\n)");
				if (0 < matchObj.Groups[8].Length) 
				{
					sb.Append(matchObj.Result("\r\n$10\r\nline $12"));
				}
			}
			argList = null;
			matchObj = null;
			matchCol = null;
			Console.WriteLine(sb.ToString());
			sb = null;
		}
	}
}
//This code produces output similar to the following; 
//results may vary based on the computer/file structure/etc.:
//
// Welcome.
// This application demonstrates the FileInfo.MoveTo method.
// Press any key to start.
//
//     Checking whether C:\Documents and Settings\MyComputer\My Documents\FileInfoTestDirectory\MoveFrom\FromFile.xml exists.
// Creating file C:\Documents and Settings\MyComputer\My Documents\FileInfoTestDirectory\MoveFrom\FromFile.xml.
// Adding data to the file.
// Successfully created the file.
// The FileInfo instance shows these property values.
// FullName: C:\Documents and Settings\MyComputer\My Documents\FileInfoTestDirectory\MoveFrom\FromFile.xml
// CreationTime: 4/18/2006 1:24:19 PM
// LastWriteTime: 4/18/2006 1:24:19 PM
//
// File contents:
//
// <?xml version="1.0" standalone="yes"?>
// <FileInfo.MoveTo>
// <MyElement Index="0">
// MyElement at position 0.
// </MyElement>
// <MyElement Index="1">
// MyElement at position 1.
// </MyElement>
// <MyElement Index="2">
// MyElement at position 2.
// </MyElement>
// <MyElement Index="3">
// MyElement at position 3.
// </MyElement>
// <MyElement Index="4">
// MyElement at position 4.
// </MyElement>
// <MyElement Index="5">
// MyElement at position 5.
// </MyElement>
// <MyElement Index="6">
// MyElement at position 6.
// </MyElement>
// <MyElement Index="7">
// MyElement at position 7.
// </MyElement>
// <MyElement Index="8">
// MyElement at position 8.
// </MyElement>
// <MyElement Index="9">
// MyElement at position 9.
// </MyElement>
// </FileInfo.MoveTo>

// Preparing to move the file to
// C:\Documents and Settings\MYComputer\My Documents\FileInfoTestDirectory\DestFile.xml.
// File moved to
// C:\Documents and Settings\MYComputer\My Documents\FileInfoTestDirectory\DestFile.xml
// The FileInfo instance shows these property values.
// FullName: C:\Documents and Settings\MYComputer\My Documents\FileInfoTestDirectory\DestFile.xml
// CreationTime: 4/18/2006 1:24:19 PM
// LastWriteTime: 4/18/2006 1:24:19 PM
// 
// File contents:
// 
// <?xml version="1.0" standalone="yes"?>
// <FileInfo.MoveTo>
// <MyElement Index="0">
// MyElement at position 0.
// </MyElement>
// <MyElement Index="1">
// MyElement at position 1.
// </MyElement>
// <MyElement Index="2">
// MyElement at position 2.
// </MyElement>
// <MyElement Index="3">
// MyElement at position 3.
// </MyElement>
// <MyElement Index="4">
// MyElement at position 4.
// </MyElement>
// <MyElement Index="5">
// MyElement at position 5.
// </MyElement>
// <MyElement Index="6">
// MyElement at position 6.
// </MyElement>
// <MyElement Index="7">
// MyElement at position 7.
// </MyElement>
// <MyElement Index="8">
// MyElement at position 8.
// </MyElement>
// <MyElement Index="9">
// MyElement at position 9.
// </MyElement>
// </FileInfo.MoveTo>
// 
// Preparing to delete directories.
// Successfully deleted directories and files.
// Press the ENTER key to close this application.





File.Delete Method (String)


Deletes the specified file.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static void Delete(
	string path
)

Parameters

path
Type: System.String

The name of the file to be deleted. Wildcard characters are not supported.

Exceptions

ExceptionCondition
ArgumentException

path is a zero-length string, contains only white space, or contains one or more invalid characters as defined by InvalidPathChars.

ArgumentNullException

path is null.

DirectoryNotFoundException

The specified path is invalid (for example, it is on an unmapped drive).

IOException

The specified file is in use.

-or-

There is an open handle on the file, and the operating system is Windows XP or earlier. This open handle can result from enumerating directories and files. For more information, see How to: Enumerate Directories and Files.

NotSupportedException

path is in an invalid format.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

UnauthorizedAccessException

The caller does not have the required permission.

-or-

The file is an executable file that is in use.

-or-

path is a directory.

-or-

path specified a read-only file.

Remarks

Specify a file name with any relative or absolute path information for the path parameter. Wildcard characters cannot be included. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

If the file to be deleted does not exist, no exception is thrown.

For a list of common I/O tasks, see Common I/O Tasks.

WinNt4Family

Delete does not delete a file that is open for normal I/O or a file that is memory mapped.

Examples

The following example copies groups of files to the C:\archives\2008 backup folder and then deletes them from the source folder.

string sourceDir = @"c:\current";
string backupDir = @"c:\archives\2008";

try
{
    string[] picList = Directory.GetFiles(sourceDir, "*.jpg");
    string[] txtList = Directory.GetFiles(sourceDir, "*.txt");

    // Copy picture files.
    foreach (string f in picList)
    {
        // Remove path from the file name.
        string fName = f.Substring(sourceDir.Length + 1);

        // Use the Path.Combine method to safely append the file name to the path.
        // Will overwrite if the destination file already exists.
        File.Copy(Path.Combine(sourceDir, fName), Path.Combine(backupDir, fName), true);
    }

    // Copy text files.
    foreach (string f in txtList)
    {

        // Remove path from the file name.
        string fName = f.Substring(sourceDir.Length + 1);

        try
        {
            // Will not overwrite if the destination file already exists.
            File.Copy(Path.Combine(sourceDir, fName), Path.Combine(backupDir, fName));
        }

        // Catch exception if the file was already copied.
        catch (IOException copyError)
        {
            Console.WriteLine(copyError.Message);
        }
    }

    // Delete source files that were copied.
    foreach (string f in txtList)
    {
        File.Delete(f);
    }
    foreach (string f in picList)
    {
        File.Delete(f);
    }
}

catch (DirectoryNotFoundException dirNotFound)
{
    Console.WriteLine(dirNotFound.Message);
}





FileInfo.Delete Method ()


Permanently deletes a file.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public override void Delete()

Exceptions

ExceptionCondition
IOException

The target file is open or memory-mapped on a computer running Microsoft Windows NT.

-or-

There is an open handle on the file, and the operating system is Windows XP or earlier. This open handle can result from enumerating directories and files. For more information, see How to: Enumerate Directories and Files.

SecurityException

The caller does not have the required permission.

UnauthorizedAccessException

The path is a directory.

Remarks

If the file does not exist, this method does nothing.

WinNt4Family

Delete does not delete a file that is open for normal I/O or a file that is memory-mapped.

Examples

The following example demonstrates the Delete method.

using System;
using System.IO;

class Test 
{

    public static void Main() 
    {
        string path = @"c:\MyTest.txt";
        FileInfo fi1 = new FileInfo(path);

        try 
        {
            using (StreamWriter sw = fi1.CreateText()) {}
            string path2 = path + "temp";
            FileInfo fi2 = new FileInfo(path2);

            //Ensure that the target does not exist.
            fi2.Delete();

            //Copy the file.
            fi1.CopyTo(path2);
            Console.WriteLine("{0} was copied to {1}.", path, path2);

            //Delete the newly created file.
            fi2.Delete();
            Console.WriteLine("{0} was successfully deleted.", path2);

        } 
        catch (Exception e) 
        {
            Console.WriteLine("The process failed: {0}", e.ToString());
        }
    }
}
//This code produces output similar to the following; 
//results may vary based on the computer/file structure/etc.:
//
//c:\MyTest.txt was copied to c:\MyTest.txttemp.
//c:\MyTest.txttemp was successfully deleted.

The following example creates, closes, and deletes a file.

using System;
using System.IO;

public class DeleteTest 
{
    public static void Main() 
    {
        // Create a reference to a file.
        FileInfo fi = new FileInfo("temp.txt");
        // Actually create the file.
        FileStream fs = fi.Create();
        // Modify the file as required, and then close the file.
        fs.Close();
        // Delete the file.
        fi.Delete();
    }
}





File.Copy Method (String, String)


Copies an existing file to a new file. Overwriting a file of the same name is not allowed.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static void Copy(
	string sourceFileName,
	string destFileName
)

Parameters

sourceFileName
Type: System.String

The file to copy.

destFileName
Type: System.String

The name of the destination file. This cannot be a directory or an existing file.

Exceptions

ExceptionCondition
UnauthorizedAccessException

The caller does not have the required permission.

ArgumentException

sourceFileName or destFileName is a zero-length string, contains only white space, or contains one or more invalid characters as defined by InvalidPathChars.

-or-

sourceFileName or destFileName specifies a directory.

ArgumentNullException

sourceFileName or destFileName is null.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

DirectoryNotFoundException

The path specified in sourceFileName or destFileName is invalid (for example, it is on an unmapped drive).

FileNotFoundException

sourceFileName was not found.

IOException

destFileName exists.

-or-

An I/O error has occurred.

NotSupportedException

sourceFileName or destFileName is in an invalid format.

Remarks

This method is equivalent to the Copy(String, String, Boolean) method overload with the overwrite parameter set to false.

The sourceFileName and destFileName parameters can specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see the Directory.GetCurrentDirectory method. This method does not support wildcard characters in the parameters.

The attributes of the original file are retained in the copied file.

Examples

The following example copies files to the C:\archives\2008 backup folder. It uses the two overloads of the Copy method as follows:

  • It first uses the File.Copy(String, String)method overload to copy text (.txt) files. The code demonstrates that this overload does not allow overwriting files that were already copied.

  • It then uses the File.Copy(String, String, Boolean) method overload to copy pictures (.jpg files). The code demonstrates that this overload does allow overwriting files that were already copied.

string sourceDir = @"c:\current";
string backupDir = @"c:\archives\2008";

try
{
    string[] picList = Directory.GetFiles(sourceDir, "*.jpg");
    string[] txtList = Directory.GetFiles(sourceDir, "*.txt");

    // Copy picture files.
    foreach (string f in picList)
    {
        // Remove path from the file name.
        string fName = f.Substring(sourceDir.Length + 1);

        // Use the Path.Combine method to safely append the file name to the path.
        // Will overwrite if the destination file already exists.
        File.Copy(Path.Combine(sourceDir, fName), Path.Combine(backupDir, fName), true);
    }

    // Copy text files.
    foreach (string f in txtList)
    {

        // Remove path from the file name.
        string fName = f.Substring(sourceDir.Length + 1);

        try
        {
            // Will not overwrite if the destination file already exists.
            File.Copy(Path.Combine(sourceDir, fName), Path.Combine(backupDir, fName));
        }

        // Catch exception if the file was already copied.
        catch (IOException copyError)
        {
            Console.WriteLine(copyError.Message);
        }
    }

    // Delete source files that were copied.
    foreach (string f in txtList)
    {
        File.Delete(f);
    }
    foreach (string f in picList)
    {
        File.Delete(f);
    }
}

catch (DirectoryNotFoundException dirNotFound)
{
    Console.WriteLine(dirNotFound.Message);
}





FileInfo.CopyTo Method (String)


Copies an existing file to a new file, disallowing the overwriting of an existing file.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public FileInfo CopyTo(
	string destFileName
)

Parameters

destFileName
Type: System.String

The name of the new file to copy to.

Return Value

Type: System.IO.FileInfo

A new file with a fully qualified path.

Exceptions

ExceptionCondition
ArgumentException

destFileName is empty, contains only white spaces, or contains invalid characters.

IOException

An error occurs, or the destination file already exists.

SecurityException

The caller does not have the required permission.

ArgumentNullException

destFileName is null.

UnauthorizedAccessException

A directory path is passed in, or the file is being moved to a different drive.

DirectoryNotFoundException

The directory specified in destFileName does not exist.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

NotSupportedException

destFileName contains a colon (:) within the string but does not specify the volume.

Remarks

Use the CopyTo method to allow overwriting of an existing file.

System_CAPS_cautionCaution

Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior

Examples

The following example demonstrates both overloads of the CopyTo method.

using System;
using System.IO;

class Test
{

    public static void Main()
    {
        string path = @"c:\SoureFile.txt";
        string path2 = @"c:\NewFile.txt";
        FileInfo fi1 = new FileInfo(path);
        FileInfo fi2 = new FileInfo(path2);

        try
        {
            // Create the source file.
            using (FileStream fs = fi1.Create()) { }

            //Ensure that the target file does not exist.
            if (File.Exists(path2))
            {
                fi2.Delete();
            }

            //Copy the file.f
            fi1.CopyTo(path2);
            Console.WriteLine("{0} was copied to {1}.", path, path2);
        }
        catch (IOException ioex)
        {
            Console.WriteLine(ioex.Message);
        }
    }
}

The following example demonstrates copying one file to another file, throwing an exception if the destination file already exists.

using System;
using System.IO;

public class CopyToTest 
{
    public static void Main() 
    {
        try
        {
            // Create a reference to a file, which might or might not exist.
            // If it does not exist, it is not yet created.
            FileInfo fi = new FileInfo("temp.txt");
            // Create a writer, ready to add entries to the file.
            StreamWriter sw = fi.AppendText();
            sw.WriteLine("Add as many lines as you like...");
            sw.WriteLine("Add another line to the output...");
            sw.Flush();
            sw.Close();
            // Get the information out of the file and display it.
            StreamReader sr = new StreamReader(fi.OpenRead());
            Console.WriteLine("This is the information in the first file:");
            while (sr.Peek() != -1)
                Console.WriteLine(sr.ReadLine());
            // Copy this file to another file. The file will not be overwritten if it already exists.
            FileInfo newfi = fi.CopyTo("newTemp.txt");
            // Get the information out of the new file and display it.
            sr = new StreamReader(newfi.OpenRead());
            Console.WriteLine("{0}This is the information in the second file:", Environment.NewLine);
            while (sr.Peek() != -1)
                Console.WriteLine(sr.ReadLine());
        }
        catch(Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}
//This code produces output similar to the following; 
//results may vary based on the computer/file structure/etc.:
//
//This is the information in the first file:
//Add as many lines as you like...
//Add another line to the output...

//This is the information in the second file:
//Add as many lines as you like...
//Add another line to the output...





FileInfo.Length Property


Gets the size, in bytes, of the current file.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public long Length { get; }

Property Value

Type: System.Int64

The size of the current file in bytes.

Exceptions

ExceptionCondition
IOException

Refresh cannot update the state of the file or directory.

FileNotFoundException

The file does not exist.

-or-

The Length property is called for a directory.

Remarks

The value of the Length property is pre-cached if the current instance of the FileInfo object was returned from any of the following DirectoryInfomethods:

To get the latest value, call the Refresh method.

Examples

The following example displays the size of the specified files.

// The following example displays the names and sizes
// of the files in the specified directory.
using System;
using System.IO;

public class FileLength
{
    public static void Main()
    {
        // Make a reference to a directory.
        DirectoryInfo di = new DirectoryInfo("c:\\");
        // Get a reference to each file in that directory.
        FileInfo[] fiArr = di.GetFiles();
        // Display the names and sizes of the files.
        Console.WriteLine("The directory {0} contains the following files:", di.Name);
        foreach (FileInfo f in fiArr)
            Console.WriteLine("The size of {0} is {1} bytes.", f.Name, f.Length);
    }
}
//This code produces output similar to the following; 
//results may vary based on the computer/file structure/etc.:
//
//The directory c:\ contains the following files:
//The size of MyComputer.log is 274 bytes.
//The size of AUTOEXEC.BAT is 0 bytes.
//The size of boot.ini is 211 bytes.
//The size of CONFIG.SYS is 0 bytes.
//The size of hiberfil.sys is 1072775168 bytes.
//The size of IO.SYS is 0 bytes.
//The size of MASK.txt is 2700 bytes.
//The size of mfc80.dll is 1093632 bytes.
//The size of mfc80u.dll is 1079808 bytes.
//The size of MSDOS.SYS is 0 bytes.
//The size of NTDETECT.COM is 47564 bytes.
//The size of ntldr is 250032 bytes.
//The size of pagefile.sys is 1610612736 bytes.
//The size of UpdatePatch.log is 22778 bytes.
//The size of UpdatePatch.txt is 30 bytes.
//The size of wt3d.ini is 234 bytes.






File.GetAttributes Method (String)


Gets the FileAttributes of the file on the path.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static FileAttributes GetAttributes(
	string path
)

Parameters

path
Type: System.String

The path to the file.

Return Value

Type: System.IO.FileAttributes

The FileAttributes of the file on the path.

Exceptions

ExceptionCondition
ArgumentException

path is empty, contains only white spaces, or contains invalid characters.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

NotSupportedException

path is in an invalid format.

FileNotFoundException

path represents a file and is invalid, such as being on an unmapped drive, or the file cannot be found.

DirectoryNotFoundException

path represents a directory and is invalid, such as being on an unmapped drive, or the directory cannot be found.

IOException

This file is being used by another process.

UnauthorizedAccessException

The caller does not have the required permission.

Remarks

The path parameter is permitted to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example demonstrates the GetAttributes and SetAttributes methods by applying the Archive and Hidden attributes to a file.

using System;
using System.IO;
using System.Text;

class Test 
{
    public static void Main() 
    {
        string path = @"c:\temp\MyTest.txt";

        // Create the file if it does not exist.
        if (!File.Exists(path)) 
        {
            File.Create(path);
        }

        FileAttributes attributes = File.GetAttributes(path);

        if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
        {
            // Show the file.
            attributes = RemoveAttribute(attributes, FileAttributes.Hidden);
            File.SetAttributes(path, attributes);
            Console.WriteLine("The {0} file is no longer hidden.", path);
        } 
        else 
        {
            // Hide the file.
            File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden);
            Console.WriteLine("The {0} file is now hidden.", path);
        }
    }

    private static FileAttributes RemoveAttribute(FileAttributes attributes, FileAttributes attributesToRemove)
    {
        return attributes & ~attributesToRemove;
    }
}






File.SetAttributes Method (String, FileAttributes)


Sets the specified FileAttributes of the file on the specified path.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static void SetAttributes(
	string path,
	FileAttributes fileAttributes
)

Parameters

path
Type: System.String

The path to the file.

fileAttributes
Type: System.IO.FileAttributes

A bitwise combination of the enumeration values.

Exceptions

ExceptionCondition
ArgumentException

path is empty, contains only white spaces, contains invalid characters, or the file attribute is invalid.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

NotSupportedException

path is in an invalid format.

DirectoryNotFoundException

The specified path is invalid, (for example, it is on an unmapped drive).

FileNotFoundException

The file cannot be found.

UnauthorizedAccessException

path specified a file that is read-only.

-or-

This operation is not supported on the current platform.

-or-

path specified a directory.

-or-

The caller does not have the required permission.

Remarks

The path parameter is permitted to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

Certain file attributes, such as Hidden and ReadOnly, can be combined. Other attributes, such as Normal, must be used alone.

It is not possible to change the compression status of a File object using the SetAttributes method.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example demonstrates the GetAttributes and SetAttributes methods by applying the Archive and Hidden attributes to a file.

using System;
using System.IO;
using System.Text;

class Test 
{
    public static void Main() 
    {
        string path = @"c:\temp\MyTest.txt";

        // Create the file if it does not exist.
        if (!File.Exists(path)) 
        {
            File.Create(path);
        }

        FileAttributes attributes = File.GetAttributes(path);

        if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
        {
            // Show the file.
            attributes = RemoveAttribute(attributes, FileAttributes.Hidden);
            File.SetAttributes(path, attributes);
            Console.WriteLine("The {0} file is no longer hidden.", path);
        } 
        else 
        {
            // Hide the file.
            File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden);
            Console.WriteLine("The {0} file is now hidden.", path);
        }
    }

    private static FileAttributes RemoveAttribute(FileAttributes attributes, FileAttributes attributesToRemove)
    {
        return attributes & ~attributesToRemove;
    }
}





File.Exists Method (String)


Determines whether the specified file exists.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static bool Exists(
	string path
)

Parameters

path
Type: System.String

The file to check.

Return Value

Type: System.Boolean

true if the caller has the required permissions and path contains the name of an existing file; otherwise, false. This method also returns false if path is null, an invalid path, or a zero-length string. If the caller does not have sufficient permissions to read the specified file, no exception is thrown and the method returns false regardless of the existence of path.

Remarks

The Exists method should not be used for path validation, this method merely checks if the file specified in path exists. Passing an invalid path to Exists returns false. To check whether the path contains any invalid characters, you can call the GetInvalidPathChars method to retrieve the characters that are invalid for the file system. You can also create a regular expression to test the whether the path is valid for your environment. For examples of acceptable paths, see File.

To check if a directory exists, see Directory.Exists.

Be aware that another process can potentially do something with the file in between the time you call the Exists method and perform another operation on the file, such as Delete.

The path parameter is permitted to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

If path describes a directory, this method returns false. Trailing spaces are removed from the path parameter before determining if the file exists.

The Exists method returns false if any error occurs while trying to determine if the specified file exists. This can occur in situations that raise exceptions such as passing a file name with invalid characters or too many characters, a failing or missing disk, or if the caller does not have permission to read the file.

Examples

The following example determines if a file exists.

string curFile = @"c:\temp\test.txt";
Console.WriteLine(File.Exists(curFile) ? "File exists." : "File does not exist.");





How to: Read and Write to a Newly Created Data File


The BinaryWriter and System.IO.BinaryReader classes are used for writing and reading data rather than character strings. The following example demonstrates how to write data to, and read data from, a new, empty file stream called Test.data. After creating the data file in the current directory, the associated BinaryWriter and BinaryReader objects are created, and the BinaryWriter object is used to write the integers 0 through 10 to Test.data, which leaves the file pointer at the end of the file. After setting the file pointer back to the origin, the BinaryReader object reads out the specified content.

using System;
using System.IO;

class MyStream
{
    private const string FILE_NAME = "Test.data";

    public static void Main()
    {
        if (File.Exists(FILE_NAME))
        {
            Console.WriteLine("{0} already exists!", FILE_NAME);
            return;
        }

        using (FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew))
        {
            using (BinaryWriter w = new BinaryWriter(fs))
            {
                for (int i = 0; i < 11; i++)
                {
                    w.Write(i);
                }
            }
        }
        
        using (FileStream fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read))
        {
            using (BinaryReader r = new BinaryReader(fs))
            {
                for (int i = 0; i < 11; i++)
                {
                    Console.WriteLine(r.ReadInt32());
                }
            }
        }
    }
}





Path.GetExtension Method (String)


Returns the extension of the specified path string.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static string GetExtension(
	string path
)

Parameters

path
Type: System.String

The path string from which to get the extension.

Return Value

Type: System.String

The extension of the specified path (including the period "."), or null, or String.Empty. If path is nullGetExtension returns null. If path does not have extension information, GetExtension returns String.Empty.

Exceptions

ExceptionCondition
ArgumentException

path contains one or more of the invalid characters defined in GetInvalidPathChars.

Remarks

The extension of path is obtained by searching path for a period (.), starting with the last character in path and continuing toward the start of path. If a period is found before a DirectorySeparatorChar or AltDirectorySeparatorChar character, the returned string contains the period and the characters after it; otherwise, Empty is returned.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following code example demonstrates using the GetExtension method on a Windows-based desktop platform.

string fileName = @"C:\mydir.old\myfile.ext";
string path = @"C:\mydir.old\";
string extension;

extension = Path.GetExtension(fileName);
Console.WriteLine("GetExtension('{0}') returns '{1}'", 
    fileName, extension);

extension = Path.GetExtension(path);
Console.WriteLine("GetExtension('{0}') returns '{1}'", 
    path, extension);

// This code produces output similar to the following:
//
// GetExtension('C:\mydir.old\myfile.ext') returns '.ext'
// GetExtension('C:\mydir.old\') returns ''





Path.GetFullPath Method (String)


Returns the absolute path for the specified path string.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static string GetFullPath(
	string path
)

Parameters

path
Type: System.String

The file or directory for which to obtain absolute path information.

Return Value

Type: System.String

The fully qualified location of path, such as "C:\MyFile.txt".

Exceptions

ExceptionCondition
ArgumentException

path is a zero-length string, contains only white space, or contains one or more of the invalid characters defined in GetInvalidPathChars.

-or-

The system could not retrieve the absolute path.

SecurityException

The caller does not have the required permissions.

ArgumentNullException

path is null.

NotSupportedException

path contains a colon (":") that is not part of a volume identifier (for example, "c:\").

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

Remarks

The .NET Framework does not support direct access to physical disks through paths that are device names, such as "\\.\PHYSICALDRIVE0 ".

The absolute path includes all information required to locate a file or directory on a system.

The file or directory specified by path is not required to exist. For example, if c:\temp\newdir is the current directory, calling GetFullPath on a file name such as test.txt returns c:\temp\newdir\test.txt. The file need not exist.

However, if path does exist, the caller must have permission to obtain path information for path. Note that unlike most members of the Path class, this method accesses the file system.

This method uses current directory and current volume information to fully qualify path. If you specify a file name only in pathGetFullPath returns the fully qualified path of the current directory.

If you pass in a short file name, it is expanded to a long file name.

If a path contains no significant characters it is invalid unless it contains one or more "." characters followed by any number of spaces, then it will be parsed as either "." or "..".

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following code example demonstrates the GetFullPath method on a Windows-based desktop platform.

string fileName = "myfile.ext";
string path1 = @"mydir";
string path2 = @"\mydir";
string fullPath;

fullPath = Path.GetFullPath(path1);
Console.WriteLine("GetFullPath('{0}') returns '{1}'", 
    path1, fullPath);

fullPath = Path.GetFullPath(fileName);
Console.WriteLine("GetFullPath('{0}') returns '{1}'", 
    fileName, fullPath);

fullPath = Path.GetFullPath(path2);
Console.WriteLine("GetFullPath('{0}') returns '{1}'", 
    path2, fullPath);

// Output is based on your current directory, except
// in the last case, where it is based on the root drive
// GetFullPath('mydir') returns 'C:\temp\Demo\mydir'
// GetFullPath('myfile.ext') returns 'C:\temp\Demo\myfile.ext'
// GetFullPath('\mydir') returns 'C:\mydir'





Path.GetFileName Method (String)


Returns the file name and extension of the specified path string.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static string GetFileName(
	string path
)

Parameters

path
Type: System.String

The path string from which to obtain the file name and extension.

Return Value

Type: System.String

The characters after the last directory character in path. If the last character of path is a directory or volume separator character, this method returns String.Empty. If path is null, this method returns null.

Exceptions

ExceptionCondition
ArgumentException

path contains one or more of the invalid characters defined in GetInvalidPathChars.

Remarks

The returned value is null if the file path is null.

The separator characters used to determine the start of the file name are DirectorySeparatorChar and AltDirectorySeparatorChar.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following code example demonstrates the behavior of the GetFileName method on a Windows-based desktop platform.

string fileName = @"C:\mydir\myfile.ext";
string path = @"C:\mydir\";
string result;

result = Path.GetFileName(fileName);
Console.WriteLine("GetFileName('{0}') returns '{1}'", 
    fileName, result);

result = Path.GetFileName(path);
Console.WriteLine("GetFileName('{0}') returns '{1}'", 
    path, result);

// This code produces output similar to the following:
//
// GetFileName('C:\mydir\myfile.ext') returns 'myfile.ext'
// GetFileName('C:\mydir\') returns ''





Path.ChangeExtension Method (String, String)


Changes the extension of a path string.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static string ChangeExtension(
	string path,
	string extension
)

Parameters

path
Type: System.String

The path information to modify. The path cannot contain any of the characters defined in GetInvalidPathChars.

extension
Type: System.String

The new extension (with or without a leading period). Specify null to remove an existing extension from path.

Return Value

Type: System.String

The modified path information.

On Windows-based desktop platforms, if path is null or an empty string (""), the path information is returned unmodified. If extension is null, the returned string contains the specified path with its extension removed. If path has no extension, and extension is not null, the returned path string contains extension appended to the end of path.

Exceptions

ExceptionCondition
ArgumentException

path contains one or more of the invalid characters defined in GetInvalidPathChars.

Remarks

If neither path nor extension contains a period (.), ChangeExtension adds the period.

The extension parameter can contain multiple periods and any valid path characters, and can be any length. If extension is null, the returned string contains the contents of path with the last period and all characters following it removed.

If extension is an empty string, the returned path string contains the contents of path with any characters following the last period removed.

If path does not have an extension and extension is not null, the returned string contains path followed by extension.

If extension is not null and does not contain a leading period, the period is added.

If path contains a multiple extension separated by multiple periods, the returned string contains the contents of path with the last period and all characters following it replaced by extension. For example, if path is "\Dir1\examples\pathtests.csx.txt" and extension is "cs", the modified path is "\Dir1\examples\pathtests.csx.cs".

It is not possible to verify that the returned results are valid in all scenarios. For example, if path is empty, extension is appended.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following code example demonstrates a use of the ChangeExtension method.

using System;
using System.IO;

public class PathSnippets
{

    public void ChangeExtension()
    {
        string goodFileName = @"C:\mydir\myfile.com.extension";
        string badFileName = @"C:\mydir\";
        string result;

        result = Path.ChangeExtension(goodFileName, ".old");
        Console.WriteLine("ChangeExtension({0}, '.old') returns '{1}'",
            goodFileName, result); 

        result = Path.ChangeExtension(goodFileName, "");
        Console.WriteLine("ChangeExtension({0}, '') returns '{1}'", 
            goodFileName, result); 

        result = Path.ChangeExtension(badFileName, ".old");
        Console.WriteLine("ChangeExtension({0}, '.old') returns '{1}'", 
            badFileName, result); 

        // This code produces output similar to the following:
        //
        // ChangeExtension(C:\mydir\myfile.com.extension, '.old') returns 'C:\mydir\myfile.com.old'
        // ChangeExtension(C:\mydir\myfile.com.extension, '') returns 'C:\mydir\myfile.com.'
        // ChangeExtension(C:\mydir\, '.old') returns 'C:\mydir\.old'





How to: Write Text to a File


This topic shows different ways you can write text to a file for .NET Framework applications or Windows 8.x Store apps. The following classes and methods are typically used to write text to a file:

The samples have been kept simple in order to focus on the task being performed. For this reason, the samples perform minimal error checking and exception handling, if any. A real-world application generally provides more robust error checking and exception handling.

The following example shows how to synchronously write text to a new file using the StreamWriter class, one line at a time. The new text file is saved to the user's My Documents folder. Because the StreamWriter object is declared and instantiated in a using statement, the Dispose method is invoked which automatically flushes and closes the stream.

        // Create a string array with the lines of text
        string[] lines = { "First line", "Second line", "Third line" };

        // Set a variable to the My Documents path.
        string mydocpath =
            Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        // Write the string array to a new file named "WriteLines.txt".
        using (StreamWriter outputFile = new StreamWriter(mydocpath + @"\WriteLines.txt")) {
            foreach (string line in lines)
                outputFile.WriteLine(line);
        }

The following example shows how to append text to an existing file using the StreamWriter class. It uses the same text file from the previous example.

        // Set a variable to the My Documents path.
        string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        // Append text to an existing file named "WriteLines.txt".
        using (StreamWriter outputFile = new StreamWriter(mydocpath + @"\WriteLines.txt", true)) {
            outputFile.WriteLine("Fourth Line");
        }

The following example shows how to asynchronously write text to a new file using the StreamWriter class. In order to invoke the WriteAsync method, the method call needs to be within an async method. The new text file is saved to the user's My Documents folder.

    static async void WriteTextAsync(string text)
    {
        // Set a variable to the My Documents path.
        string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        // Write the text asynchronously to a new file named "WriteTextAsync.txt".
        using (StreamWriter outputFile = new StreamWriter(mydocpath + @"\WriteTextAsync.txt")) {
            await outputFile.WriteAsync(text);
        }
    }

The following example shows how to write text to a new file and append new lines of text to the same file using the File class. The WriteAllText and AppendAllLines methods open and close the file automatically. If the path you provide to the WriteAllText method already exists, the file will be overwritten.

        // Create a string array with the lines of text
        string text = "First line" + Environment.NewLine;

        // Set a variable to the My Documents path.
        string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        // Write the text to a new file named "WriteFile.txt".
        File.WriteAllText(mydocpath + @"\WriteFile.txt", text);

        // Create a string array with the additional lines of text
        string[] lines = { "New line 1", "New line 2" };

        // Append new lines of text to the file
        File.AppendAllLines(mydocpath + @"\WriteFile.txt", lines);

The following example shows how to asynchronously write user input to a text file in a Windows 8.x Store app. Because of security considerations, opening a file from a Windows 8.x Store app typically requires the use of a FileOpenPicker control. In this example, the FileOpenPicker is filtered to show text files.

<Page  
    x:Class="OpenFileWindowsStore.MainPage"  
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    xmlns:local="using:OpenFileWindowsStore"  
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
    mc:Ignorable="d">  
  
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">  
        <Button Content="save text to a file" HorizontalAlignment="Left" Margin="103,417,0,0" VerticalAlignment="Top"   
                Width="329" Height="86" FontSize="35" Click="Button_Click"/>  
        <TextBox Name="UserInputTextBox"  FontSize="18" HorizontalAlignment="Left" Margin="106,146,0,0"   
                 TextWrapping="Wrap" Text="Write some text here, and select a file to write it to." VerticalAlignment="Top"   
                 Height="201" Width="558" AcceptsReturn="True"/>  
        <TextBlock Name="StatusTextBox" HorizontalAlignment="Left" Margin="106,570,0,147" TextWrapping="Wrap" Text="Status:"   
                   VerticalAlignment="Center" Height="51" Width="1074" FontSize="18" />  
    </Grid>  
</Page>  

using System;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Storage;
using System.Text;
using Windows.Storage.Pickers;
using Windows.UI.Popups; 

namespace OpenFileWindowsStore
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        // Create a file picker to open a file. Most file access in Windows Store Apps
        // requires the use of a file picker for security purposes.
        FileOpenPicker picker = new FileOpenPicker();
        private async void Button_Click(object sender, RoutedEventArgs e)
        {
         
           // Set properties on the file picker such as start location and the type 
            // of files to display.
            picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
            picker.ViewMode = PickerViewMode.List;
            picker.FileTypeFilter.Add(".txt");

            // Show picker enabling user to pick one file.
            StorageFile result = await picker.PickSingleFileAsync();

            if (result != null)
            {
                try
                {
                    // Use FileIO to replace the content of the text file
                    await FileIO.WriteTextAsync(result, UserInputTextBox.Text);

                    // Display a success message
                    StatusTextBox.Text = "Status: File saved successfully";
                }
                catch (Exception ex)
                {
                    // Display an error message
                    StatusTextBox.Text = "Status: error saving the file - " + ex.Message;
                }
            }
            else
                StatusTextBox.Text = "Status: User cancelled save operation";
        }
    }
}






Directory.CreateDirectory Method (String)


Creates all directories and subdirectories in the specified path unless they already exist.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static DirectoryInfo CreateDirectory(
	string path
)

Parameters

path
Type: System.String

The directory to create.

Return Value

Type: System.IO.DirectoryInfo

An object that represents the directory at the specified path. This object is returned regardless of whether a directory at the specified path already exists.

Exceptions

ExceptionCondition
IOException

The directory specified by path is a file.

-or-

The network name is not known.

UnauthorizedAccessException

The caller does not have the required permission.

ArgumentException

path is a zero-length string, contains only white space, or contains one or more invalid characters. You can query for invalid characters by using the GetInvalidPathChars method.

-or-

path is prefixed with, or contains, only a colon character (:).

ArgumentNullException

path is null.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters and file names must be less than 260 characters.

DirectoryNotFoundException

The specified path is invalid (for example, it is on an unmapped drive).

NotSupportedException

path contains a colon character (:) that is not part of a drive label ("C:\").

Remarks

Any and all directories specified in path are created, unless they already exist or unless some part of path is invalid. If the directory already exists, this method does not create a new directory, but it returns a DirectoryInfo object for the existing directory.

The path parameter specifies a directory path, not a file path.

Trailing spaces are removed from the end of the path parameter before creating the directory.

You can create a directory on a remote computer, on a share that you have write access to. UNC paths are supported; for example, you can specify the following for path\\2009\Archives\December in Visual Basic, and \\\\2009\\Archives\\December in C#.

Creating a directory with only the colon character (:) is not supported, and will cause a NotSupportedException to be thrown.

Examples

The following example creates and deletes the specified directory.

using System;
using System.IO;

class Test 
{
    public static void Main() 
    {
        // Specify the directory you want to manipulate.
        string path = @"c:\MyDir";

        try 
        {
            // Determine whether the directory exists.
            if (Directory.Exists(path)) 
            {
                Console.WriteLine("That path exists already.");
                return;
            }

            // Try to create the directory.
            DirectoryInfo di = Directory.CreateDirectory(path);
            Console.WriteLine("The directory was created successfully at {0}.", Directory.GetCreationTime(path));

            // Delete the directory.
            di.Delete();
            Console.WriteLine("The directory was deleted successfully.");
        } 
        catch (Exception e) 
        {
            Console.WriteLine("The process failed: {0}", e.ToString());
        } 
        finally {}
    }
}

To create the directory C:\Users\User1\Public\Html when the current directory is C:\Users\User1, use any of the following calls to ensure that the backslash is interpreted properly.

In Visual Basic:

Directory.CreateDirectory("Public\Html") 
    Directory.CreateDirectory("\Users\User1\Public\Html") 
    Directory.CreateDirectory("c:\Users\User1\Public\Html")

In C#:

Directory.CreateDirectory("Public\\Html");
    Directory.CreateDirectory("\\Users\\User1\\Public\\Html");
    Directory.CreateDirectory("c:\\Users\\User1\\Public\\Html");

In C++:

Directory::CreateDirectory("Public\\Html");
    Directory::CreateDirectory("\\Users\\User1\\Public\\Html");
    Directory::CreateDirectory("c:\\Users\\User1\\Public\\Html");






FileInfo.Directory Property


Gets an instance of the parent directory.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public DirectoryInfo Directory { get; }

Property Value

Type: System.IO.DirectoryInfo

DirectoryInfo object representing the parent directory of this file.

Exceptions

ExceptionCondition
DirectoryNotFoundException

The specified path is invalid, such as being on an unmapped drive.

SecurityException

The caller does not have the required permission.

Remarks

To get the parent directory as a string, use the DirectoryName property.

Examples

The following example opens or creates a file, determines its full path, and determines and displays the full contents of the directory.

using System;
using System.IO;

public class DirectoryTest 
{
    public static void Main() 
    {

        // Open an existing file, or create a new one.
        FileInfo fi = new FileInfo("temp.txt");

        // Determine the full path of the file just created.
        DirectoryInfo di = fi.Directory;

        // Figure out what other entries are in that directory.
        FileSystemInfo[] fsi = di.GetFileSystemInfos();

        Console.WriteLine("The directory '{0}' contains the following files and directories:", di.FullName);

        // Print the names of all the files and subdirectories of that directory.
        foreach (FileSystemInfo info in fsi)
            Console.WriteLine(info.Name);
    }
}
//This code produces output similar to the following; 
//results may vary based on the computer/file structure/etc.:
//
//The directory 'C:\Visual Studio 2005\release' contains the following files 
//and directories:
//TempPE
//fileinfodirectory.exe
//fileinfodirectory.pdb
//newTemp.txt
//temp.txt






DirectoryInfo.CreateSubdirectory Method (String)


Creates a subdirectory or subdirectories on the specified path. The specified path can be relative to this instance of the DirectoryInfo class.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public DirectoryInfo CreateSubdirectory(
	string path
)

Parameters

path
Type: System.String

The specified path. This cannot be a different disk volume or Universal Naming Convention (UNC) name.

Return Value

Type: System.IO.DirectoryInfo

The last directory specified in path.

Exceptions

ExceptionCondition
ArgumentException

path does not specify a valid file path or contains invalid DirectoryInfo characters.

ArgumentNullException

path is null.

DirectoryNotFoundException

The specified path is invalid, such as being on an unmapped drive.

IOException

The subdirectory cannot be created.

-or-

A file or directory already has the name specified by path.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters. The specified path, file name, or both are too long.

SecurityException

The caller does not have code access permission to create the directory.

-or-

The caller does not have code access permission to read the directory described by the returned DirectoryInfo object. This can occur when the path parameter describes an existing directory.

NotSupportedException

path contains a colon character (:) that is not part of a drive label ("C:\").

Remarks

Any and all directories specified in path are created, unless some part of path is invalid. The path parameter specifies a directory path, not a file path. If the subdirectory already exists, this method does nothing.

System_CAPS_noteNote

Path names are limited to 248 characters.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example demonstrates creating a subdirectory. In this example, the created directories are removed once created. Therefore, to test this sample, comment out the delete lines in the code.

using System;
using System.IO;

public class CreateSubTest 
{
    public static void Main() 
    {
        // Create a reference to a directory.
        DirectoryInfo di = new DirectoryInfo("TempDir");

        // Create the directory only if it does not already exist.
        if (di.Exists == false)
            di.Create();

        // Create a subdirectory in the directory just created.
        DirectoryInfo dis = di.CreateSubdirectory("SubDir");

        // Process that directory as required.
        // ...

        // Delete the subdirectory.
        dis.Delete(true);

        // Delete the directory.
        di.Delete(true);
    }
}






Directory.Move Method (String, String)


Moves a file or a directory and its contents to a new location.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static void Move(
	string sourceDirName,
	string destDirName
)

Parameters

sourceDirName
Type: System.String

The path of the file or directory to move.

destDirName
Type: System.String

The path to the new location for sourceDirName. If sourceDirName is a file, then destDirName must also be a file name.

Exceptions

ExceptionCondition
IOException

An attempt was made to move a directory to a different volume.

-or-

destDirName already exists.

-or-

The sourceDirName and destDirName parameters refer to the same file or directory.

-or-

The directory or a file within it is being used by another process.

UnauthorizedAccessException

The caller does not have the required permission.

ArgumentException

sourceDirName or destDirName is a zero-length string, contains only white space, or contains one or more invalid characters. You can query for invalid characters with the GetInvalidPathChars method.

ArgumentNullException

sourceDirName or destDirName is null.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters and file names must be less than 260 characters.

DirectoryNotFoundException

The path specified by sourceDirName is invalid (for example, it is on an unmapped drive).

Remarks

This method creates a new directory with the name specified by destDirName and moves the contents of sourceDirName to the newly created destination directory. If you try to move a directory to a directory that already exists, an IOException will occur. For example, an exception will occur if you try to move c:\mydir to c:\public, and c:\public already exists. Alternatively, you could specify "c:\\public\\mydir" as the destDirName parameter, provided that "mydir" does not exist under "c:\\public", or specify a new directory name such as "c:\\newdir".

The sourceDirName and destDirName arguments are permitted to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

Trailing spaces are removed from the end of the path parameters before moving the directory.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example demonstrates how to move a directory and all its files to a new directory. The original directory no longer exists after it has been moved.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string sourceDirectory = @"C:\source";
            string destinationDirectory = @"C:\destination";

            try
            {
                Directory.Move(sourceDirectory, destinationDirectory);  
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}





DirectoryInfo.MoveTo Method (String)


Moves a DirectoryInfo instance and its contents to a new path.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public void MoveTo(
	string destDirName
)

Parameters

destDirName
Type: System.String

The name and path to which to move this directory. The destination cannot be another disk volume or a directory with the identical name. It can be an existing directory to which you want to add this directory as a subdirectory.

Exceptions

ExceptionCondition
ArgumentNullException

destDirName is null.

ArgumentException

destDirName is an empty string (''").

IOException

An attempt was made to move a directory to a different volume.

-or-

destDirName already exists.

-or-

You are not authorized to access this path.

-or-

The directory being moved and the destination directory have the same name.

SecurityException

The caller does not have the required permission.

DirectoryNotFoundException

The destination directory cannot be found.

Remarks

This method throws an IOException if, for example, you try to move c:\mydir to c:\public, and c:\public already exists. You must specify "c:\\public\\mydir" as the destDirName parameter, or specify a new directory name such as "c:\\newdir".

This method permits moving a directory to a read-only directory. The read/write attribute of neither directory is affected.

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example demonstrates moving a directory.

using System;
using System.IO;

public class MoveToTest 
{
    public static void Main() 
    {

        // Make a reference to a directory.
        DirectoryInfo di = new DirectoryInfo("TempDir");

        // Create the directory only if it does not already exist.
        if (di.Exists == false)
            di.Create();

        // Create a subdirectory in the directory just created.
        DirectoryInfo dis = di.CreateSubdirectory("SubDir");

        // Move the main directory. Note that the contents move with the directory.
        if (Directory.Exists("NewTempDir") == false)
            di.MoveTo("NewTempDir");

        try 
        {
            // Attempt to delete the subdirectory. Note that because it has been
            // moved, an exception is thrown.
            dis.Delete(true);
        } 
        catch (Exception) 
        {
            // Handle this exception in some way, such as with the following code:
            // Console.WriteLine("That directory does not exist.");
        }

        // Point the DirectoryInfo reference to the new directory.
        //di = new DirectoryInfo("NewTempDir");

        // Delete the directory.
        //di.Delete(true);
    }
}






How to: Copy Directories


This example demonstrates how to use I/O classes to synchronously copy the contents of a directory to another location. In this example, the user can specify whether to also copy the subdirectories. If the subdirectories are copied, the method in this example recursively copies them by calling itself on each subsequent subdirectory until there are no more to copy.

For an example of copying files asynchronously, see Asynchronous File I/O.

using System;
using System.IO;

class DirectoryCopyExample
{
    static void Main()
    {
        // Copy from the current directory, include subdirectories.
        DirectoryCopy(".", @".\temp", true);
    }

    private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
    {
        // Get the subdirectories for the specified directory.
        DirectoryInfo dir = new DirectoryInfo(sourceDirName);

        if (!dir.Exists)
        {
            throw new DirectoryNotFoundException(
                "Source directory does not exist or could not be found: "
                + sourceDirName);
        }

        DirectoryInfo[] dirs = dir.GetDirectories();
        // If the destination directory doesn't exist, create it.
        if (!Directory.Exists(destDirName))
        {
            Directory.CreateDirectory(destDirName);
        }
        
        // Get the files in the directory and copy them to the new location.
        FileInfo[] files = dir.GetFiles();
        foreach (FileInfo file in files)
        {
            string temppath = Path.Combine(destDirName, file.Name);
            file.CopyTo(temppath, false);
        }

        // If copying subdirectories, copy them and their contents to new location.
        if (copySubDirs)
        {
            foreach (DirectoryInfo subdir in dirs)
            {
                string temppath = Path.Combine(destDirName, subdir.Name);
                DirectoryCopy(subdir.FullName, temppath, copySubDirs);
            }
        }
    }
}






Directory.Delete Method (String)


Deletes an empty directory from a specified path.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static void Delete(
	string path
)

Parameters

path
Type: System.String

The name of the empty directory to remove. This directory must be writable and empty.

Exceptions

ExceptionCondition
IOException

A file with the same name and location specified by path exists.

-or-

The directory is the application's current working directory.

-or-

The directory specified by path is not empty.

-or-

The directory is read-only or contains a read-only file.

-or-

The directory is being used by another process.

UnauthorizedAccessException

The caller does not have the required permission.

ArgumentException

path is a zero-length string, contains only white space, or contains one or more invalid characters. You can query for invalid characters by using the GetInvalidPathChars method.

ArgumentNullException

path is null.

PathTooLongException

The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters and file names must be less than 260 characters.

DirectoryNotFoundException

path does not exist or could not be found.

-or-

The specified path is invalid (for example, it is on an unmapped drive).

Remarks

This method behaves identically to Delete(String, Boolean) with false specified for the second parameter.

The path parameter may specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory. To obtain the current working directory, see GetCurrentDirectory.

Trailing spaces are removed from the end of the path parameter before deleting the directory.

This method throws an IOException if the directory specified in the path parameter contains files or subdirectories.

The path parameter is not case-sensitive.

In some cases, if you have the specified directory open in File Explorer, the Delete method may not be able to delete it.

Examples

The following example shows how to create a new directory and subdirectory, and then delete only the subdirectory.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string subPath = @"C:\NewDirectory\NewSubDirectory";

            try
            {
                Directory.CreateDirectory(subPath);   
                Directory.Delete(subPath);

                bool directoryExists = Directory.Exists(@"C:\NewDirectory");
                bool subDirectoryExists = Directory.Exists(subPath);

                Console.WriteLine("top-level directory exists: " + directoryExists);
                Console.WriteLine("sub-directory exists: " + subDirectoryExists);
            }
            catch (Exception e)
            {
                Console.WriteLine("The process failed: {0}", e.Message);
            }
        }
    }
}






DirectoryInfo.Delete Method ()


Deletes this DirectoryInfo if it is empty.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public override void Delete()

Exceptions

ExceptionCondition
UnauthorizedAccessException

The directory contains a read-only file.

DirectoryNotFoundException

The directory described by this DirectoryInfo object does not exist or could not be found.

IOException

The directory is not empty.

-or-

The directory is the application's current working directory.

-or-

There is an open handle on the directory, and the operating system is Windows XP or earlier. This open handle can result from enumerating directories. For more information, see How to: Enumerate Directories and Files.

SecurityException

The caller does not have the required permission.

Remarks

For a list of common I/O tasks, see Common I/O Tasks.

Examples

The following example throws an exception if you attempt to delete a directory that is not empty.

using System;
using System.IO;

class Test 
{
    public static void Main() 
    {
        // Specify the directories you want to manipulate.
        DirectoryInfo di1 = new DirectoryInfo(@"c:\MyDir");

        try 
        {
            // Create the directories.
            di1.Create();
            di1.CreateSubdirectory("temp");

            //This operation will not be allowed because there are subdirectories.
            Console.WriteLine("I am about to attempt to delete {0}", di1.Name);
            di1.Delete();
            Console.WriteLine("The Delete operation was successful, which was unexpected.");
        } 
        catch (Exception) 
        {
            Console.WriteLine("The Delete operation failed as expected.");
        } 
        finally {}
    }
}






How to: Enumerate Directories and Files


You can enumerate directories and files by using methods that return an enumerable collection of strings of their names. You can also use methods that return an enumerable collection of DirectoryInfoFileInfo, or FileSystemInfo objects. Enumerable collections provide better performance than arrays when you work with large collections of directories and files.

You can also use enumerable collections obtained from these methods to supply the IEnumerable<T> parameter for constructors of collection classes such as the List<T> class.

If you want to obtain only the names of directories or files, use the enumeration methods of the Directory class. If you want to obtain other properties of directories or files, use the DirectoryInfo and FileSystemInfo classes.

The following table provides a guide to the methods that return enumerable collections.

To enumerateEnumerable collection to returnMethod to use
DirectoriesDirectory namesDirectory.EnumerateDirectories
Directory information (DirectoryInfo)DirectoryInfo.EnumerateDirectories
FilesFile namesDirectory.EnumerateFiles
File information (FileInfo)DirectoryInfo.EnumerateFiles
File system informationFile system entriesDirectory.EnumerateFileSystemEntries
File system information (FileSystemInfo)DirectoryInfo.EnumerateFileSystemInfos

Although you can immediately enumerate all the files in the subdirectories of a parent directory by using the AllDirectories search option provided by the SearchOption enumeration, unauthorized access exceptions (UnauthorizedAccessException) may cause the enumeration to be incomplete. If these exceptions are possible, you can catch them and continue by first enumerating directories and then enumerating files.

To enumerate directory names

  • Use the Directory.EnumerateDirectories(String) method to obtain a list of the top-level directory names in a specified path.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    
    class Program
    {
        private static void Main(string[] args)
        {
            try
            {
                string dirPath = @"\\archives\2009\reports";
    
                List<string> dirs = new List<string>(Directory.EnumerateDirectories(dirPath));
                        
                foreach (var dir in dirs)
                {
                    Console.WriteLine("{0}", dir.Substring(dir.LastIndexOf("\\") + 1));
                }
                Console.WriteLine("{0} directories found.",  dirs.Count);
            }
            catch (UnauthorizedAccessException UAEx)
            {
                Console.WriteLine(UAEx.Message);
            }
            catch (PathTooLongException PathEx)
            {
                Console.WriteLine(PathEx.Message);
            }
        }
    }
    

To enumerate file names in a directory and subdirectories

  • Use the Directory.EnumerateFiles(String, String, SearchOption) method to search a directory and (optionally) its subdirectories, and to obtain a list of file names that match a specified search pattern.

    using System;
    using System.IO;
    using System.Linq;
    
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var files = from file in Directory.EnumerateFiles(@"c:\", "*.txt", SearchOption.AllDirectories)
                            from line in File.ReadLines(file)
                            where line.Contains("Microsoft")
                            select new
                            {
                                File = file,
                                Line = line
                            };
    
                foreach (var f in files)
                {
                    Console.WriteLine("{0}\t{1}", f.File, f.Line);
                }
    			Console.WriteLine("{0} files found.", files.Count().ToString());
            }
            catch (UnauthorizedAccessException UAEx)
            {
                Console.WriteLine(UAEx.Message);
            }
            catch (PathTooLongException PathEx)
            {
                Console.WriteLine(PathEx.Message);
            }
        }
    }
    

To enumerate a collection of DirectoryInfo objects

  • Use the DirectoryInfo.EnumerateDirectories method to obtain a collection of top-level directories.

    DirectoryInfo dirPrograms = new DirectoryInfo(@"c:\program files");
    DateTime StartOf2009 = new DateTime(2009, 01, 01);
    
    var dirs = from dir in dirPrograms.EnumerateDirectories()
                where dir.CreationTimeUtc < StartOf2009
                select new
                {
                    ProgDir = dir,
                };
    
    foreach (var di in dirs)
    {
        Console.WriteLine("{0}", di.ProgDir.Name);
    }
    

To enumerate a collection of FileInfo objects in all directories

  • Use the DirectoryInfo.EnumerateFiles method to obtain a collection of files that match a specified search pattern in all directories. This example first enumerates the top-level directories to catch possible unauthorized access exceptions, and then enumerates the files.

    using System;
    using System.IO;
    
    class Program
    {
        static void Main(string[] args)
        {
            DirectoryInfo diTop = new DirectoryInfo(@"d:\");
            try
            {
                foreach (var fi in diTop.EnumerateFiles())
                {
                    try
                    {
                        // Display each file over 10 MB;
                        if (fi.Length > 10000000)
                        {
                            Console.WriteLine("{0}\t\t{1}", fi.FullName, fi.Length.ToString("N0"));
                        }
                    }
                    catch (UnauthorizedAccessException UnAuthTop)
                    {
                        Console.WriteLine("{0}", UnAuthTop.Message);
                    }
                }
                
                foreach (var di in diTop.EnumerateDirectories("*"))
                {
                    try
                    {
                        foreach (var fi in di.EnumerateFiles("*", SearchOption.AllDirectories))
                        {
                            try
                            {
                                // Display each file over 10 MB;
                                if (fi.Length > 10000000)
                                {
                                    Console.WriteLine("{0}\t\t{1}",  fi.FullName, fi.Length.ToString("N0"));
                                }
                            }
                            catch (UnauthorizedAccessException UnAuthFile)
                            {
                                Console.WriteLine("UnAuthFile: {0}", UnAuthFile.Message);
                            }
                        }
                    }
                    catch (UnauthorizedAccessException UnAuthSubDir)
                    {
                        Console.WriteLine("UnAuthSubDir: {0}", UnAuthSubDir.Message);
                    }
                }
            }
            catch (DirectoryNotFoundException DirNotFound)
            {
                Console.WriteLine("{0}", DirNotFound.Message);
            }
            catch (UnauthorizedAccessException UnAuthDir)
            {
                Console.WriteLine("UnAuthDir: {0}", UnAuthDir.Message);
            }
            catch (PathTooLongException LongPath)
            {
                Console.WriteLine("{0}", LongPath.Message);
            }
        }
    }






How to: Enumerate Directories and Files


You can enumerate directories and files by using methods that return an enumerable collection of strings of their names. You can also use methods that return an enumerable collection of DirectoryInfo, FileInfo, or FileSystemInfo objects. Enumerable collections provide better performance than arrays when you work with large collections of directories and files.

You can also use enumerable collections obtained from these methods to supply the IEnumerable<T> parameter for constructors of collection classes such as the List<T> class.

If you want to obtain only the names of directories or files, use the enumeration methods of the Directory class. If you want to obtain other properties of directories or files, use the DirectoryInfo and FileSystemInfo classes.

The following table provides a guide to the methods that return enumerable collections.

To enumerateEnumerable collection to returnMethod to use
DirectoriesDirectory namesDirectory.EnumerateDirectories
Directory information (DirectoryInfo)DirectoryInfo.EnumerateDirectories
FilesFile namesDirectory.EnumerateFiles
File information (FileInfo)DirectoryInfo.EnumerateFiles
File system informationFile system entriesDirectory.EnumerateFileSystemEntries
File system information (FileSystemInfo)DirectoryInfo.EnumerateFileSystemInfos

Although you can immediately enumerate all the files in the subdirectories of a parent directory by using the AllDirectories search option provided by the SearchOption enumeration, unauthorized access exceptions (UnauthorizedAccessException) may cause the enumeration to be incomplete. If these exceptions are possible, you can catch them and continue by first enumerating directories and then enumerating files.

To enumerate directory names

  • Use the Directory.EnumerateDirectories(String) method to obtain a list of the top-level directory names in a specified path.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    
    class Program
    {
        private static void Main(string[] args)
        {
            try
            {
                string dirPath = @"\\archives\2009\reports";
    
                List<string> dirs = new List<string>(Directory.EnumerateDirectories(dirPath));
                        
                foreach (var dir in dirs)
                {
                    Console.WriteLine("{0}", dir.Substring(dir.LastIndexOf("\\") + 1));
                }
                Console.WriteLine("{0} directories found.",  dirs.Count);
            }
            catch (UnauthorizedAccessException UAEx)
            {
                Console.WriteLine(UAEx.Message);
            }
            catch (PathTooLongException PathEx)
            {
                Console.WriteLine(PathEx.Message);
            }
        }
    }
    

To enumerate file names in a directory and subdirectories

  • Use the Directory.EnumerateFiles(String, String, SearchOption) method to search a directory and (optionally) its subdirectories, and to obtain a list of file names that match a specified search pattern.

    using System;
    using System.IO;
    using System.Linq;
    
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var files = from file in Directory.EnumerateFiles(@"c:\", "*.txt", SearchOption.AllDirectories)
                            from line in File.ReadLines(file)
                            where line.Contains("Microsoft")
                            select new
                            {
                                File = file,
                                Line = line
                            };
    
                foreach (var f in files)
                {
                    Console.WriteLine("{0}\t{1}", f.File, f.Line);
                }
    			Console.WriteLine("{0} files found.", files.Count().ToString());
            }
            catch (UnauthorizedAccessException UAEx)
            {
                Console.WriteLine(UAEx.Message);
            }
            catch (PathTooLongException PathEx)
            {
                Console.WriteLine(PathEx.Message);
            }
        }
    }
    

To enumerate a collection of DirectoryInfo objects

  • Use the DirectoryInfo.EnumerateDirectories method to obtain a collection of top-level directories.

    DirectoryInfo dirPrograms = new DirectoryInfo(@"c:\program files");
    DateTime StartOf2009 = new DateTime(2009, 01, 01);
    
    var dirs = from dir in dirPrograms.EnumerateDirectories()
                where dir.CreationTimeUtc < StartOf2009
                select new
                {
                    ProgDir = dir,
                };
    
    foreach (var di in dirs)
    {
        Console.WriteLine("{0}", di.ProgDir.Name);
    }
    

To enumerate a collection of FileInfo objects in all directories

  • Use the DirectoryInfo.EnumerateFiles method to obtain a collection of files that match a specified search pattern in all directories. This example first enumerates the top-level directories to catch possible unauthorized access exceptions, and then enumerates the files.

    using System;
    using System.IO;
    
    class Program
    {
        static void Main(string[] args)
        {
            DirectoryInfo diTop = new DirectoryInfo(@"d:\");
            try
            {
                foreach (var fi in diTop.EnumerateFiles())
                {
                    try
                    {
                        // Display each file over 10 MB;
                        if (fi.Length > 10000000)
                        {
                            Console.WriteLine("{0}\t\t{1}", fi.FullName, fi.Length.ToString("N0"));
                        }
                    }
                    catch (UnauthorizedAccessException UnAuthTop)
                    {
                        Console.WriteLine("{0}", UnAuthTop.Message);
                    }
                }
                
                foreach (var di in diTop.EnumerateDirectories("*"))
                {
                    try
                    {
                        foreach (var fi in di.EnumerateFiles("*", SearchOption.AllDirectories))
                        {
                            try
                            {
                                // Display each file over 10 MB;
                                if (fi.Length > 10000000)
                                {
                                    Console.WriteLine("{0}\t\t{1}",  fi.FullName, fi.Length.ToString("N0"));
                                }
                            }
                            catch (UnauthorizedAccessException UnAuthFile)
                            {
                                Console.WriteLine("UnAuthFile: {0}", UnAuthFile.Message);
                            }
                        }
                    }
                    catch (UnauthorizedAccessException UnAuthSubDir)
                    {
                        Console.WriteLine("UnAuthSubDir: {0}", UnAuthSubDir.Message);
                    }
                }
            }
            catch (DirectoryNotFoundException DirNotFound)
            {
                Console.WriteLine("{0}", DirNotFound.Message);
            }
            catch (UnauthorizedAccessException UnAuthDir)
            {
                Console.WriteLine("UnAuthDir: {0}", UnAuthDir.Message);
            }
            catch (PathTooLongException LongPath)
            {
                Console.WriteLine("{0}", LongPath.Message);
            }
        }
    }






Directory Class


Exposes static methods for creating, moving, and enumerating through directories and subdirectories. This class cannot be inherited.

To browse the .NET Framework source code for this type, see the Reference Source.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Inheritance Hierarchy

System.Object
  System.IO.Directory

Remarks

System_CAPS_noteNote

To view the .NET Framework source code for this type, see the Reference Source. You can browse through the source code online, download the reference for offline viewing, and step through the sources (including patches and updates) during debugging; see instructions.

Use the Directory class for typical operations such as copying, moving, renaming, creating, and deleting directories.

The static methods of the Directory class perform security checks on all methods. If you are going to reuse an object several times, consider using the corresponding instance method of DirectoryInfo instead, because the security check will not always be necessary.

If you are performing only one directory-related action, it might be more efficient to use a static Directory method rather than a corresponding DirectoryInfo instance method. Most Directory methods require the path to the directory that you are manipulating.

System_CAPS_noteNote

In members that accept a string path parameter, that path must be well-formed or an exception is raised. For example, if a path is fully qualified but begins with a space (" c:\temp"), the path string isn't trimmed, so the path is considered malformed and an exception is raised. In addition, a path or a combination of paths cannot be fully qualified twice. For example, "c:\temp c:\windows" also raises an exception. Ensure that your paths are well-formed when using methods that accept a path string. For more information see Path.

In members that accept a path, the path can refer to a file or a directory. You can use a full path, a relative path, or a Universal Naming Convention (UNC) path for a server and share name. For example, all the following are acceptable paths:

  • "c:\\MyDir" in C#, or "c:\MyDir" in Visual Basic.

  • "MyDir\\MySubdir" in C#, or "MyDir\MySubDir" in Visual Basic.

  • "\\\\MyServer\\MyShare" in C#, or "\\MyServer\MyShare" in Visual Basic.

By default, full read/write access to new directories is granted to all users. However, the app must have the correct security to access existing directories.

To demand permissions for a directory and all its subdirectories, end the path string with the directory separator character. (For example, "C:\Temp\" grants access to C:\Temp\ and all its subdirectories.) To demand permissions only for a specific directory, end the path string with a period. (For example, "C:\Temp\." grants access only to C:\Temp\, not to its subdirectories.)

In members that accept a searchPattern parameter, the search string can be any combination of literal characters and two wildcard characters; * and ?. This parameter does not recognize regular expressions. For more information, see the EnumerateDirectories(String, String) method or any other method that uses the searchPattern parameter.

For a list of common I/O tasks, see Common I/O Tasks.

Directory and DirectoryInfo are not supported for use in Windows Store apps. For information about how to access files and folders in Windows Store apps, see Accessing data and files (Windows Store apps).

Examples

The following example shows how to retrieve all the text files from a directory and move them to a new directory. After the files are moved, they no longer exist in the original directory.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string sourceDirectory = @"C:\current";
            string archiveDirectory = @"C:\archive";

            try
            {
                var txtFiles = Directory.EnumerateFiles(sourceDirectory, "*.txt");

                foreach (string currentFile in txtFiles)
                {
                    string fileName = currentFile.Substring(sourceDirectory.Length + 1);
                    Directory.Move(currentFile, Path.Combine(archiveDirectory, fileName));
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}

The following example demonstrates how to use the EnumerateFiles method to retrieve a collection of text files from a directory, and then use that collection in a query to find all the lines that contain "Example".

using System;
using System.IO;
using System.Linq;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string archiveDirectory = @"C:\archive";

            var files = from retrievedFile in Directory.EnumerateFiles(archiveDirectory, "*.txt", SearchOption.AllDirectories)
                        from line in File.ReadLines(retrievedFile)
                        where line.Contains("Example")
                        select new
                        {
                            File = retrievedFile,
                            Line = line
                        };

            foreach (var f in files)
            {
                Console.WriteLine("{0} contains {1}", f.File, f.Line);
            }
            Console.WriteLine("{0} lines found.", files.Count().ToString());
        }
    }
}

The following example demonstrates how to move a directory and all its files to a new directory. The original directory no longer exists after it has been moved.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string sourceDirectory = @"C:\source";
            string destinationDirectory = @"C:\destination";

            try
            {
                Directory.Move(sourceDirectory, destinationDirectory);  
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}






Directory.Exists Method (String)


Determines whether the given path refers to an existing directory on disk.

Namespace:   System.IO
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public static bool Exists(
	string path
)

Parameters

path
Type: System.String

The path to test.

Return Value

Type: System.Boolean

true if path refers to an existing directory; false if the directory does not exist or an error occurs when trying to determine if the specified directory exists.

Remarks

The path parameter is permitted to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory.

Trailing spaces are removed from the end of the path parameter before checking whether the directory exists.

The path parameter is not case-sensitive.

If you do not have at a minimum read-only permission to the directory, the Exists method will return false.

The Exists method returns false if any error occurs while trying to determine if the specified file exists. This can occur in situations that raise exceptions such as passing a file name with invalid characters or too many characters, a failing or missing disk, or if the caller does not have permission to read the file.

Examples

The following example takes an array of file or directory names on the command line, determines what kind of name it is, and processes it appropriately.

// For File.Exists, Directory.Exists
using System;
using System.IO;
using System.Collections;

public class RecursiveFileProcessor 
{
    public static void Main(string[] args) 
    {
        foreach(string path in args) 
        {
            if(File.Exists(path)) 
            {
                // This path is a file
                ProcessFile(path); 
            }               
            else if(Directory.Exists(path)) 
            {
                // This path is a directory
                ProcessDirectory(path);
            }
            else 
            {
                Console.WriteLine("{0} is not a valid file or directory.", path);
            }        
        }        
    }


    // Process all files in the directory passed in, recurse on any directories 
    // that are found, and process the files they contain.
    public static void ProcessDirectory(string targetDirectory) 
    {
        // Process the list of files found in the directory.
        string [] fileEntries = Directory.GetFiles(targetDirectory);
        foreach(string fileName in fileEntries)
            ProcessFile(fileName);

        // Recurse into subdirectories of this directory.
        string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
        foreach(string subdirectory in subdirectoryEntries)
            ProcessDirectory(subdirectory);
    }

    // Insert logic for processing found files here.
    public static void ProcessFile(string path) 
    {
        Console.WriteLine("Processed file '{0}'.", path);	    
    }
}






How to: Read Characters from a String


The following code examples show how to read characters synchronously and asynchronously from a string.

This example reads 13 characters synchronously from a string, stores them in an array, and displays those characters. It then reads the remaining characters in the string, stores them in the array starting at the sixth element, and displays the contents of the array.

using System;
using System.IO;

public class CharsFromStr
{
    public static void Main()
    {
        string str = "Some number of characters";
        char[] b = new char[str.Length];

        using (StringReader sr = new StringReader(str))
        {
            // Read 13 characters from the string into the array.
            sr.Read(b, 0, 13);
            Console.WriteLine(b);

            // Read the rest of the string starting at the current string position.
            // Put in the array starting at the 6th array member.
            sr.Read(b, 5, str.Length - 13);
            Console.WriteLine(b);
        }
    }
}
// The example has the following output:
//
// Some number o
// Some f characters

The next example reads all the characters asynchronously from a TextBox control, and stores them in an array. It then asynchronously writes each letter or white space character on a separate line followed by a line break to a TextBlock control.

using System;
using System.Text;
using System.Windows;
using System.IO;

namespace WpfApplication
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void ReadButton_Click(object sender, RoutedEventArgs e)
        {
            char[] charsRead = new char[UserInput.Text.Length];
            using (StringReader reader = new StringReader(UserInput.Text))
            {
                await reader.ReadAsync(charsRead, 0, UserInput.Text.Length);
            }

            StringBuilder reformattedText = new StringBuilder();
            using (StringWriter writer = new StringWriter(reformattedText))
            {
                foreach (char c in charsRead)
                {
                    if (char.IsLetter(c) || char.IsWhiteSpace(c))
                    {
                        await writer.WriteLineAsync(char.ToLower(c));
                    }
                }
            }
            Result.Text = reformattedText.ToString();
        }
    }
}






How to: Write Characters to a String


The following code examples write characters synchronously and asynchronously from a character array into a string.

The following example writes 5 characters synchronously from an array to a string.

using System;
using System.IO;
using System.Text;

public class CharsToStr
{
    public static void Main()
    {
        StringBuilder sb = new StringBuilder("Start with a string and add from ");
        char[] b = { 'c', 'h', 'a', 'r', '.', ' ', 'B', 'u', 't', ' ', 'n', 'o', 't', ' ', 'a', 'l', 'l' };

        using (StringWriter sw = new StringWriter(sb))
        {
            // Write five characters from the array into the StringBuilder.
            sw.Write(b, 0, 5);
            Console.WriteLine(sb);
        }
    }
}
// The example has the following output:
//
// Start with a string and add from char.


The next example reads all the characters asynchronously from a TextBox control, and stores them in an array. It then asynchronously writes each letter or white space character on a separate line followed by a line break to a TextBlock control.

using System;
using System.Text;
using System.Windows;
using System.IO;

namespace WpfApplication
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void ReadButton_Click(object sender, RoutedEventArgs e)
        {
            char[] charsRead = new char[UserInput.Text.Length];
            using (StringReader reader = new StringReader(UserInput.Text))
            {
                await reader.ReadAsync(charsRead, 0, UserInput.Text.Length);
            }

            StringBuilder reformattedText = new StringBuilder();
            using (StringWriter writer = new StringWriter(reformattedText))
            {
                foreach (char c in charsRead)
                {
                    if (char.IsLetter(c) || char.IsWhiteSpace(c))
                    {
                        await writer.WriteLineAsync(char.ToLower(c));
                    }
                }
            }
            Result.Text = reformattedText.ToString();
        }
    }
}






How to: Add or Remove Access Control List Entries


To add or remove Access Control List (ACL) entries to or from a file, the FileSecurity or DirectorySecurity object must be obtained from the file or directory, modified, and then applied back to the file or directory.

To add or remove an ACL entry from a File

  1. Call the GetAccessControl method to get a FileSecurity object that contains the current ACL entries of a file.

  2. Add or remove ACL entries from the FileSecurity object returned from step 1.

  3. Pass the FileSecurity object to the SetAccessControl method to apply the changes.

To add or remove an ACL entry from a Directory

  1. Call the GetAccessControl method to get a DirectorySecurity object that contains the current ACL entries of a directory.

  2. Add or remove ACL entries from the DirectorySecurity object returned from step 1.

  3. Pass the DirectorySecurity object to the SetAccessControl method to apply the changes.

using System;
using System.IO;
using System.Security.AccessControl;

namespace FileSystemExample
{
    class FileExample
    {
        public static void Main()
        {
            try
            {
                string fileName = "test.xml";

                Console.WriteLine("Adding access control entry for "
                    + fileName);

                // Add the access control entry to the file.
                AddFileSecurity(fileName, @"DomainName\AccountName",
                    FileSystemRights.ReadData, AccessControlType.Allow);

                Console.WriteLine("Removing access control entry from "
                    + fileName);

                // Remove the access control entry from the file.
                RemoveFileSecurity(fileName, @"DomainName\AccountName",
                    FileSystemRights.ReadData, AccessControlType.Allow);

                Console.WriteLine("Done.");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

        // Adds an ACL entry on the specified file for the specified account.
        public static void AddFileSecurity(string fileName, string account,
            FileSystemRights rights, AccessControlType controlType)
        {


            // Get a FileSecurity object that represents the
            // current security settings.
            FileSecurity fSecurity = File.GetAccessControl(fileName);

            // Add the FileSystemAccessRule to the security settings.
            fSecurity.AddAccessRule(new FileSystemAccessRule(account,
                rights, controlType));

            // Set the new access settings.
            File.SetAccessControl(fileName, fSecurity);

        }

        // Removes an ACL entry on the specified file for the specified account.
        public static void RemoveFileSecurity(string fileName, string account,
            FileSystemRights rights, AccessControlType controlType)
        {

            // Get a FileSecurity object that represents the
            // current security settings.
            FileSecurity fSecurity = File.GetAccessControl(fileName);

            // Remove the FileSystemAccessRule from the security settings.
            fSecurity.RemoveAccessRule(new FileSystemAccessRule(account,
                rights, controlType));

            // Set the new access settings.
            File.SetAccessControl(fileName, fSecurity);

        }
    }
}

You must supply a valid user or group account to run this example. This example uses a File object; however, the same procedure is used for the FileInfoDirectory, and DirectoryInfo classes.






How to: Compress and Extract Files


The System.IO.Compression namespace contains the following types for compressing and decompressing files and streams. You can also use these types to read and modify the contents of a compressed file:

The following examples show some of the functions you can perform when working with compressed files.

This example shows how to create and extract a compressed file that has a .zip file name extension by using the ZipFile class. It compresses the contents of a folder into a new .zip file and then extracts that content to a new folder. To use the ZipFile class, you must reference the System.IO.Compression.FileSystem assembly in your project.

using System;
using System.IO;
using System.IO.Compression;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string startPath = @"c:\example\start";
            string zipPath = @"c:\example\result.zip";
            string extractPath = @"c:\example\extract";

            ZipFile.CreateFromDirectory(startPath, zipPath);

            ZipFile.ExtractToDirectory(zipPath, extractPath);
        }
    }
}

The next example shows how to iterate through the contents of an existing .zip file and extract files that have a .txt extension. It uses the ZipArchive class to access an existing .zip file, and the ZipArchiveEntry class to inspect the individual entries in the compressed file. It uses an extension method (ExtractToFile) for the ZipArchiveEntry object. The extension method is available in the System.IO.Compression.ZipFileExtensions class. To use the ZipFileExtensions class, you must reference the System.IO.Compression.FileSystem assembly in your project.

using System;
using System.IO;
using System.IO.Compression;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string zipPath = @"c:\example\start.zip";
            string extractPath = @"c:\example\extract";

            using (ZipArchive archive = ZipFile.OpenRead(zipPath))
            {
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    if (entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
                    {
                        entry.ExtractToFile(Path.Combine(extractPath, entry.FullName));
                    }
                }
            } 
        }
    }
}

The next example uses the ZipArchive class to access an existing .zip file, and adds a new file to the compressed file. The new file gets compressed when you add it to the existing .zip file.

using System;
using System.IO;
using System.IO.Compression;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            using (FileStream zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open))
            {
                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                {
                    ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
                    using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                    {
                            writer.WriteLine("Information about this package.");
                            writer.WriteLine("========================");
                    }
                }
            }
        }
    }
}

You can also use the GZipStream and DeflateStream classes to compress and decompress data. They use the same compression algorithm. Compressed GZipStream objects that are written to a file that has an extension of .gz can be decompressed by using many common tools in addition to the methods provided by GZipStream. This example shows how to compress and decompress a directory of files by using the GZipStream class.

using System;
using System.IO;
using System.IO.Compression;

namespace zip
{
    public class Program
    {
        private static string directoryPath = @"c:\temp";
        public static void Main()
        {
            DirectoryInfo directorySelected = new DirectoryInfo(directoryPath);
            Compress(directorySelected);

            foreach (FileInfo fileToDecompress in directorySelected.GetFiles("*.gz"))
            {
                Decompress(fileToDecompress);
            }
        }

        public static void Compress(DirectoryInfo directorySelected)
        {
            foreach (FileInfo fileToCompress in directorySelected.GetFiles())
            {
                using (FileStream originalFileStream = fileToCompress.OpenRead())
                {
                    if ((File.GetAttributes(fileToCompress.FullName) & 
                       FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
                    {
                        using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
                        {
                            using (GZipStream compressionStream = new GZipStream(compressedFileStream, 
                               CompressionMode.Compress))
                            {
                                originalFileStream.CopyTo(compressionStream);

                            }
                        }
                        FileInfo info = new FileInfo(directoryPath + "\\" + fileToCompress.Name + ".gz");
                        Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
                        fileToCompress.Name, fileToCompress.Length.ToString(), info.Length.ToString());
                    }

                }
            }
        }

        public static void Decompress(FileInfo fileToDecompress)
        {
            using (FileStream originalFileStream = fileToDecompress.OpenRead())
            {
                string currentFileName = fileToDecompress.FullName;
                string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);

                using (FileStream decompressedFileStream = File.Create(newFileName))
                {
                    using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
                    {
                        decompressionStream.CopyTo(decompressedFileStream);
                        Console.WriteLine("Decompressed: {0}", fileToDecompress.Name);
                    }
                }
            }
        }
    }
}






Composing Streams


A backing store is a storage medium, such as a disk or memory. Each different backing store implements its own stream as an implementation of the Stream class. Each stream type reads and writes bytes from and to its given backing store. Streams that connect to backing stores are called base streams. Base streams have constructors that have the parameters necessary to connect the stream to the backing store. For example, FileStream has constructors that specify a path parameter, which specifies how the file will be shared by processes, and so on.

The design of the System.IO classes provides simplified stream composing. Base streams can be attached to one or more pass-through streams that provide the functionality you want. A reader or writer can be attached to the end of the chain so that the preferred types can be read or written easily.

The following code example creates a FileStream around the existing MyFile.txt in order to buffer MyFile.txt. (Note that FileStreams are buffered by default.) Next, a StreamReader is created to read characters from the FileStream, which is passed to the StreamReader as its constructor argument. ReadLine reads until Peek finds no more characters.

using System;
using System.IO;

public class CompBuf
{
    private const string FILE_NAME = "MyFile.txt";

    public static void Main()
    {
        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 an instance of StreamReader that can read
        // characters from the FileStream.
        using (StreamReader sr = new StreamReader(fsIn))
        {
            string input;
            // While not at the end of the file, read lines from the file.
            while (sr.Peek() > -1)
            {
                input = sr.ReadLine();
                Console.WriteLine(input);
            }
        }
    }
}

The following code example creates a FileStream around the existing MyFile.txt in order to buffer MyFile.txt. (Note that FileStreams are buffered by default.) Next, a BinaryReader is created to read bytes from the FileStream, which is passed to the BinaryReader as its constructor argument. ReadByte reads until PeekChar finds no more bytes.

using System;
using System.IO;

public class ReadBuf
{
    private const string FILE_NAME = "MyFile.txt";

    public static void Main()
    {
        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 an instance of BinaryReader that can
        // read bytes from the FileStream.
        using (BinaryReader br = new BinaryReader(f))
        {
            byte input;
            // While not at the end of the file, read lines from the file.
            while (br.PeekChar() > -1 )
            {
                input = br.ReadByte();
                Console.WriteLine(input);
            }
        }
    }
}












'프로그래밍 > C#' 카테고리의 다른 글

Developing Windows Service Applications  (0) 2017.04.02
Events  (0) 2017.03.29
Thread 관련  (0) 2017.03.05
Sockets  (0) 2017.03.02
Using the Visual Studio Development Environment for C#  (0) 2017.02.14
:
Posted by 지훈2
2017. 3. 5. 04:52

Thread 관련 프로그래밍/C#2017. 3. 5. 04:52


  1. ManualResetEvent
  2. AutoResetEvent
  3. AutoResetEvent 클래스 (http://www.csharpstudy.com)
  4. ManualResetEvent 클래스 (http://www.csharpstudy.com)
  5. CountdownEvent 클래스 (http://www.csharpstudy.com)




AutoResetEvent

1. Set() 을 호출하면 Wait 하고 있는 쓰레드를 중에서 처음 한개만 통과시키고 나머지는 대기시킴

2. 다시 Set() 호출하면 그 다음 쓰레드를 통과시키고 나머지는 대기시킴.


ManualResetEvent

1. Set() 을 호출하면 Wait 하고 있는 쓰레드 모두 통과시킴. (계속 통과 상태)

2. Reset() 을 호출하면 다시 대기 상태



ManualResetEvent Class


https://msdn.microsoft.com/en-us/library/system.threading.manualresetevent(v=vs.110).aspx


Notifies one or more waiting threads that an event has occurred. This class cannot be inherited.

Namespace:   System.Threading
Assembly:  mscorlib (in mscorlib.dll)

Inheritance Hierarchy

System.Object
  System.MarshalByRefObject
    System.Threading.WaitHandle
      System.Threading.EventWaitHandle
        System.Threading.ManualResetEvent




Remarks

In the .NET Framework version 2.0, ManualResetEvent derives from the new EventWaitHandle class. A ManualResetEvent is functionally equivalent to an EventWaitHandle created with EventResetMode.ManualReset.

System_CAPS_noteNote

Unlike the ManualResetEvent class, the EventWaitHandle class provides access to named system synchronization events.

ManualResetEvent allows threads to communicate with each other by signaling. Typically, this communication concerns a task which one thread must complete before other threads can proceed.

When a thread begins an activity that must complete before other threads proceed, it calls Reset to put ManualResetEvent in the non-signaled state. This thread can be thought of as controlling the ManualResetEvent. Threads that call WaitOne on the ManualResetEvent will block, awaiting the signal. When the controlling thread completes the activity, it calls Set to signal that the waiting threads can proceed. All waiting threads are released.

Once it has been signaled, ManualResetEvent remains signaled until it is manually reset. That is, calls to WaitOne return immediately.

You can control the initial state of a ManualResetEvent by passing a Boolean value to the constructor, true if the initial state is signaled and false otherwise.

ManualResetEvent can also be used with the staticWaitAll and WaitAny methods.

For more information about thread synchronization mechanisms, see ManualResetEvent and ManualResetEventSlim in the conceptual documentation.

Examples

The following example demonstrates how ManualResetEvent works. The example starts with a ManualResetEvent in the unsignaled state (that is, false is passed to the constructor). The example creates three threads, each of which blocks on the ManualResetEvent by calling its WaitOne method. When the user presses the Enter key, the example calls the Set method, which releases all three threads. Contrast this with the behavior of the AutoResetEvent class, which releases threads one at a time, resetting automatically after each release.

Pressing the Enter key again demonstrates that the ManualResetEvent remains in the signaled state until its Reset method is called: The example starts two more threads. These threads do not block when they call the WaitOne method, but instead run to completion.

Pressing the Enter key again causes the example to call the Reset method and to start one more thread, which blocks when it calls WaitOne. Pressing the Enter key one final time calls Set to release the last thread, and the program ends.

using System;
using System.Threading;

public class Example
{
    // mre is used to block and release threads manually. It is
    // created in the unsignaled state.
    private static ManualResetEvent mre = new ManualResetEvent(false);

    static void Main()
    {
        Console.WriteLine("\nStart 3 named threads that block on a ManualResetEvent:\n");

        for(int i = 0; i <= 2; i++)
        {
            Thread t = new Thread(ThreadProc);
            t.Name = "Thread_" + i;
            t.Start();
        }

        Thread.Sleep(500);
        Console.WriteLine("\nWhen all three threads have started, press Enter to call Set()" +
                          "\nto release all the threads.\n");
        Console.ReadLine();

        mre.Set();

        Thread.Sleep(500);
        Console.WriteLine("\nWhen a ManualResetEvent is signaled, threads that call WaitOne()" +
                          "\ndo not block. Press Enter to show this.\n");
        Console.ReadLine();

        for(int i = 3; i <= 4; i++)
        {
            Thread t = new Thread(ThreadProc);
            t.Name = "Thread_" + i;
            t.Start();
        }

        Thread.Sleep(500);
        Console.WriteLine("\nPress Enter to call Reset(), so that threads once again block" +
                          "\nwhen they call WaitOne().\n");
        Console.ReadLine();

        mre.Reset();

        // Start a thread that waits on the ManualResetEvent.
        Thread t5 = new Thread(ThreadProc);
        t5.Name = "Thread_5";
        t5.Start();

        Thread.Sleep(500);
        Console.WriteLine("\nPress Enter to call Set() and conclude the demo.");
        Console.ReadLine();

        mre.Set();

        // If you run this example in Visual Studio, uncomment the following line:
        //Console.ReadLine();
    }


    private static void ThreadProc()
    {
        string name = Thread.CurrentThread.Name;

        Console.WriteLine(name + " starts and calls mre.WaitOne()");

        mre.WaitOne();

        Console.WriteLine(name + " ends.");
    }
}

/* This example produces output similar to the following:

Start 3 named threads that block on a ManualResetEvent:

Thread_0 starts and calls mre.WaitOne()
Thread_1 starts and calls mre.WaitOne()
Thread_2 starts and calls mre.WaitOne()

When all three threads have started, press Enter to call Set()
to release all the threads.


Thread_2 ends.
Thread_0 ends.
Thread_1 ends.

When a ManualResetEvent is signaled, threads that call WaitOne()
do not block. Press Enter to show this.


Thread_3 starts and calls mre.WaitOne()
Thread_3 ends.
Thread_4 starts and calls mre.WaitOne()
Thread_4 ends.

Press Enter to call Reset(), so that threads once again block
when they call WaitOne().


Thread_5 starts and calls mre.WaitOne()

Press Enter to call Set() and conclude the demo.

Thread_5 ends.
 */





AutoResetEvent


https://msdn.microsoft.com/en-us/library/system.threading.autoresetevent(v=vs.110).aspx


Notifies a waiting thread that an event has occurred. This class cannot be inherited.

Namespace:   System.Threading
Assembly:  mscorlib (in mscorlib.dll)

Inheritance Hierarchy

System.Object
  System.MarshalByRefObject
    System.Threading.WaitHandle
      System.Threading.EventWaitHandle
        System.Threading.AutoResetEvent




Remarks

AutoResetEvent allows threads to communicate with each other by signaling. Typically, you use this class when threads need exclusive access to a resource.

System_CAPS_importantImportant

This type implements the IDisposable interface. When you have finished using the type, you should dispose of it either directly or indirectly. To dispose of the type directly, call its Dispose method in a try/catch block. To dispose of it indirectly, use a language construct such as using (in C#) or Using (in Visual Basic). For more information, see the “Using an Object that Implements IDisposable” section in the IDisposable interface topic.

A thread waits for a signal by calling WaitOne on the AutoResetEvent. If the AutoResetEvent is in the non-signaled state, the thread blocks, waiting for the thread that currently controls the resource to signal that the resource is available by calling Set.

Calling Set signals AutoResetEvent to release a waiting thread. AutoResetEvent remains signaled until a single waiting thread is released, and then automatically returns to the non-signaled state. If no threads are waiting, the state remains signaled indefinitely.

If a thread calls WaitOne while the AutoResetEvent is in the signaled state, the thread does not block. The AutoResetEvent releases the thread immediately and returns to the non-signaled state.

System_CAPS_importantImportant

There is no guarantee that every call to the Set method will release a thread. If two calls are too close together, so that the second call occurs before a thread has been released, only one thread is released. It is as if the second call did not happen. Also, if Set is called when there are no threads waiting and the AutoResetEvent is already signaled, the call has no effect.

You can control the initial state of an AutoResetEvent by passing a Boolean value to the constructor: true if the initial state is signaled and false otherwise.

AutoResetEvent can also be used with the staticWaitAll and WaitAny methods.

For more information about thread synchronization mechanisms, see AutoResetEvent in the conceptual documentation.

Beginning with the .NET Framework version 2.0, AutoResetEvent derives from the new EventWaitHandle class. An AutoResetEvent is functionally equivalent to an EventWaitHandle created with EventResetMode.AutoReset.

System_CAPS_noteNote

Unlike the AutoResetEvent class, the EventWaitHandle class provides access to named system synchronization events.

Examples

The following example shows how to use AutoResetEvent to release one thread at a time, by calling the Set method (on the base class) each time the user presses the Enter key. The example starts three threads, which wait on an AutoResetEvent that was created in the signaled state. The first thread is released immediately, because the AutoResetEvent is already in the signaled state. This resets the AutoResetEvent to the non-signaled state, so that subsequent threads block. The blocked threads are not released until the user releases them one at a time by pressing the Enter key.

After the threads are released from the first AutoResetEvent, they wait on another AutoResetEvent that was created in the non-signaled state. All three threads block, so the Set method must be called three times to release them all.

using System;
using System.Threading;

// Visual Studio: Replace the default class in a Console project with 
//                the following class.
class Example
{
    private static AutoResetEvent event_1 = new AutoResetEvent(true);
    private static AutoResetEvent event_2 = new AutoResetEvent(false);

    static void Main()
    {
        Console.WriteLine("Press Enter to create three threads and start them.\r\n" +
                          "The threads wait on AutoResetEvent #1, which was created\r\n" +
                          "in the signaled state, so the first thread is released.\r\n" +
                          "This puts AutoResetEvent #1 into the unsignaled state.");
        Console.ReadLine();

        for (int i = 1; i < 4; i++)
        {
            Thread t = new Thread(ThreadProc);
            t.Name = "Thread_" + i;
            t.Start();
        }
        Thread.Sleep(250);

        for (int i = 0; i < 2; i++)
        {
            Console.WriteLine("Press Enter to release another thread.");
            Console.ReadLine();
            event_1.Set();
            Thread.Sleep(250);
        }

        Console.WriteLine("\r\nAll threads are now waiting on AutoResetEvent #2.");
        for (int i = 0; i < 3; i++)
        {
            Console.WriteLine("Press Enter to release a thread.");
            Console.ReadLine();
            event_2.Set();
            Thread.Sleep(250);
        }

        // Visual Studio: Uncomment the following line.
        //Console.Readline();
    }

    static void ThreadProc()
    {
        string name = Thread.CurrentThread.Name;

        Console.WriteLine("{0} waits on AutoResetEvent #1.", name);
        event_1.WaitOne();
        Console.WriteLine("{0} is released from AutoResetEvent #1.", name);

        Console.WriteLine("{0} waits on AutoResetEvent #2.", name);
        event_2.WaitOne();
        Console.WriteLine("{0} is released from AutoResetEvent #2.", name);

        Console.WriteLine("{0} ends.", name);
    }
}

/* This example produces output similar to the following:

Press Enter to create three threads and start them.
The threads wait on AutoResetEvent #1, which was created
in the signaled state, so the first thread is released.
This puts AutoResetEvent #1 into the unsignaled state.

Thread_1 waits on AutoResetEvent #1.
Thread_1 is released from AutoResetEvent #1.
Thread_1 waits on AutoResetEvent #2.
Thread_3 waits on AutoResetEvent #1.
Thread_2 waits on AutoResetEvent #1.
Press Enter to release another thread.

Thread_3 is released from AutoResetEvent #1.
Thread_3 waits on AutoResetEvent #2.
Press Enter to release another thread.

Thread_2 is released from AutoResetEvent #1.
Thread_2 waits on AutoResetEvent #2.

All threads are now waiting on AutoResetEvent #2.
Press Enter to release a thread.

Thread_2 is released from AutoResetEvent #2.
Thread_2 ends.
Press Enter to release a thread.

Thread_1 is released from AutoResetEvent #2.
Thread_1 ends.
Press Enter to release a thread.

Thread_3 is released from AutoResetEvent #2.
Thread_3 ends.
 */


1. signaled 상태에서는 Set() 호출해도 non-signaled로 안됨

2. non-signaled 상태에서는 Set() 호출하면 signaled로 됨





AutoResetEvent 클래스


http://www.csharpstudy.com/Threads/autoresetevent.aspx



신호(Signal)에 의한 쓰레드 동기화 

쓰레드 동기화에는 Locking과 같이 공유 리소스에 락을 걸어 쓰레드 접근을 제한하는 방식 (Monitor, Mutex, Semaphore 등)이외에 대기 중인 쓰레드에게 외부에서 신호(Signal)을 보냄으로써 쓰레드 흐름을 통제하는 방식도 있다. 이러한 신호(Signaling) 방식으로 많이 사용되는 것으로 AutoResetEvent, ManualResetEvent, CountdownEvent, Wait/Pulse 등이 있다. (NOTE: 여기서의 Event는 윈도우 프로그래밍에서 말하는 이벤트와 전혀 다른 개념이다. 여기서의 Event는 쓰레드 동기화에 사용되는 OS 리소스이다) 



AutoResetEvent 클래스 

AutoResetEvent는 이 이벤트를 기다리는 쓰레드들에게 신호를 보내 하나의 쓰레드만 통과시키고 나머지 쓰레드들은 다음 신호를 기다리게 한다. 이는 흡사 유료 주차장 자동 게이트와 같이 한 차량이 통과하면 자동으로 게이트가 닫히는 것과 같다. 쓰레드 A가 AutoResetEvent 객체의 WaitOne() 메소드를 써서 대기하고 있다가, 다른 쓰레드 B에서 이 AutoResetEvent 객체의 Set() 메서드를 호출하면, 쓰레드 A는 대기 상태를 해제하고 계속 다음 문장을 실행할 수 있게 된다. 

예제

using System;
using System.Threading;

namespace MultiThrdApp
{
    class Program
    {
        // AutoResetEvent 객체 필드
        static AutoResetEvent autoEvent = new AutoResetEvent(false);

        static void Main()
        {
            // 쓰레드 A 생성
            Thread A = new Thread(Run);
            A.Name = "Thread A";
            A.Start();            

            // 메인쓰레드            
            Thread.Sleep(3000); //3초 대기
            autoEvent.Set(); // 쓰레드 A에 신호
        }

        static void Run()
        {
            string name = Thread.CurrentThread.Name;
            Console.WriteLine("{0}: Run Start", name);

            // AutoResetEvent 신호 대기
            autoEvent.WaitOne();            
            Console.WriteLine("{0} : DoWork", name);

            Console.WriteLine("{0}: Run End", name);
        }
    }
}




AutoResetEvent 활용 예제 

AutoResetEvent 활용한 한 예제로 교통 신호를 통제하는 예를 들어 보자. 실제 교통 신호보다 좀 단순화하여 상하방향과 좌우방향만을 각각 통제하는 2개의 신호만이 있다고 가정하자. 상하방향 신호가 켜지면 상하방향 차량들이 모두 통과되고 (즉, 상하방향 Queue에 있는 모두 데이타 처리), 더 이상 차량이 없으면 좌우방향에 신호를 보내 좌우방향에 밀려 있는 차량들을 통과한다 (즉, 좌우방향 Queue에 있는 모두 데이타 처리). 아래 예제는 2개의 쓰레드가 각각 상하, 좌우 데이타 처리를 위한 메서드들을 실행하고, 2개의 AutoResetEvent 객체를 신호로 사용하고 있다. 각 쓰레드의 메서드는 먼저 자신의 신호 이벤트를 기다렸다가 이벤트가 Set되면 큐의 있는 모든 데이타를 처리한 후 상대편 이벤트를 Set하여 상대편에게 실행 제어권을 넘긴다. 메인쓰레드에서는 계속 데이타를 큐에 넣는 역활을 하고 있다. 

예제

using System;
using System.Threading;
using System.Collections.Generic;

namespace MultiThrdApp
{
    class Program
    {
        static void Main()
        {
            Traffic traffic = new Traffic();

            // 2개의 쓰레드 구동
            Thread v = new Thread(traffic.ProcessVertical);
            Thread h = new Thread(traffic.ProcessHorizontal);
            v.Start();
            h.Start();

            // 메인쓰레드에서 데이타 전송
            for (int i = 0; i < 30; i+=3)
            {
                traffic.AddVertical(new int[] { i, i + 1, i + 2 });
                traffic.AddHorizontal(new int[] { i, i + 1, i + 2 });
                Thread.Sleep(10);
            }

            Thread.Sleep(1000);
            traffic.Running = false;                 
        }
    }

    class Traffic
    {
        private bool _running = true;

        // 상하, 좌우 통행 신호 역활을 하는 AutoResetEvent 이벤트들
        private AutoResetEvent _evtVert = new AutoResetEvent(true);
        private AutoResetEvent _evtHoriz = new AutoResetEvent(false);

        private Queue<int> _Qvert = new Queue<int>();
        private Queue<int> _Qhoriz = new Queue<int>();

        // 상하방향의 큐 데이타 처리
        // Vertical 방향의 처리 신호(_evtVert)를 받으면
        // Vertical 큐의 모든 큐 아이템을 처리하고
        // 좌우방향 처리 신호(_evtHoriz)를 보냄
        public void ProcessVertical()
        {            
            while (_running)
            {
                // Vertical 방향 처리 신호 기다림
                _evtVert.WaitOne();

                // Vertical 큐의 모든 데이타 처리
                // 큐는 다른 쓰레드에서 엑세스 가능하므로 lock을 건다
                lock (_Qvert)
                {
                    while (_Qvert.Count > 0)
                    {
                        int val = _Qvert.Dequeue();
                        Console.WriteLine("Vertical : {0}", val);
                    }
                }

                // Horizontal 방향 처리 신호 보냄
                _evtHoriz.Set();
            }

            Console.WriteLine("ProcessVertical : Done");
        }

        // 좌우방향의 큐 데이타 처리
        // Horizontal 방향의 처리 신호(_evtHoriz)를 받으면
        // Horizontal 큐의 모든 큐 아이템을 처리하고
        // 상하방향 처리 신호(_evtHoriz)를 보냄
        public void ProcessHorizontal()
        {
            while (_running)
            {
                _evtHoriz.WaitOne();

                lock (_Qhoriz)
                {
                    while (_Qhoriz.Count > 0)
                    {
                        int val = _Qhoriz.Dequeue();
                        Console.WriteLine("Horizontal : {0}", val);
                    }
                }
                
                _evtVert.Set();
            }

            Console.WriteLine("ProcessHorizontal : Done");
        }

        public bool Running
        {
            get { return _running; }
            set { _running = value; }
        }

        public void AddVertical(int[] data)
        {
            lock (_Qvert)
            {
                foreach (var item in data)
                {
                    _Qvert.Enqueue(item);
                }                
            }
        }

        public void AddHorizontal(int[] data)
        {
            lock (_Qhoriz)
            {
                foreach (var item in data)
                {
                    _Qhoriz.Enqueue(item);    
                }                
            }
        }
    }
}








ManualResetEvent 클래스


http://www.csharpstudy.com/Threads/manualresetevent.aspx



ManualResetEvent 클래스 

ManualResetEvent는 하나의 쓰레드만 통과시키고 닫는 AutoResetEvent와 달리, 한번 열리면 대기중이던 모든 쓰레드를 실행하게 하고 코드에서 수동으로 Reset()을 호출하여 문을 닫고 이후 도착한 쓰레드들을 다시 대기토록 한다. 아래는 여러 쓰레드의 실행을 중지시킨 후, ManualResetEvent로 신호를 보내 대기중이던 모든 쓰레들들을 한꺼번에 실행시키는 예제이다. 

예제

using System;
using System.Threading;

namespace MultiThrdApp
{
    class Program
    {
        // ManualResetEvent 객체 필드
        static ManualResetEvent manualEvent = new ManualResetEvent(false);

        static void Main()
        {
            // 10개의 쓰레드 생성
            // 10개 쓰레드 모두 manualEvent.WaitOne(); 에서
            // 실행 중지후 대기중
            for (int i = 0; i < 10; i++)
            {
                new Thread(Run).Start(i);
            }

            // 메인쓰레드            
            Thread.Sleep(3000);

            // ManualResetEvent 객체 Set() 호출
            // 10개 쓰레드 모두 실행 계속함.
            manualEvent.Set(); 
        }

        static void Run(object id)
        {            
            Console.WriteLine("{0} in Wait", id);

            // ManualResetEvent 신호 대기
            manualEvent.WaitOne();                        

            Console.WriteLine("{0}: Done", id);
        }
    }
}



테스드 결과 







CountdownEvent 클래스


http://www.csharpstudy.com/Threads/countdownevent.aspx



ManualResetEvent가 한 쓰레드에서 신호(Signal)을 보내 복수 쓰레드들을 통제하는데 사용되는 반면, .NET 4.0에 소개된 CountdownEvent는 한 쓰레드에서 복수 쓰레드들로부터의 신호들을 기다리는데 사용된다. 아래는 10개의 쓰레드를 시작한 후, 이 쓰레드들로부터 처음 5개의 신호가 (CountdownEvent.Signal() 메서드) 먼저 도착하는 대로 메인쓰레드는 Wait 대기 상태를 해제하고 다음 문장을 실행하게 된다. 

예제

using System;
using System.Threading;

namespace MultiThrdApp
{
    class Program
    {
        // CountdownEvent 객체 필드
        static CountdownEvent countEvent = new CountdownEvent(5);

        static void Main()
        {
            // 10개의 쓰레드 시작
            // 10개중 5개만 Vote만 끝내면 중지            
            for (int i = 0; i < 10; i++)
            {
                new Thread(Vote).Start(i);
            }

            // 메인쓰레드 첫 5개 신호를 기다림
            countEvent.Wait();

            Console.WriteLine("Vote is done!");            
        }

        static void Vote(object id)
        {                        
            if (countEvent.CurrentCount > 0)
            {
                // CountdownEvent 신호. -1씩 카운트다운.
                countEvent.Signal();

                Console.WriteLine("{0}: Vote", id);
            }
            else
            {
                Console.WriteLine("{0}: No vote", id);
            }
        }
    }
}
















'프로그래밍 > C#' 카테고리의 다른 글

Events  (0) 2017.03.29
Common I/O Tasks  (0) 2017.03.15
Sockets  (0) 2017.03.02
Using the Visual Studio Development Environment for C#  (0) 2017.02.14
Getting Started with C#  (0) 2017.02.13
:
Posted by 지훈2