<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Martin Plante</title>
    <link>http://blogs.xceedsoft.com/plantem/</link>
    <description>Open window on development at Xceed </description>
    <language>en-us</language>
    <copyright>Xceed Software Inc.</copyright>
    <lastBuildDate>Wed, 05 Apr 2006 12:43:13 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.8.5223.0</generator>
    <managingEditor>plantem@xceedsoft.com</managingEditor>
    <webMaster>plantem@xceedsoft.com</webMaster>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=b637efea-3f3b-4ed3-84b9-99a588912b33</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,b637efea-3f3b-4ed3-84b9-99a588912b33.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      It's been a long time since I've posted something "chewable". My energies were all
      directed on the soon to be released <a href="http://xceedsoft.com/products/ZipNet/">Xceed
      Zip for .NET</a> version 3.0. Though the apparent changes on the public interface
      are quite minor, and one can teach the new classes quite easily, the underlying code
      wasn't trivial.
   </p>
        <p>
      In short, for all of you who know what ZipArchive, ZippedFile and ZippedFolder are,
      say hello to TarArchive, TarredFile, TarredFolder, GZipArchive and GZippedFile.
   </p>
        <p>
      And when I say "easy to teach", what it really means is "find yourself a zipping example,
      and replace class name occurances of Zip{something} with Tar{somethong} or GZip{something}".
   </p>
        <p>
      Sure, there are some gotchas, like the fact that a GZIP archive cannot contain
      filenames with subfolders, are not well-suited to contain more than one compressed
      file, and can contain files without filenames. But these are details you'll get used
      to quite easily.
   </p>
        <p>
      There are two things that make me really proud in that product. One is under the hood,
      and the other is a sample. First, the engine: My colleague Jacques and I have come
      up with what we call the "Storage Engine". It's an abstraction of what an archiving
      library needs in term of temp storage, in-place archive updating, and transactional
      operations on an archive. Both the new TAR and GZIP implementations use it. In short,
      it abstracts the fact that we want to always update an archive in-place when possible,
      but revert to temp files and make sure to commit those temp files with any existing
      archive upon the last modification of it. If things go well, the ZIP implementation
      will benefit from it sooner than later.
   </p>
        <p>
      Second, the sample: The FTP Sample Explorer is gone, replaced with the FileSystem
      Snippet Explorer, a sample that let's you see, modify and run code snippets that show
      you the various tasks one might wish to implement. It goes straight to the point.
      No bells and whistle, no gravy, just the meat. The code is embedded in the executable
      as compressed serialized XML data. The main information (each topic's description
      and code) is nothing else than rich text. The nice thing about this sample is
      that in order for me to modify and add new topics, I simply need to compile the project
      with an extra define, and I'm now running the application in "admin" mode, enabling
      me to update the compressed XML file directly, for the next compilation to benefit
      from this update.
   </p>
        <p>
      Though I've finished work on this 3.0 version, I already have both hands in the two
      next releases of Xceed Zip for .NET and Xceed FTP for .NET. The first one will add
      support for AES encryption, and the second one will now offer proxy support.
   </p>
        <p>
      I didn't have much time to write because all those releases have a tight schedule
      I can't bust. I'm leaving Xceed in two months. Yup, I've decided it was time for me
      to move on. Until then, I have agreed to complete AES implementation, help Jacques
      kick-start proxy support and train about everybody here, each earning one of the numerous
      hats I'm wearing. It was a very difficult decision, since I have only friends at Xceed.
      Though the nine years or so I've spent here were exciting and challenging, I feel
      it's time for me to try new stuff... by myself. This isn't a divorce. I won't be far
      from Xceed, and still available to help them from time to time. As for you, dear customers
      and readers, rest assured you will stay in good hands. The team behind Xceed Zip and
      Xceed FTP, both .NET and ActiveX, will remain strong, even get stronger than it is
      now.
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=b637efea-3f3b-4ed3-84b9-99a588912b33" />
      </body>
      <title>Releases come and go...</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,b637efea-3f3b-4ed3-84b9-99a588912b33.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,b637efea-3f3b-4ed3-84b9-99a588912b33.aspx</link>
      <pubDate>Wed, 05 Apr 2006 12:43:13 GMT</pubDate>
      <description>&lt;p&gt;
   It's been a long time since I've posted something "chewable". My energies were all
   directed on the soon to be released &lt;a href="http://xceedsoft.com/products/ZipNet/"&gt;Xceed
   Zip for .NET&lt;/a&gt; version 3.0. Though the apparent changes on the public interface
   are quite minor, and one can teach the new classes quite easily, the underlying code
   wasn't trivial.
&lt;/p&gt;
&lt;p&gt;
   In short, for all of you who know what ZipArchive, ZippedFile and ZippedFolder are,
   say hello to TarArchive, TarredFile, TarredFolder, GZipArchive and GZippedFile.
&lt;/p&gt;
&lt;p&gt;
   And when I say "easy to teach", what it really means is "find yourself a zipping example,
   and replace class name occurances of Zip{something} with Tar{somethong} or GZip{something}".
&lt;/p&gt;
&lt;p&gt;
   Sure, there are some gotchas, like the fact that a GZIP&amp;nbsp;archive cannot contain
   filenames with subfolders, are not well-suited to contain more than one compressed
   file, and can contain files without filenames. But these are details you'll get used
   to quite easily.
&lt;/p&gt;
&lt;p&gt;
   There are two things that make me really proud in that product. One is under the hood,
   and the other is a sample. First, the engine: My colleague Jacques and I have come
   up with what we call the "Storage Engine". It's an abstraction of what an archiving
   library needs in term of temp storage, in-place archive updating, and transactional
   operations on an archive. Both the new TAR and GZIP implementations use it. In short,
   it abstracts the fact that we want to always update an archive in-place when possible,
   but revert to temp files and make sure to commit those temp files with any existing
   archive upon the last modification of it. If things go well, the ZIP implementation
   will benefit from it sooner than later.
&lt;/p&gt;
&lt;p&gt;
   Second, the sample: The FTP Sample Explorer is gone, replaced with the FileSystem
   Snippet Explorer, a sample that let's you see, modify and run code snippets that show
   you the various tasks one might wish to implement. It goes straight to the point.
   No bells and whistle, no gravy, just the meat. The code is embedded in the executable
   as compressed serialized XML data. The main information (each topic's description
   and code) is nothing else than rich text. The nice thing about&amp;nbsp;this sample&amp;nbsp;is
   that in order for me to modify and add new topics, I simply need to compile the project
   with an extra define, and I'm now running the application in "admin" mode, enabling
   me to update the compressed XML file directly, for the next compilation to benefit
   from this update.
&lt;/p&gt;
&lt;p&gt;
   Though I've finished work on this 3.0 version, I already have both hands in the two
   next releases of Xceed Zip for .NET and Xceed FTP for .NET. The first one will add
   support for AES encryption, and the second one will now offer proxy support.
&lt;/p&gt;
&lt;p&gt;
   I didn't have much time to write because all those releases have a tight schedule
   I can't bust. I'm leaving Xceed in two months. Yup, I've decided it was time for me
   to move on. Until then, I have agreed to complete AES implementation, help Jacques
   kick-start proxy support and train about everybody here, each earning one of the numerous
   hats I'm wearing. It was a very difficult decision, since I have only friends at Xceed.
   Though the nine years or so I've spent here were exciting and challenging, I feel
   it's time for me to try new stuff... by myself. This isn't a divorce. I won't be far
   from Xceed, and still available to help them from time to time. As for you, dear customers
   and readers, rest assured you will stay in good hands. The team behind Xceed Zip and
   Xceed FTP, both .NET and ActiveX, will remain strong, even get stronger than it is
   now.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=b637efea-3f3b-4ed3-84b9-99a588912b33" /&gt;</description>
      <category>.NET;FTP;General;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=efb9c15a-a6e0-492b-af25-193e9be22594</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,efb9c15a-a6e0-492b-af25-193e9be22594.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      Ever since I've been working with the .NET framework, most of my time was spent on
      the <a href="http://msdn2.microsoft.com/en-us/library/29kt2zfk(en-us,VS.80).aspx">System.IO</a> namespace.
      I'm not a UI guy, I'm an IO guy! The most important class in that namespace is <a href="http://msdn2.microsoft.com/en-us/library/system.io.stream.aspx">System.IO.Stream</a>.
      And since it was well-designed, probably inspired by other successful stream implementations
      (Delphi comes to mind), it's very easy to expose features using streams.
   </p>
        <p>
      My favorite use of streams is for pass-through streams. A pass-through stream
      is a class which derives from System.IO.Stream, but reads from or writes to an inner
      stream received at creation. It serves as a data modifyer or data analyser. When reading
      from a pass-through stream, it first reads from its inner stream, then processes the
      data read (potentially modifying it) and returns this data. When writing to a pass-through
      stream, it first processes the provided data (again potentially modifying it), then
      writes it to its inner stream.
   </p>
        <p>
      Xceed Zip for .NET and Xceed FTP for .NET both use a pletoria of pass-through streams.
      The most popular is <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.compression.compressedstream.html">Xceed.Compression.CompressedStream</a>,
      the stream responsible for compressing data before writing it to its inner stream,
      or decompressing data read from its inner stream. But most others are internal. We've
      been juggling with the idea of exposing them for a long time, but beleive it would
      only confuse developers to "see" those new namespaces and classes. Another useful
      thing with internal classes is that we can change their interface without causing
      breaking changes.
   </p>
        <h5>TransientStream
   </h5>
        <p>
      It was a long debate before we decided to go forth with the "transient" keyword. Not
      only is it used in the TransientStream type name, but also as a property on many of
      our pass-through streams. What we meant by "transient" is "volatile", or if you prefer
      more explicit keywords, "does-not-close-its-inner-stream-when-closed". A TransientStream
      is about the simplest expression of a pass-through stream. All required property and
      method overrides simply call the inner stream. The only exception is for the Close
      method, which simply makes sure not to call Close on the inner stream. This is very
      useful when you need to pass your stream to another routine which closes the stream,
      while you don't want your stream to get closed.
   </p>
        <h5>ChecksumStream
   </h5>
        <p>
      This stream does not modify the data read from or written to, but takes the opportunity
      to calculate either a CRC32 or an Adler32 on that data. When reading, it can also
      make sure, upon closing it, that the calculated checksum matches an expected stream, else
      throw an exception. In this way, we can insert checksum calculation anywhere in a
      process without interfering nor requiring code changes.
   </p>
        <h5>CombinedStream
   </h5>
        <p>
      The deflate compression algorithm has the ability to detect the end of the data when
      decompressing. The CompressedStream is itself a pass-through stream. When reading
      from it, it first reads from the inner stream, then decompresses the data. When
      it reaches the end of the compressed data, the CompressedStream has the ability to
      return a stream on the remaining data, in case this inner stream contains more data
      after the compressed block. Why isn't this equivalent to the inner stream you might
      ask? Let's say the inner stream isn't seekable. The CompressedStream's Read method
      first reads N bytes from the inner stream, but may have found that the end of the
      compressed data is after M bytes (M &lt; N). The inner stream is already N-M bytes
      too far. The CombinedStream receives both a byte array (the unused N-M bytes) and
      the inner stream as ctor parameters, and will expose those as one contiguous stream.
      Pretty slick!
   </p>
        <h5>HeaderFooterStream
   </h5>
        <p>
      Xceed Streaming Compression for .NET exposes stream-based (as opposed to archive-based)
      compression formats. Those formats all have one thing in common: they have a header
      and a footer. Not all of them can depend on the deflate algorithm to automatically
      detect the end of the stream. That's why they need to make sure to never return the
      first M bytes and last N bytes from the inner stream, where M is the expected header
      size and N the expected footer size.
   </p>
        <h5>WindowStream
   </h5>
        <p>
      When exposing part of a zip file as a single AbstractFile, we need to make sure we
      do not read past the boundaries of that file's data in the zip file. The WindowStream
      exposes a region of its inner stream as a zero-position, N-length stream.
   </p>
        <h5>ZCryptStream
   </h5>
        <p>
      This pass-though stream automatically encrypts or decrypts the data written or read,
      using the basic Zip encryption (which is as weak as me in front of a cheese cake).
      I will be working on AES encryption very soon, and it will most probably be implemented
      as a pass-through stream too!
   </p>
        <h5>NotifyStream
   </h5>
        <p>
      Though pass-through streams can do much of the task, it is often better for the clarity
      of the code to have processing done by other classes not deriving from System.IO.Stream.
      The NotifyStream class exposes three events: ReadingFromStream, WritingToStream and
      ClosingStream. Any other class can advise for those events to intervene in the reading
      or writing process. This old class exists since the beginning of Xceed Zip for .NET,
      but it has proven very useful in the current development we are doing for Tar and
      GZip support within Xceed Zip for .NET.
   </p>
        <h5>ForwardSeekableStream
   </h5>
        <p>
      This new class created for Xceed Zip for .NET 3.0 (Tar and GZip support) can expose
      a non-seekable stream as a seekable stream when reading, or at least a stream reporting
      a Position when writing. When reading, you can call Seek with an offset behond
      the current position, and it will simply read from the non-seekable inner stream until
      well positioned. And for both reading and writing operations, it counts the number
      of bytes read or written so it can report a position (granting we knew
      the original position when created).
   </p>
        <h5>FtpAsciiDataStream
   </h5>
        <p>
      Xceed FTP for .NET also uses pass-through streams. For example, the FtpAsciiDataStream
      wraps the NetworkStream to perform convertion of LF to CR/LF on the fly when sending
      a file in ASCII mode.
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=efb9c15a-a6e0-492b-af25-193e9be22594" />
      </body>
      <title>Pass-through streams</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,efb9c15a-a6e0-492b-af25-193e9be22594.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,efb9c15a-a6e0-492b-af25-193e9be22594.aspx</link>
      <pubDate>Tue, 31 Jan 2006 14:47:29 GMT</pubDate>
      <description>&lt;p&gt;
   Ever since I've been working with the .NET framework, most of my time was spent on
   the &lt;a href="http://msdn2.microsoft.com/en-us/library/29kt2zfk(en-us,VS.80).aspx"&gt;System.IO&lt;/a&gt; namespace.
   I'm not a UI guy, I'm an IO guy! The most important class in that namespace is &lt;a href="http://msdn2.microsoft.com/en-us/library/system.io.stream.aspx"&gt;System.IO.Stream&lt;/a&gt;.
   And since it was well-designed, probably inspired by other successful stream implementations
   (Delphi comes to mind), it's very easy to expose features using streams.
&lt;/p&gt;
&lt;p&gt;
   My favorite use&amp;nbsp;of streams is for pass-through streams. A pass-through stream
   is a class which derives from System.IO.Stream, but reads from or writes to an inner
   stream received at creation. It serves as a data modifyer or data analyser. When reading
   from a pass-through stream, it first reads from its inner stream, then processes the
   data read (potentially modifying it) and returns this data. When writing to a pass-through
   stream, it first processes the provided data (again potentially modifying it), then
   writes it to its inner stream.
&lt;/p&gt;
&lt;p&gt;
   Xceed Zip for .NET and Xceed FTP for .NET both use a pletoria of pass-through streams.
   The most popular is &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.compression.compressedstream.html"&gt;Xceed.Compression.CompressedStream&lt;/a&gt;,
   the stream responsible for compressing data before writing it to its inner stream,
   or decompressing data read from its inner stream. But most others are internal. We've
   been juggling with the idea of exposing them for a long time, but beleive it would
   only confuse developers to "see" those new namespaces and classes. Another useful
   thing with internal classes is that we can change their interface without causing
   breaking changes.
&lt;/p&gt;
&lt;h5&gt;TransientStream
&lt;/h5&gt;
&lt;p&gt;
   It was a long debate before we decided to go forth with the "transient" keyword. Not
   only is it used in the TransientStream type name, but also as a property on many of
   our pass-through streams. What we meant by "transient" is "volatile", or if you prefer
   more explicit keywords, "does-not-close-its-inner-stream-when-closed". A TransientStream
   is about the simplest expression of a pass-through stream. All required property and
   method overrides simply call the inner stream. The only exception is for the Close
   method, which simply makes sure not to call Close on the inner stream. This is very
   useful when you need to pass your stream to another routine which closes the stream,
   while you don't want your stream to get closed.
&lt;/p&gt;
&lt;h5&gt;ChecksumStream
&lt;/h5&gt;
&lt;p&gt;
   This stream does not modify the data read from or written to, but takes the opportunity
   to calculate either a CRC32 or an Adler32 on that data. When reading, it can also
   make sure, upon closing it, that the calculated checksum matches an expected stream,&amp;nbsp;else
   throw an exception. In this way, we can insert checksum calculation anywhere in a
   process without interfering nor requiring code changes.
&lt;/p&gt;
&lt;h5&gt;CombinedStream
&lt;/h5&gt;
&lt;p&gt;
   The deflate compression algorithm has the ability to detect the end of the data when
   decompressing. The CompressedStream is itself a pass-through stream. When reading
   from it, it first reads&amp;nbsp;from the inner stream, then decompresses the data. When
   it reaches the end of the compressed data, the CompressedStream has the ability to
   return a stream on the remaining data, in case this inner stream contains more data
   after the compressed block. Why isn't this equivalent to the inner stream you might
   ask? Let's say the inner stream isn't seekable. The CompressedStream's Read method
   first reads N bytes from the inner stream, but may have found that the end of the
   compressed data is after M bytes (M &amp;lt; N). The inner stream is already N-M bytes
   too far. The CombinedStream receives both a byte array (the&amp;nbsp;unused N-M bytes)&amp;nbsp;and
   the inner stream as ctor parameters, and will expose those as one contiguous stream.
   Pretty slick!
&lt;/p&gt;
&lt;h5&gt;HeaderFooterStream
&lt;/h5&gt;
&lt;p&gt;
   Xceed Streaming Compression for .NET exposes stream-based (as opposed to archive-based)
   compression formats. Those formats all have one thing in common: they have a header
   and a footer. Not all of them can depend on the deflate algorithm to automatically
   detect the end of the stream. That's why they need to make sure to never return the
   first M bytes and last N bytes from the inner stream, where M is the expected header
   size and N the expected footer size.
&lt;/p&gt;
&lt;h5&gt;WindowStream
&lt;/h5&gt;
&lt;p&gt;
   When exposing part of a zip file as a single AbstractFile, we need to make sure we
   do not read past the boundaries of that file's data in the zip file. The WindowStream
   exposes a region of its inner stream as a zero-position, N-length stream.
&lt;/p&gt;
&lt;h5&gt;ZCryptStream
&lt;/h5&gt;
&lt;p&gt;
   This pass-though stream automatically encrypts or decrypts the data written or read,
   using the basic Zip encryption (which is as weak as me in front of a cheese cake).
   I will be working on AES encryption very soon, and it will most probably be implemented
   as a pass-through stream too!
&lt;/p&gt;
&lt;h5&gt;NotifyStream
&lt;/h5&gt;
&lt;p&gt;
   Though pass-through streams can do much of the task, it is often better for the clarity
   of the code to have processing done by other classes not deriving from System.IO.Stream.
   The NotifyStream class exposes three events: ReadingFromStream, WritingToStream and
   ClosingStream. Any other class can advise for those events to intervene in the reading
   or writing process. This old class exists since the beginning of Xceed Zip for .NET,
   but it has proven very useful in the current development we are doing for Tar and
   GZip support within Xceed Zip for .NET.
&lt;/p&gt;
&lt;h5&gt;ForwardSeekableStream
&lt;/h5&gt;
&lt;p&gt;
   This new class created for Xceed Zip for .NET 3.0 (Tar and GZip support) can expose
   a non-seekable stream as a seekable stream when reading, or at least a stream reporting
   a Position when writing. When reading, you can call Seek with an offset&amp;nbsp;behond
   the current position, and it will simply read from the non-seekable inner stream until
   well positioned. And for both reading and writing operations, it counts the number
   of bytes read or written&amp;nbsp;so it can report&amp;nbsp;a position (granting&amp;nbsp;we knew
   the original position when created).
&lt;/p&gt;
&lt;h5&gt;FtpAsciiDataStream
&lt;/h5&gt;
&lt;p&gt;
   Xceed FTP for .NET also uses pass-through streams. For example, the FtpAsciiDataStream
   wraps the NetworkStream to perform convertion of LF to CR/LF on the fly when sending
   a file in ASCII mode.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=efb9c15a-a6e0-492b-af25-193e9be22594" /&gt;</description>
      <category>.NET;Compression;FileSystem;FTP;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=e89375a1-63e3-470f-b804-28ef40192554</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,e89375a1-63e3-470f-b804-28ef40192554.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I previously <a href="http://blogs.xceedsoft.com/plantem/default.aspx?month=2005-06#a5bba8ded-a7b0-40ce-ae9f-33b3c3cbb4e3">gave
      a glimpse</a> of how to zip into an HttpResponse's OutputStream, but it wasn't explaining
      all aspects of zipping from ASP.NET. So I'll get in more details here.
   </p>
        <p>
      First, I have used my fantastic talent in UI designs to create this web page:
   </p>
        <p>
          <img src="http://blogs.xceedsoft.com/plantem/content/binary/ZipAndSend.png" border="0" />
        </p>
        <p>
      Yup, three checkboxes and a button is enough gadgets for me!
   </p>
        <p>
      The first piece of code involves Application_Start. Since I know I won't be zipping
      gazillions of bytes, I want my web page to use memory as a temporary location for
      compressed data. How you do this with Xceed Zip for .NET is simple: You create a RAM
      drive! Oh the good old days of RAM drives...
   </p>
        <p>
        </p>
        <pre>    protected void Application_Start(Object sender, EventArgs e)
    {
      Xceed.Zip.Licenser.LicenseKey = "ZIN23-#####-#####-####";
      ZipArchive.DefaultTempFolder = new MemoryFolder();
    }
</pre>
        <p>
        </p>
        <p>
      This new MemoryFolder is acting exactly like a per-process RAM drive. It's an AbstractFolder
      like any other AbstractFolder. The TempFolder of all new ZipArchive instances will be
      initialized to that value. Application_Start is also a great place where to set
      your license key, before anything else.
   </p>
        <p>
      We're now ready for the button's click event. Again, I want to avoid write access
      on the hard drive, and wish to zip directly in the response stream. But the idea behind
      the Xceed FileSystem is to copy source files and folders to destination files and
      folders. How can I zip into a Stream? The StreamFile class comes to the rescue. It
      lets you expose a Stream as if it were an AbstractFile. Then, you can pass this StreamFile
      to the ZipArchive's constructor, to tell that new instance to write into that Stream.
      The rest is glue code for my wonderful ASP.NET application to zip the correct files.
   </p>
        <p>
        </p>
        <pre>    private void Button1_Click(object sender, System.EventArgs e)
    {
      if( !CheckBox1.Checked &amp;&amp; !CheckBox2.Checked &amp;&amp; !CheckBox3.Checked )
      {
        // Redirect to error page...
        return;
      }

      // The "MACHINE\ASP_NET" user must have read access to that folder.
      DiskFolder source = new DiskFolder( @"d:\" );

      // We want the client-side to recognize the upcoming file as a zip file.
      this.Response.ContentType = "application/zip";
      this.Response.AddHeader( "Content-Disposition", "attachment; filename=YourFiles.zip" );

      // We will zip directly in the response stream. The temporary compressed
      // data will be written to the ZipArchive's TempFolder, thus the MemoryFolder 
      // we set in Application_Start.
      ZipArchive destination = new ZipArchive( new StreamFile( this.Response.OutputStream ) );

      // And finally we zip in a single operation. If we had to zip more than
      // one source, we could have used ZipArchive.BeginUpdate/EndUpdate.
      ArrayList nameFilters = new ArrayList();

      if( CheckBox1.Checked )
        nameFilters.Add( new NameFilter( "*.txt" ) );

      if( CheckBox2.Checked )
        nameFilters.Add( new NameFilter( "*.jpg" ) );

      if( CheckBox3.Checked )
        nameFilters.Add( new NameFilter( "*.exe|*.dll" ) );

      // Passing more than one filter to CopyFilesTo does an "AndFilter"
      // by default.
      Filter mainFilter = ( nameFilters.Count == 1 )
        ? nameFilters[ 0 ] as Filter
        : new OrFilter( nameFilters.ToArray( typeof( NameFilter ) ) );

      source.CopyFilesTo( destination, false, true, mainFilter );

      this.Response.End();
    }
</pre>
        <p>
      We now have an ASP.NET application which only requires read access to the source
      files and folders to zip. Everything else is done in memory, without drifting away
      from the logic of the Xceed FileSystem; manipulating files and folders.
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=e89375a1-63e3-470f-b804-28ef40192554" />
      </body>
      <title>Zipping from an ASP.NET - A real sample</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,e89375a1-63e3-470f-b804-28ef40192554.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,e89375a1-63e3-470f-b804-28ef40192554.aspx</link>
      <pubDate>Fri, 11 Nov 2005 14:26:28 GMT</pubDate>
      <description>&lt;p&gt;
   I previously &lt;a href="http://blogs.xceedsoft.com/plantem/default.aspx?month=2005-06#a5bba8ded-a7b0-40ce-ae9f-33b3c3cbb4e3"&gt;gave
   a glimpse&lt;/a&gt; of how to zip into an HttpResponse's OutputStream, but it wasn't explaining
   all aspects of zipping from ASP.NET. So I'll get in more details here.
&lt;/p&gt;
&lt;p&gt;
   First, I have used my&amp;nbsp;fantastic talent in UI designs to create this web page:
&lt;/p&gt;
&lt;p&gt;
   &lt;img src="http://blogs.xceedsoft.com/plantem/content/binary/ZipAndSend.png" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
   Yup, three checkboxes and a button is enough gadgets for me!
&lt;/p&gt;
&lt;p&gt;
   The first piece of code involves Application_Start. Since I know I won't be zipping
   gazillions of bytes, I want my web page to use memory as a temporary location for
   compressed data. How you do this with Xceed Zip for .NET is simple: You create a RAM
   drive! Oh the good old days of RAM drives...
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;    protected void Application_Start(Object sender, EventArgs e)
    {
      Xceed.Zip.Licenser.LicenseKey = "ZIN23-#####-#####-####";
      ZipArchive.DefaultTempFolder = new MemoryFolder();
    }
&lt;/pre&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
   This new MemoryFolder is acting exactly like a per-process RAM drive. It's an AbstractFolder
   like any other AbstractFolder. The TempFolder of all new ZipArchive instances will&amp;nbsp;be
   initialized to that value.&amp;nbsp;Application_Start is also a great place where to set
   your license key, before anything else.
&lt;/p&gt;
&lt;p&gt;
   We're now ready for the button's click event. Again, I want to avoid write access
   on the hard drive, and wish to zip directly in the response stream. But the idea behind
   the Xceed FileSystem is to copy source files and folders to destination files and
   folders. How can I zip into a Stream? The StreamFile class comes to the rescue. It
   lets you expose a Stream as if it were an AbstractFile. Then, you can pass this StreamFile
   to the ZipArchive's constructor, to tell that new instance to write into that Stream.
   The rest is glue code for my wonderful ASP.NET application to zip the correct files.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;    private void Button1_Click(object sender, System.EventArgs e)
    {
      if( !CheckBox1.Checked &amp;amp;&amp;amp; !CheckBox2.Checked &amp;amp;&amp;amp; !CheckBox3.Checked )
      {
        // Redirect to error page...
        return;
      }

      // The "MACHINE\ASP_NET" user must have read access to that folder.
      DiskFolder source = new DiskFolder( @"d:\" );

      // We want the client-side to recognize the upcoming file as a zip file.
      this.Response.ContentType = "application/zip";
      this.Response.AddHeader( "Content-Disposition", "attachment; filename=YourFiles.zip" );

      // We will zip directly in the response stream. The temporary compressed
      // data will be written to the ZipArchive's TempFolder, thus the MemoryFolder 
      // we set in Application_Start.
      ZipArchive destination = new ZipArchive( new StreamFile( this.Response.OutputStream ) );

      // And finally we zip in a single operation. If we had to zip more than
      // one source, we could have used ZipArchive.BeginUpdate/EndUpdate.
      ArrayList nameFilters = new ArrayList();

      if( CheckBox1.Checked )
        nameFilters.Add( new NameFilter( "*.txt" ) );

      if( CheckBox2.Checked )
        nameFilters.Add( new NameFilter( "*.jpg" ) );

      if( CheckBox3.Checked )
        nameFilters.Add( new NameFilter( "*.exe|*.dll" ) );

      // Passing more than one filter to CopyFilesTo does an "AndFilter"
      // by default.
      Filter mainFilter = ( nameFilters.Count == 1 )
        ? nameFilters[ 0 ] as Filter
        : new OrFilter( nameFilters.ToArray( typeof( NameFilter ) ) );

      source.CopyFilesTo( destination, false, true, mainFilter );

      this.Response.End();
    }
&lt;/pre&gt;
&lt;p&gt;
   We&amp;nbsp;now have an ASP.NET application which only requires read access to the source
   files and folders to zip. Everything else is done in memory, without drifting away
   from the logic of the Xceed FileSystem; manipulating files and folders.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=e89375a1-63e3-470f-b804-28ef40192554" /&gt;</description>
      <category>.NET;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=af20b143-cb89-4b4e-8006-298cdff4c0ce</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,af20b143-cb89-4b4e-8006-298cdff4c0ce.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      Just in case my <a href="http://blogs.xceedsoft.com/plantem/PermaLink,guid,78f813ed-96ee-4752-8ab5-2061b0f9d758.aspx">previous
      post on the subject</a> did not ring a bell, the release of version 2.1 of Xceed FTP
      for .NET means you can directly unzip from a zip file located on an FTP server, without
      downloading the file first! Look at the following code:
   </p>
        <p>
        </p>
        <pre>  using( FtpConnection connection = new FtpConnection( "ftp.xceed.com" ) )
  {
    FtpFile source = new FtpFile( connection, @"/images/Flowers/Backup/Flowers.zip" );
    DiskFolder dest = new DiskFolder( @"d:\temp\flowers" );

    ZipArchive zip = new ZipArchive( source );
    zip.CopyFilesTo( dest, true, true );
  }
</pre>
        <p>
      The secret behind this code is the kind of stream "FtpFile.OpenRead" returns. Though
      we are dealing with a network connection, this stream is fully seekable! The FtpFile
      takes advantage of the "REST" FTP command, which tells the FTP server we wish to start
      the transfer at a specific offset. Thus, when the ZipArchive needs to seek at the
      end of the file to locate the ending header, a proper "REST" command is issued to
      avoid having to read all the zip file first. And the same happens when reading the
      central directory, or unzipping specific files.
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=af20b143-cb89-4b4e-8006-298cdff4c0ce" />
      </body>
      <title>Unzipping from an FTP server</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,af20b143-cb89-4b4e-8006-298cdff4c0ce.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,af20b143-cb89-4b4e-8006-298cdff4c0ce.aspx</link>
      <pubDate>Tue, 01 Nov 2005 20:15:40 GMT</pubDate>
      <description>&lt;p&gt;
   Just in case my &lt;a href="http://blogs.xceedsoft.com/plantem/PermaLink,guid,78f813ed-96ee-4752-8ab5-2061b0f9d758.aspx"&gt;previous
   post on the subject&lt;/a&gt; did not ring a bell, the release of version 2.1 of Xceed FTP
   for .NET means you can directly unzip from a zip file located on an FTP server, without
   downloading&amp;nbsp;the file&amp;nbsp;first! Look at the following code:
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;  using( FtpConnection connection = new FtpConnection( "ftp.xceed.com" ) )
  {
    FtpFile source = new FtpFile( connection, @"/images/Flowers/Backup/Flowers.zip" );
    DiskFolder dest = new DiskFolder( @"d:\temp\flowers" );

    ZipArchive zip = new ZipArchive( source );
    zip.CopyFilesTo( dest, true, true );
  }
&lt;/pre&gt;
&lt;p&gt;
   The secret behind this code is the kind of stream "FtpFile.OpenRead" returns. Though
   we are dealing with a network connection, this stream is fully seekable! The FtpFile
   takes advantage of the "REST" FTP command, which tells the FTP server we wish to start
   the transfer at a specific offset. Thus, when the ZipArchive needs to seek at the
   end of the file to locate the ending header, a proper "REST" command is issued to
   avoid having to read all the zip file first. And the same happens when reading the
   central directory, or unzipping specific files.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=af20b143-cb89-4b4e-8006-298cdff4c0ce" /&gt;</description>
      <category>.NET;FileSystem;FTP;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=78f813ed-96ee-4752-8ab5-2061b0f9d758</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,78f813ed-96ee-4752-8ab5-2061b0f9d758.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I'm glad to announce that Xceed FTP for .NET 2.1 is <a href="http://xceedsoft.com/download/downloadform.aspx?produitID=371">now
      available for download</a>. I've been working on this release for the past few months,
      and I'm very excited to finally see the FTP FileSystem come to life.
   </p>
        <p>
      For those not familiar with the Xceed FileSystem, which comes with Xceed Zip for .NET,
      here is some code that sheds some light on what you can do with it. Consider these
      variables of the same base type:
   </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      A file on disk</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFile
      first = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> DiskFile(
      @"d:\FileSystem.txt" );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      Another file on disk</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFile
      second = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> DiskFile(
      @"c:\temp\AnotherFileSystem.txt" );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      A file compressed in a zip file on disk</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFile
      third = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> ZippedFile( </span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> DiskFile(
      @"c:\temp\data.zip" ), "FileSystemInAZip.txt" );;</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      A file in the isolated storage</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFile
      fourth = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> IsolatedFile(
      "Isolated.txt" );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      A file in memory (random name)</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFile
      fifth = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> MemoryFile();</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      A file compressed in a zip file in memory</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFile
      sixth = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> ZippedFile( </span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> MemoryFile(),
      "VolatileFileSystem.txt" );</span>
          </pre>
        </div>
        <!--EndFragment-->
        <p>
      You can copy files around very easily:
   </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      Copying the first file anywhere else is always the same!</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">first.CopyTo(
      second, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">first.CopyTo(
      third, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">first.CopyTo(
      fourth, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">first.CopyTo(
      fifth, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">first.CopyTo(
      sixth, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> );</span>
          </pre>
        </div>
        <!--EndFragment-->
        <p>
      And accessing the contents of any file is always the same:
   </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">private</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">
            </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">void</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> DisplayTextFile(
      AbstractFile file )</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">{</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      Console.WriteLine( "Displaying the contents of {0}, which is a {1}.", </span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        file.FullName,</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        file.GetType().Name );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">using</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">(
      StreamReader reader = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> StreamReader(
      file.OpenRead() ) )</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      {</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">string</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> line;</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">while</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">(
      ( line = reader.ReadLine() ) != </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">null</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> )</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        {</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
          Console.WriteLine( line );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        }</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      }</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      Console.WriteLine();</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">}</span>
          </pre>
        </div>
        <!--EndFragment-->
        <br />
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      Displaying the contents of those files is always the same!</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">DisplayTextFile(
      first );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">DisplayTextFile(
      second );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">DisplayTextFile(
      third );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">DisplayTextFile(
      fourth );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">DisplayTextFile(
      fifth );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">DisplayTextFile(
      sixth );</span>
          </pre>
        </div>
        <!--EndFragment-->
        <p>
      And why not finish this demonstration by deleting the files we just created.
   </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      And finally, deleting files is the same!</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">second.Delete();</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">third.Delete();</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">fourth.Delete();</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">fifth.Delete();</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">sixth.Delete();</span>
          </pre>
        </div>
        <!--EndFragment-->
        <p>
      Any kind of file is an AbstractFile. Any kind of folder is an AbstractFolder. This
      way, a DiskFile, an IsolatedFile, a ZippedFile and a MemoryFile share a common set
      of properties and methods for accessing their metadata and reading/writing their actual
      data. And a DiskFolder, an IsolatedFolder, a ZippedFolder and a MemoryFolder share
      a common set of methods for discovering child items.
   </p>
        <p>
      How does the FTP FileSystem come into play? Simply by offering the same abstraction
      over files and folders stored on an FTP server. We could simply add this code to the
      above sample, and everything works just as expected!
   </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFile
      seventh = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpFile( </span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpConnection(
      "localhost" ), @"\RemoteFileSystem.txt" );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">first.CopyTo(
      seventh, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">DisplayTextFile(
      seventh );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">seventh.Delete();</span>
          </pre>
        </div>
        <!--EndFragment-->
        <p>
      Let's dive a little bit into this implementation of an AbstractFile and AbstractFolder.
      Each constructor requires an FtpConnection instance, which contains information on
      how to connect to the target FTP server. Though it looks like a simple information
      storage class, it does much more. Each time an FtpFile or an FtpFolder requires information,
      or an incoming or outgoing stream on a file's data, it asks the FtpConnection for
      an active command channel connection to the server. This way, a unique command channel
      is generally required for accessing many files on the server.
   </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">using</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">(
      FtpConnection connection = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpConnection(
      "ftp.xceed.com" ) )</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">{</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      connection.TraceWriter = Console.Out;</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      FtpFolder root = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpFolder(
      connection );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">foreach</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">(
      AbstractFile file </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">in</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> root.GetFiles( </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">false</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">,
      "*.txt" ) )</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      {</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        DisplayTextFile( file );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      }</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">}</span>
          </pre>
        </div>
        <!--EndFragment-->
        <p>
      If we comment out the "Console.WriteLine( line );" line in "DisplayTextFile", we can
      see the FTP conversation that occurred for the above code:
   </p>
        <p>
        </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">Connected to 66.46.177.250:21 on 9/27/2005 @ 2:24:54 PM<br />
      &lt; 220 Serv-U FTP Server v6.0 for WinSock ready...<br />
      &gt; USER anonymous<br />
      &lt; 331 User name okay, please send complete E-mail address as password.<br />
      &gt; PASS *****<br />
      &lt; 230 User logged in, proceed.<br />
      &gt; PWD<br />
      &lt; 257 "/" is current directory.<br />
      &gt; CWD /<br />
      &lt; 250 Directory changed to /<br />
      &gt; CWD /<br />
      &lt; 250 Directory changed to /<br />
      &gt; CWD /<br />
      &lt; 250 Directory changed to /<br />
      &gt; TYPE A<br />
      &lt; 200 Type set to A.<br />
      &gt; PASV<br />
      &lt; 227 Entering Passive Mode (66,46,177,250,6,238)<br />
      &gt; LIST<br />
      Data connection established with 66.46.177.250:1774 on 9/27/2005 @ 2:24:56 PM<br />
      &lt; 150 Opening ASCII mode data connection for /bin/ls.<br />
      &lt; 226-Maximum disk quota limited to Unlimited kBytes<br />
      &lt; Used disk quota 0 kBytes, available Unlimited kBytes<br />
      &lt; 226 Transfer complete.<br />
      Displaying the contents of \FileSystem.txt, which is a FtpFile.<br />
      &gt; CWD /<br />
      &lt; 250 Directory changed to /<br />
      &gt; TYPE I<br />
      &lt; 200 Type set to I.<br />
      &gt; PASV<br />
      &lt; 227 Entering Passive Mode (66,46,177,250,6,240)<br />
      &gt; RETR FileSystem.txt<br />
      Data connection established with 66.46.177.250:1776 on 9/27/2005 @ 2:24:57 PM<br />
      &lt; 150 Opening BINARY mode data connection for FileSystem.txt (1198 Bytes).<br />
      &lt; 226-Maximum disk quota limited to Unlimited kBytes<br />
      &lt; Used disk quota 0 kBytes, available Unlimited kBytes<br />
      &lt; 226 Transfer complete.<br /><br />
      Displaying the contents of \appnote.txt, which is a FtpFile.<br />
      &gt; CWD /<br />
      &lt; 250 Directory changed to /<br />
      &gt; TYPE I<br />
      &lt; 200 Type set to I.<br />
      &gt; PASV<br />
      &lt; 227 Entering Passive Mode (66,46,177,250,6,246)<br />
      &gt; RETR appnote.txt<br />
      Data connection established with 66.46.177.250:1782 on 9/27/2005 @ 2:24:58 PM<br />
      &lt; 150 Opening BINARY mode data connection for appnote.txt (109785 Bytes).<br />
      &lt; 226-Maximum disk quota limited to Unlimited kBytes<br />
      &lt; Used disk quota 0 kBytes, available Unlimited kBytes<br />
      &lt; 226 Transfer complete.<br /><br />
      &gt; QUIT<br />
      Disconnected from 66.46.177.250:21 on 9/27/2005 @ 2:25:04 PM</pre>
        </div>
        <p>
        </p>
        <p>
      Each FtpFolder and FtpFile instance shared the same FtpConnection, and since no two
      operations were done at the same time, a single connection was required, as the log
      indicates. The FtpConnection object implements the IDisposable interface, since it
      keeps any active connection available until disposed (or finalized).
   </p>
        <p>
      Now what happens if I try to open two files at the same time, like this?
   </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">using</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">(
      FtpConnection connection = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpConnection(
      "ftp.xceed.com" ) )</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">{</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      connection.TraceWriter = Console.Out;</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      AbstractFile first = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpFile(
      connection, @"\FileSystem.txt" );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      AbstractFile second = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpFile(
      connection, @"\appnote.txt" );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">using</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">(
      Stream firstStream = first.OpenRead() )</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      {</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">using</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">(
      Stream secondStream = second.OpenRead() )</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        {</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
          </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      In an FTP conversation with an FTP server, only one command</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
          </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      at a time can be pending. Here, we clearly have two files</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
          </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      open at the same time on the same FTP server. How? Each file</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
          </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      has its own connection to the FTP server!</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
        }</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> 
      }</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">}</span>
          </pre>
        </div>
        <!--EndFragment-->
        <p>
      The FtpConnection object will create extra command channel connections as required. The
      output shows two command channel connections were made:
   </p>
        <p>
        </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <font color="#ff0000">Connected
      to 66.46.177.250:21 on 9/27/2005 @ 2:38:06 PM<br />
      &lt; 220 Serv-U FTP Server v6.0 for WinSock ready...<br />
      &gt; USER anonymous<br />
      &lt; 331 User name okay, please send complete E-mail address as password.<br />
      &gt; PASS *****<br />
      &lt; 230 User logged in, proceed.<br /></font>&gt; CWD /<br />
      &lt; 250 Directory changed to /<br />
      &gt; TYPE A<br />
      &lt; 200 Type set to A.<br />
      &gt; PASV<br />
      &lt; 227 Entering Passive Mode (66,46,177,250,10,53)<br />
      &gt; LIST<br />
      Data connection established with 66.46.177.250:2613 on 9/27/2005 @ 2:38:07 PM<br />
      &lt; 150 Opening ASCII mode data connection for /bin/ls.<br />
      &lt; 226-Maximum disk quota limited to Unlimited kBytes<br />
      &lt;     Used disk quota 0 kBytes, available Unlimited kBytes<br />
      &lt; 226 Transfer complete.<br />
      &gt; CWD /<br />
      &lt; 250 Directory changed to /<br />
      &gt; TYPE I<br />
      &lt; 200 Type set to I.<br />
      &gt; PASV<br />
      &lt; 227 Entering Passive Mode (66,46,177,250,10,54)<br />
      &gt; RETR FileSystem.txt<br />
      Data connection established with 66.46.177.250:2614 on 9/27/2005 @ 2:38:08 PM<br />
      &lt; 150 Opening BINARY mode data connection for FileSystem.txt (1198 Bytes).<br />
      Connected to 66.46.177.250:21 on 9/27/2005 @ 2:38:08 PM<br /><font color="#ff0000">&lt; 220 Serv-U FTP Server v6.0 for WinSock ready...<br />
      &gt; USER anonymous<br /></font>&lt; 226-Maximum disk quota limited to Unlimited kBytes<br />
      &lt;     Used disk quota 0 kBytes, available Unlimited kBytes<br />
      &lt; 226 Transfer complete.<br /><font color="#ff0000">&lt; 331 User name okay, please send complete E-mail address
      as password.<br /></font><font color="#ff0000">&gt; PASS *****<br />
      &lt; 230 User logged in, proceed.<br /></font>&gt; CWD /<br />
      &lt; 250 Directory changed to /<br />
      &gt; TYPE I<br />
      &lt; 200 Type set to I.<br />
      &gt; PASV<br />
      &lt; 227 Entering Passive Mode (66,46,177,250,10,55)<br />
      &gt; RETR appnote.txt<br />
      Data connection established with 66.46.177.250:2615 on 9/27/2005 @ 2:38:09 PM<br />
      &lt; 150 Opening BINARY mode data connection for appnote.txt (109785 Bytes).<br />
      &lt; 426-Maximum disk quota limited to Unlimited kBytes<br />
      &lt;     Used disk quota 0 kBytes, available Unlimited kBytes<br />
      &lt; 426 Data connection closed, file transfer appnote.txt aborted.<br /><font color="#ff0000">&gt; QUIT<br />
      Disconnected from 66.46.177.250:21 on 9/27/2005 @ 2:38:13 PM<br />
      &gt; QUIT<br />
      Disconnected from 66.46.177.250:21 on 9/27/2005 @ 2:38:13 PM</font></pre>
        </div>
        <p>
        </p>
        <p>
      And the great part about all this is that you don't have to worry about this while
      coding. You're just manipulating yet another kind of AbstractFile or AbstractFolder.
   </p>
        <p>
      If we get back to the Zip implementation of the Xceed FileSystem, you can see that
      a ZippedFile or ZippedFolder (or ZipArchive, the root ZippedFolder) constructor needs
      to know which AbstractFile is holding the actual zip file that should contain this
      file or folder. "AbstractFile" truly means "any file", as long as there is an AbstractFile-derived
      class somewhere to expose this file. It means that zipping directly onto an FTP server
      is no more difficult than zipping in a regular file on disk.
   </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFolder
      source = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> DiskFolder(
      @"d:\Data" );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFolder
      localDest = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> ZipArchive( </span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> DiskFile(
      @"d:\temp\local.zip" ) );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFolder
      remoteDest = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> ZipArchive(</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpFile( </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpConnection(
      "localhost" ), @"remote.zip" ) );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      Copying is the same, no matter what is the destination</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      file or folder.</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">source.CopyTo(
      localDest, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">source.CopyTo(
      remoteDest, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> );</span>
          </pre>
        </div>
        <!--EndFragment-->
        <p>
      Code for zipping in "D:\temp\local.zip" is no different than code for zipping in "ftp://localhost/remote.zip".
      And obviously, reading or unzipping from any zip file is the same.
   </p>
        <div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;">
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFolder
      localSource = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> ZipArchive( </span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> DiskFile(
      @"d:\temp\local.zip" ) );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFolder
      remoteSource = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> ZipArchive(</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">  </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpFile( </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> FtpConnection(
      "localhost" ), @"remote.zip" ) );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">AbstractFolder
      dest = </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">new</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"> DiskFolder(
      @"d:\restored" );</span>
          </pre>
          <pre style="margin: 0px;"> </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);">//
      Unzipping text files from any source is the same!</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">localSource.CopyFilesTo(
      dest, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">,
      "*.txt" );</span>
          </pre>
          <pre style="margin: 0px;">
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">remoteSource.CopyFilesTo(
      dest, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">, </span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);">true</span>
            <span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">,
      "*.txt" );</span>
          </pre>
        </div>
        <!--EndFragment-->
        <p>
      I really hope this new addition to the Xceed FileSystem will generate the same enthusiasm
      we had inventing and developping it. I'm very interested in hearing your opinions!
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=78f813ed-96ee-4752-8ab5-2061b0f9d758" />
      </body>
      <title>Xceed FTP FileSystem - Finally released!</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,78f813ed-96ee-4752-8ab5-2061b0f9d758.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,78f813ed-96ee-4752-8ab5-2061b0f9d758.aspx</link>
      <pubDate>Wed, 05 Oct 2005 19:09:39 GMT</pubDate>
      <description>&lt;p&gt;
   I'm glad to announce that Xceed FTP for .NET 2.1 is &lt;a href="http://xceedsoft.com/download/downloadform.aspx?produitID=371"&gt;now
   available for download&lt;/a&gt;. I've been working on this release for the past few months,
   and I'm very excited to finally see the FTP FileSystem come to life.
&lt;/p&gt;
&lt;p&gt;
   For those not familiar with the Xceed FileSystem, which comes with Xceed Zip for .NET,
   here is some code that sheds some light on what you can do with it. Consider these
   variables of the same base type:
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   A file on disk&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFile
   first = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; DiskFile(
   @"d:\FileSystem.txt" );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   Another file on disk&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFile
   second = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; DiskFile(
   @"c:\temp\AnotherFileSystem.txt" );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   A file compressed in a zip file on disk&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFile
   third = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; ZippedFile( &lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; DiskFile(
   @"c:\temp\data.zip" ), "FileSystemInAZip.txt" );;&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   A file in the isolated storage&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFile
   fourth = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; IsolatedFile(
   "Isolated.txt" );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   A file in memory (random name)&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFile
   fifth = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; MemoryFile();&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   A file compressed in a zip file in memory&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFile
   sixth = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; ZippedFile( &lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; MemoryFile(),
   "VolatileFileSystem.txt" );&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   You can copy files around very easily:
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   Copying the first file anywhere else is always the same!&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;first.CopyTo(
   second, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;first.CopyTo(
   third, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;first.CopyTo(
   fourth, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;first.CopyTo(
   fifth, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;first.CopyTo(
   sixth, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; );&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   And accessing the contents of any file is always the same:
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; DisplayTextFile(
   AbstractFile file )&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;{&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   Console.WriteLine( "Displaying the contents of {0}, which is a {1}.", &lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; file.FullName,&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; file.GetType().Name );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;using&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;(
   StreamReader reader = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; StreamReader(
   file.OpenRead() ) )&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   {&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; line;&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;while&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;(
   ( line = reader.ReadLine() ) != &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; )&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; {&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; &amp;nbsp; Console.WriteLine( line );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; }&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   }&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   Console.WriteLine();&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;br&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   Displaying the contents of those files is always the same!&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;DisplayTextFile(
   first );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;DisplayTextFile(
   second );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;DisplayTextFile(
   third );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;DisplayTextFile(
   fourth );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;DisplayTextFile(
   fifth );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;DisplayTextFile(
   sixth );&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   And why not finish this demonstration by deleting the files we just created.
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   And finally, deleting files is the same!&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;second.Delete();&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;third.Delete();&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;fourth.Delete();&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;fifth.Delete();&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;sixth.Delete();&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   Any kind of file is an AbstractFile. Any kind of folder is an AbstractFolder. This
   way, a DiskFile, an IsolatedFile, a ZippedFile and a MemoryFile share a common set
   of properties and methods for accessing their metadata and reading/writing their actual
   data. And a DiskFolder, an IsolatedFolder, a ZippedFolder and a MemoryFolder share
   a common set of methods for discovering child items.
&lt;/p&gt;
&lt;p&gt;
   How does the FTP FileSystem come into play? Simply by offering the same abstraction
   over files and folders stored on an FTP server. We could simply add this code to the
   above sample, and everything works just as expected!
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFile
   seventh = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpFile( &lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpConnection(
   "localhost" ), @"\RemoteFileSystem.txt" );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;first.CopyTo(
   seventh, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;DisplayTextFile(
   seventh );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;seventh.Delete();&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   Let's dive a little bit into this implementation of an AbstractFile and AbstractFolder.
   Each constructor requires an FtpConnection instance, which contains information on
   how to connect to the target FTP server. Though it looks like a simple information
   storage class, it does much more. Each time an FtpFile or an FtpFolder requires information,
   or an incoming or outgoing stream on a file's data, it asks the FtpConnection for
   an active command channel connection to the server. This way, a unique command channel
   is generally required for accessing many files on the server.
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;using&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;(
   FtpConnection connection = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpConnection(
   "ftp.xceed.com" ) )&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;{&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   connection.TraceWriter = Console.Out;&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   FtpFolder root = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpFolder(
   connection );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;foreach&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;(
   AbstractFile file &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;in&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; root.GetFiles( &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;false&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;,
   "*.txt" ) )&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   {&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; DisplayTextFile( file );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   }&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   If we comment out the "Console.WriteLine( line );" line in "DisplayTextFile", we can
   see the FTP conversation that occurred for the above code:
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;Connected to 66.46.177.250:21 on 9/27/2005 @ 2:24:54 PM&lt;br&gt;
   &amp;lt; 220 Serv-U FTP Server v6.0 for WinSock ready...&lt;br&gt;
   &amp;gt; USER anonymous&lt;br&gt;
   &amp;lt; 331 User name okay, please send complete E-mail address as password.&lt;br&gt;
   &amp;gt; PASS *****&lt;br&gt;
   &amp;lt; 230 User logged in, proceed.&lt;br&gt;
   &amp;gt; PWD&lt;br&gt;
   &amp;lt; 257 "/" is current directory.&lt;br&gt;
   &amp;gt; CWD /&lt;br&gt;
   &amp;lt; 250 Directory changed to /&lt;br&gt;
   &amp;gt; CWD /&lt;br&gt;
   &amp;lt; 250 Directory changed to /&lt;br&gt;
   &amp;gt; CWD /&lt;br&gt;
   &amp;lt; 250 Directory changed to /&lt;br&gt;
   &amp;gt; TYPE A&lt;br&gt;
   &amp;lt; 200 Type set to A.&lt;br&gt;
   &amp;gt; PASV&lt;br&gt;
   &amp;lt; 227 Entering Passive Mode (66,46,177,250,6,238)&lt;br&gt;
   &amp;gt; LIST&lt;br&gt;
   Data connection established with 66.46.177.250:1774 on 9/27/2005 @ 2:24:56 PM&lt;br&gt;
   &amp;lt; 150 Opening ASCII mode data connection for /bin/ls.&lt;br&gt;
   &amp;lt; 226-Maximum disk quota limited to Unlimited kBytes&lt;br&gt;
   &amp;lt; Used disk quota 0 kBytes, available Unlimited kBytes&lt;br&gt;
   &amp;lt; 226 Transfer complete.&lt;br&gt;
   Displaying the contents of \FileSystem.txt, which is a FtpFile.&lt;br&gt;
   &amp;gt; CWD /&lt;br&gt;
   &amp;lt; 250 Directory changed to /&lt;br&gt;
   &amp;gt; TYPE I&lt;br&gt;
   &amp;lt; 200 Type set to I.&lt;br&gt;
   &amp;gt; PASV&lt;br&gt;
   &amp;lt; 227 Entering Passive Mode (66,46,177,250,6,240)&lt;br&gt;
   &amp;gt; RETR FileSystem.txt&lt;br&gt;
   Data connection established with 66.46.177.250:1776 on 9/27/2005 @ 2:24:57 PM&lt;br&gt;
   &amp;lt; 150 Opening BINARY mode data connection for FileSystem.txt (1198 Bytes).&lt;br&gt;
   &amp;lt; 226-Maximum disk quota limited to Unlimited kBytes&lt;br&gt;
   &amp;lt; Used disk quota 0 kBytes, available Unlimited kBytes&lt;br&gt;
   &amp;lt; 226 Transfer complete.&lt;br&gt;
   &lt;br&gt;
   Displaying the contents of \appnote.txt, which is a FtpFile.&lt;br&gt;
   &amp;gt; CWD /&lt;br&gt;
   &amp;lt; 250 Directory changed to /&lt;br&gt;
   &amp;gt; TYPE I&lt;br&gt;
   &amp;lt; 200 Type set to I.&lt;br&gt;
   &amp;gt; PASV&lt;br&gt;
   &amp;lt; 227 Entering Passive Mode (66,46,177,250,6,246)&lt;br&gt;
   &amp;gt; RETR appnote.txt&lt;br&gt;
   Data connection established with 66.46.177.250:1782 on 9/27/2005 @ 2:24:58 PM&lt;br&gt;
   &amp;lt; 150 Opening BINARY mode data connection for appnote.txt (109785 Bytes).&lt;br&gt;
   &amp;lt; 226-Maximum disk quota limited to Unlimited kBytes&lt;br&gt;
   &amp;lt; Used disk quota 0 kBytes, available Unlimited kBytes&lt;br&gt;
   &amp;lt; 226 Transfer complete.&lt;br&gt;
   &lt;br&gt;
   &amp;gt; QUIT&lt;br&gt;
   Disconnected from 66.46.177.250:21 on 9/27/2005 @ 2:25:04 PM&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
   Each FtpFolder and FtpFile instance shared the same FtpConnection, and since no two
   operations were done at the same time, a single connection was required, as the log
   indicates. The FtpConnection object implements the IDisposable interface, since it
   keeps any active connection available until disposed (or finalized).
&lt;/p&gt;
&lt;p&gt;
   Now what happens if I try to open two files at the same time, like this?
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;using&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;(
   FtpConnection connection = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpConnection(
   "ftp.xceed.com" ) )&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;{&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   connection.TraceWriter = Console.Out;&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   AbstractFile first = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpFile(
   connection, @"\FileSystem.txt" );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   AbstractFile second = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpFile(
   connection, @"\appnote.txt" );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;using&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;(
   Stream firstStream = first.OpenRead() )&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   {&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;using&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;(
   Stream secondStream = second.OpenRead() )&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; {&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   In an FTP conversation with an FTP server, only one command&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   at a time can be pending. Here, we clearly have two files&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   open at the same time on the same FTP server. How? Each file&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   has its own connection to the FTP server!&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   &amp;nbsp; }&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp;
   }&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   The FtpConnection object will create extra command channel connections as required.&amp;nbsp;The
   output shows two command channel connections were made:
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;font color="#ff0000"&gt;Connected
   to 66.46.177.250:21 on 9/27/2005 @ 2:38:06 PM&lt;br&gt;
   &amp;lt; 220 Serv-U FTP Server v6.0 for WinSock ready...&lt;br&gt;
   &amp;gt; USER anonymous&lt;br&gt;
   &amp;lt; 331 User name okay, please send complete E-mail address as password.&lt;br&gt;
   &amp;gt; PASS *****&lt;br&gt;
   &amp;lt; 230 User logged in, proceed.&lt;br&gt;
   &lt;/font&gt;&amp;gt; CWD /&lt;br&gt;
   &amp;lt; 250 Directory changed to /&lt;br&gt;
   &amp;gt; TYPE A&lt;br&gt;
   &amp;lt; 200 Type set to A.&lt;br&gt;
   &amp;gt; PASV&lt;br&gt;
   &amp;lt; 227 Entering Passive Mode (66,46,177,250,10,53)&lt;br&gt;
   &amp;gt; LIST&lt;br&gt;
   Data connection established with 66.46.177.250:2613 on 9/27/2005 @ 2:38:07 PM&lt;br&gt;
   &amp;lt; 150 Opening ASCII mode data connection for /bin/ls.&lt;br&gt;
   &amp;lt; 226-Maximum disk quota limited to Unlimited kBytes&lt;br&gt;
   &amp;lt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Used disk quota 0 kBytes, available Unlimited kBytes&lt;br&gt;
   &amp;lt; 226 Transfer complete.&lt;br&gt;
   &amp;gt; CWD /&lt;br&gt;
   &amp;lt; 250 Directory changed to /&lt;br&gt;
   &amp;gt; TYPE I&lt;br&gt;
   &amp;lt; 200 Type set to I.&lt;br&gt;
   &amp;gt; PASV&lt;br&gt;
   &amp;lt; 227 Entering Passive Mode (66,46,177,250,10,54)&lt;br&gt;
   &amp;gt; RETR FileSystem.txt&lt;br&gt;
   Data connection established with 66.46.177.250:2614 on 9/27/2005 @ 2:38:08 PM&lt;br&gt;
   &amp;lt; 150 Opening BINARY mode data connection for FileSystem.txt (1198 Bytes).&lt;br&gt;
   Connected to 66.46.177.250:21 on 9/27/2005 @ 2:38:08 PM&lt;br&gt;
   &lt;font color="#ff0000"&gt;&amp;lt; 220 Serv-U FTP Server v6.0 for WinSock ready...&lt;br&gt;
   &amp;gt; USER anonymous&lt;br&gt;
   &lt;/font&gt;&amp;lt; 226-Maximum disk quota limited to Unlimited kBytes&lt;br&gt;
   &amp;lt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Used disk quota 0 kBytes, available Unlimited kBytes&lt;br&gt;
   &amp;lt; 226 Transfer complete.&lt;br&gt;
   &lt;font color="#ff0000"&gt;&amp;lt; 331 User name okay, please send complete E-mail address
   as password.&lt;br&gt;
   &lt;/font&gt;&lt;font color="#ff0000"&gt;&amp;gt; PASS *****&lt;br&gt;
   &amp;lt; 230 User logged in, proceed.&lt;br&gt;
   &lt;/font&gt;&amp;gt; CWD /&lt;br&gt;
   &amp;lt; 250 Directory changed to /&lt;br&gt;
   &amp;gt; TYPE I&lt;br&gt;
   &amp;lt; 200 Type set to I.&lt;br&gt;
   &amp;gt; PASV&lt;br&gt;
   &amp;lt; 227 Entering Passive Mode (66,46,177,250,10,55)&lt;br&gt;
   &amp;gt; RETR appnote.txt&lt;br&gt;
   Data connection established with 66.46.177.250:2615 on 9/27/2005 @ 2:38:09 PM&lt;br&gt;
   &amp;lt; 150 Opening BINARY mode data connection for appnote.txt (109785 Bytes).&lt;br&gt;
   &amp;lt; 426-Maximum disk quota limited to Unlimited kBytes&lt;br&gt;
   &amp;lt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Used disk quota 0 kBytes, available Unlimited kBytes&lt;br&gt;
   &amp;lt; 426 Data connection closed, file transfer appnote.txt aborted.&lt;br&gt;
   &lt;font color="#ff0000"&gt;&amp;gt; QUIT&lt;br&gt;
   Disconnected from 66.46.177.250:21 on 9/27/2005 @ 2:38:13 PM&lt;br&gt;
   &amp;gt; QUIT&lt;br&gt;
   Disconnected from 66.46.177.250:21 on 9/27/2005 @ 2:38:13 PM&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
   And the great part about all this is that you don't have to worry about this while
   coding. You're just manipulating yet another kind of AbstractFile or AbstractFolder.
&lt;/p&gt;
&lt;p&gt;
   If we get back to the Zip implementation of the Xceed FileSystem, you can see that
   a ZippedFile or ZippedFolder (or ZipArchive, the root ZippedFolder) constructor needs
   to know which AbstractFile is holding the actual zip file that should contain this
   file or folder. "AbstractFile" truly means "any file", as long as there is an AbstractFile-derived
   class somewhere to expose this file. It means that zipping directly onto an FTP server
   is no more difficult than zipping in a regular file on disk.
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFolder
   source = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; DiskFolder(
   @"d:\Data" );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFolder
   localDest = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; ZipArchive( &lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; DiskFile(
   @"d:\temp\local.zip" ) );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFolder
   remoteDest = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; ZipArchive(&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpFile( &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpConnection(
   "localhost" ), @"remote.zip" ) );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   Copying is the same, no matter what is the destination&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   file or folder.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;source.CopyTo(
   localDest, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;source.CopyTo(
   remoteDest, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; );&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   Code for zipping in "D:\temp\local.zip" is no different than code for zipping in "ftp://localhost/remote.zip".
   And obviously, reading or unzipping from any zip file is the same.
&lt;/p&gt;
&lt;div style="border: 1pt solid windowtext; padding: 0pt; background: rgb(255, 255, 255) none repeat scroll 0%; font-size: 8pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 0); font-family: Courier New;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFolder
   localSource = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; ZipArchive( &lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; DiskFile(
   @"d:\temp\local.zip" ) );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFolder
   remoteSource = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; ZipArchive(&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpFile( &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; FtpConnection(
   "localhost" ), @"remote.zip" ) );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;AbstractFolder
   dest = &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt; DiskFolder(
   @"d:\restored" );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 128, 0);"&gt;//
   Unzipping text files from any source is the same!&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;localSource.CopyFilesTo(
   dest, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;,
   "*.txt" );&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="margin: 0px;"&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;remoteSource.CopyFilesTo(
   dest, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;, &lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="background: rgb(255, 255, 255) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"&gt;,
   "*.txt" );&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   I really hope this new addition to the Xceed FileSystem will generate the same enthusiasm
   we had inventing and developping it. I'm very interested in hearing your opinions!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=78f813ed-96ee-4752-8ab5-2061b0f9d758" /&gt;</description>
      <category>.NET;FileSystem;FTP;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=5bba8ded-a7b0-40ce-ae9f-33b3c3cbb4e3</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,5bba8ded-a7b0-40ce-ae9f-33b3c3cbb4e3.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      In the new package v1.2.5309 which will be <a href="http://www.xceedsoft.com/download/updates.aspx">available
      for download</a> next week resides a new feature you won't see much emphasis
      about, but which I was very eager to complete. You can now create a <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.ziparchive.html">ZipArchive</a> instance
      around an AbstractFile that does not support reading from.
   </p>
        <p>
      (drum roll) ... (looking around) ... Nobody's applauding? That's because you probably
      don't know yet how useful this can be.
   </p>
        <p>
      Most ASP.NET applications that wish to create zip files on the fly and send them in
      the response are either stuck with creating those zip files on disk in a temporary
      filename, or create them in a <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.memoryfile.html">MemoryFile</a>,
      then copy that MemoryFile in the response stream.
   </p>
        <p>
      However, the <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.streamfile.html">StreamFile</a> class
      was created for such purposes of exposing any existing Stream as an AbstractFile.
      You already could create a StreamFile around the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebhttpresponseclasstopic.asp">Response</a>'s <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebhttpresponseclassoutputstreamtopic.asp">OutputStream</a>.
      But passing that StreamFile to the ZipArchive's constructor would fail, because it
      can't read from it. Instead of assuming an empty zip file, it miserably failed. Shame.
   </p>
        <p>
      No more... Since version 2.2.5302, it will assume the zip file is empty. So code like
      this works perfectly:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ">
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">void</span> ProcessRequest(HttpContext
      context)</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      context.Response.ContentType = "application/zip";</pre>
          <pre style="MARGIN: 0px">      context.Response.AddHeader( "Content-Disposition", "attachment; filename=images.bmp" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      ZipArchive archive = <span style="COLOR: #0000ff">new</span> ZipArchive( <span style="COLOR: #0000ff">new</span> StreamFile(
      context.Response.OutputStream ) );</pre>
          <pre style="MARGIN: 0px">      DiskFolder source = <span style="COLOR: #0000ff">new</span> DiskFolder(
      context.Request.MapPath( "." ) );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      source.CopyFilesTo( archive, <span style="COLOR: #0000ff">false</span>, <span style="COLOR: #0000ff">false</span>,
      "*.bmp" );</pre>
          <pre style="MARGIN: 0px">    }</pre>
        </div>
        <!--EndFragment-->
        <p>
      The same problem appeared when trying to combine <a href="http://www.xceedsoft.com/products/ZipNet/index.aspx">Xceed
      Zip for .NET</a> with <a href="http://www.xceedsoft.com/products/FtpNet/index.aspx">Xceed
      FTP for .NET</a>, to upload zip files directly on the FTP server. Though the <a href="http://doc.xceedsoft.com/products/ftpNet/ref/xceed.ftp.ftpclient.html">FtpClient</a> class
      exposes a very useful <a href="http://doc.xceedsoft.com/products/ftpNet/ref/xceed.ftp.ftpclient.getuploadstream_overloads.html">GetUploadStream</a> method
      to get a direct stream on the data connection, code like this previously failed.
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ">
          <pre style="MARGIN: 0px">          <span style="COLOR: #0000ff">using</span>(
      Stream upload = client.GetUploadStream( "images.zip" ) )</pre>
          <pre style="MARGIN: 0px">          {</pre>
          <pre style="MARGIN: 0px">            ZipArchive archive = <span style="COLOR: #0000ff">new</span> ZipArchive( <span style="COLOR: #0000ff">new</span> StreamFile(
      upload ) );</pre>
          <pre style="MARGIN: 0px">            DiskFolder source = <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"d:\images\" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">            source.CopyFilesTo( archive, <span style="COLOR: #0000ff">false</span>, <span style="COLOR: #0000ff">false</span>,
      "*.bmp" );</pre>
          <pre style="MARGIN: 0px">          }</pre>
        </div>
        <!--EndFragment-->
        <p>
      Talk about short and sweet uploads of zip files!<!--StartFragment --></p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=5bba8ded-a7b0-40ce-ae9f-33b3c3cbb4e3" />
      </body>
      <title>Zipping from ASP.NET or to an FTP server</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,5bba8ded-a7b0-40ce-ae9f-33b3c3cbb4e3.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,5bba8ded-a7b0-40ce-ae9f-33b3c3cbb4e3.aspx</link>
      <pubDate>Thu, 09 Jun 2005 18:56:43 GMT</pubDate>
      <description>&lt;p&gt;
   In the new package v1.2.5309 which will be&amp;nbsp;&lt;a href="http://www.xceedsoft.com/download/updates.aspx"&gt;available
   for download&lt;/a&gt;&amp;nbsp;next week&amp;nbsp;resides a new feature you won't see much emphasis
   about, but which I was very eager to complete. You can now create a &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.ziparchive.html"&gt;ZipArchive&lt;/a&gt; instance
   around an AbstractFile that does not support reading from.
&lt;/p&gt;
&lt;p&gt;
   (drum roll) ... (looking around) ... Nobody's applauding? That's because you probably
   don't know yet how useful this can be.
&lt;/p&gt;
&lt;p&gt;
   Most ASP.NET applications that wish to create zip files on the fly and send them in
   the response are either stuck with creating those zip files on disk in a temporary
   filename, or create them in a &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.memoryfile.html"&gt;MemoryFile&lt;/a&gt;,
   then copy that MemoryFile in the response stream.
&lt;/p&gt;
&lt;p&gt;
   However, the &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.streamfile.html"&gt;StreamFile&lt;/a&gt; class
   was created for such purposes of exposing any existing Stream as an AbstractFile.
   You already could create a StreamFile around the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebhttpresponseclasstopic.asp"&gt;Response&lt;/a&gt;'s &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebhttpresponseclassoutputstreamtopic.asp"&gt;OutputStream&lt;/a&gt;.
   But passing that StreamFile to the ZipArchive's constructor would fail, because it
   can't read from it. Instead of assuming an empty zip file, it miserably failed. Shame.
&lt;/p&gt;
&lt;p&gt;
   No more... Since version 2.2.5302, it will assume the zip file is empty. So code like
   this works perfectly:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ"&gt;&lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; ProcessRequest(HttpContext
   context)&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; context.Response.ContentType = "application/zip";&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; context.Response.AddHeader( "Content-Disposition", "attachment; filename=images.bmp" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ZipArchive archive = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive( &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; StreamFile(
   context.Response.OutputStream ) );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; DiskFolder source = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   context.Request.MapPath( "." ) );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; source.CopyFilesTo( archive, &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;,
   "*.bmp" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   The same problem appeared when trying to combine &lt;a href="http://www.xceedsoft.com/products/ZipNet/index.aspx"&gt;Xceed
   Zip for .NET&lt;/a&gt; with &lt;a href="http://www.xceedsoft.com/products/FtpNet/index.aspx"&gt;Xceed
   FTP for .NET&lt;/a&gt;, to upload zip files directly on the FTP server. Though the &lt;a href="http://doc.xceedsoft.com/products/ftpNet/ref/xceed.ftp.ftpclient.html"&gt;FtpClient&lt;/a&gt; class
   exposes a very useful &lt;a href="http://doc.xceedsoft.com/products/ftpNet/ref/xceed.ftp.ftpclient.getuploadstream_overloads.html"&gt;GetUploadStream&lt;/a&gt; method
   to get a direct stream on the data connection, code like this previously failed.
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ"&gt;&lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;(
   Stream upload = client.GetUploadStream( "images.zip" ) )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ZipArchive archive = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive( &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; StreamFile(
   upload ) );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; DiskFolder source = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"d:\images\" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; source.CopyFilesTo( archive, &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;,
   "*.bmp" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   Talk about short and sweet uploads of zip files!&lt;!--StartFragment --&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=5bba8ded-a7b0-40ce-ae9f-33b3c3cbb4e3" /&gt;</description>
      <category>.NET;FileSystem;FTP;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=cff8fc14-76a1-4fde-a4f0-a49ab582a21a</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,cff8fc14-76a1-4fde-a4f0-a49ab582a21a.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      Lately, people have been asking us how to abort a zipping operation with Xceed Zip
      for .NET. The official answer is "you can't", as there is no method or property exposed
      for this task, as opposed to Xceed Zip ActiveX with its simple Abort property. But
      the truth is you can, with relatively little coding.
   </p>
        <p>
      Before we get into how to abort, let's talk a little bit about the ZipArchive's TempFolder
      property. By default, it points to the same folder as the static ZipArchive.DefaultTempFolder
      property, which itself points to the user's temp folder, as exposed by System.IO.Path.GetTempPath().
   </p>
        <p>
      Though the library is designed to delete any file it creates in the temporary folder,
      this can occur only when instances get finalized if the operation failed in the middle
      of the process.
   </p>
        <p>
      A good coding pattern I like to use is the following:
   </p>
        <pre style="MARGIN: 0px">
          <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ">
            <pre style="MARGIN: 0px">    ZipArchive zip = <span style="COLOR: #0000ff">new</span> ZipArchive( <span style="COLOR: #0000ff">new</span> DiskFile(
      @"d:\temp\backup.zip" ) );</pre>
            <pre style="MARGIN: 0px">    zip.TempFolder = zip.TempFolder.CreateFolder( Guid.NewGuid().ToString() );</pre>
            <pre style="MARGIN: 0px"> </pre>
            <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">try</span></pre>
            <pre style="MARGIN: 0px">    {</pre>
            <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">using</span>(
      AutoBatchUpdate auto = <span style="COLOR: #0000ff">new</span> AutoBatchUpdate( zip
      ) )</pre>
            <pre style="MARGIN: 0px">      {</pre>
            <pre style="MARGIN: 0px">        DiskFolder source = <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"d:\Data" );</pre>
            <pre style="MARGIN: 0px">        source.CopyTo( zip, <span style="COLOR: #0000ff">true</span> );</pre>
            <pre style="MARGIN: 0px">      }</pre>
            <pre style="MARGIN: 0px">    }</pre>
            <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">finally</span></pre>
            <pre style="MARGIN: 0px">    {</pre>
            <pre style="MARGIN: 0px">      zip.TempFolder.Delete();</pre>
            <pre style="MARGIN: 0px">    }</pre>
          </div>
          <!--EndFragment-->
        </pre>
        <!--EndFragment-->
        <p>
      This makes sure no temp file survive a zipping cycle. And with that pattern, I can
      set the "default" temporary location once using the static DefaultTempFolder property,
      and each instance will use a unique folder within this starting point.
   </p>
        <p dir="ltr">
      Now that my zipping operations are cleaning their traces, we're ready to talk about
      aborting. Some key concepts:
   </p>
        <ul dir="ltr">
          <li>
            <div>The library isn't pumping messages, and does not offer async operations. If you
            want your WinForms application's "Abort" button to react, you will have to pump messages
            yourself somewhere.
         </div>
          </li>
          <li>
            <div>There are three major operations behind the creation or modification of
            a zip file:
         </div>
          </li>
          <ul>
            <li>
              <div>Compressing each new file.
            </div>
            </li>
            <li>
              <div>Moving each file to keep from the original zip file (if updating an existing
               zip file).
            </div>
            </li>
            <li>
              <div>Building the target zip file by appending data created by the above two steps.
            </div>
            </li>
          </ul>
          <li>
            <div>Zip and FileSystem events get raised at many levels, so you should pass your
            ZipEvents instance everywhere an overload accepting a FileSystemEvents or ZipEvents
            instance exists.
         </div>
          </li>
        </ul>
        <p>
      Your "Abort" button (or any abort input you like) will simply raise a flag. It can't
      do more.
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ">
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">private</span><span style="COLOR: #0000ff">bool</span> m_abort
      = <span style="COLOR: #0000ff">false</span>;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">private</span><span style="COLOR: #0000ff">void</span> AbortButton_Click(<span style="COLOR: #0000ff">object</span> sender,
      System.EventArgs e)</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      m_abort = <span style="COLOR: #0000ff">true</span>;</pre>
          <pre style="MARGIN: 0px">    }</pre>
        </div>
        <!--EndFragment-->
        <!--EndFragment-->
        <!--EndFragment-->
        <p>
      Then you handle three events matching the forementioned three steps, pump messages
      to keep a responsive application, and check if the flag is raised. You can safely
      use the same method for handling the three events.
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ">
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">private</span><span style="COLOR: #0000ff">void</span> CheckAbort_ByteProgression(<span style="COLOR: #0000ff">object</span> sender,
      ByteProgressionEventArgs e)</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">if</span>(
      m_abort )</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">throw</span><span style="COLOR: #0000ff">new</span> ApplicationException(
      "The user aborted the operation." );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      Application.DoEvents();</pre>
          <pre style="MARGIN: 0px">    }</pre>
        </div>
        <!--EndFragment-->
        <p>
      As you can see, if the flag is raised, I'm throwing an ApplicationException. This
      will result in a System.Reflection.TargetInvocationException being thrown by the originally
      called method. To get a well-behaved application, you obviously want to trap any exception
      the FileSystem could throw. You can catch any TargetInvocationException to display
      an "operation aborted" message. Here's my code for the full operation:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ">
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">private</span><span style="COLOR: #0000ff">void</span> StartButton_Click(<span style="COLOR: #0000ff">object</span> sender,
      System.EventArgs e)</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      m_abort = <span style="COLOR: #0000ff">false</span>;</pre>
          <pre style="MARGIN: 0px">      StartButton.Enabled = <span style="COLOR: #0000ff">false</span>;</pre>
          <pre style="MARGIN: 0px">      AbortButton.Enabled = <span style="COLOR: #0000ff">true</span>;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">try</span></pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        ZipEvents events = <span style="COLOR: #0000ff">new</span> ZipEvents();</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">        <span style="BACKGROUND: #ffffff; COLOR: #008000">//
      Advise for the three main events for checking abort flag.</span></pre>
          <pre style="MARGIN: 0px">        events.ByteProgression += </pre>
          <pre style="MARGIN: 0px">          <span style="COLOR: #0000ff">new</span> ByteProgressionEventHandler(
      CheckAbort_ByteProgression );</pre>
          <pre style="MARGIN: 0px">        events.GatheringZipContentByteProgression += </pre>
          <pre style="MARGIN: 0px">          <span style="COLOR: #0000ff">new</span> GatheringZipContentByteProgressionEventHandler(
      CheckAbort_ByteProgression );</pre>
          <pre style="MARGIN: 0px">        events.BuildingZipByteProgression += </pre>
          <pre style="MARGIN: 0px">          <span style="COLOR: #0000ff">new</span> BuildingZipByteProgressionEventHandler(
      CheckAbort_ByteProgression );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">        <span style="BACKGROUND: #ffffff; COLOR: #008000">//
      What's cool with delegates is that you can separate logic from UI.</span></pre>
          <pre style="MARGIN: 0px">        events.ByteProgression += </pre>
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">new</span> ByteProgressionEventHandler(
      UpdateUI_ByteProgression );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">        ZipArchive zip = <span style="COLOR: #0000ff">new</span> ZipArchive( </pre>
          <pre style="MARGIN: 0px">          events, <span style="COLOR: #0000ff">null</span>, <span style="COLOR: #0000ff">new</span> DiskFile(
      @"d:\temp\backup.zip" ) );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">        zip.TempFolder = zip.TempFolder.CreateFolder( Guid.NewGuid().ToString() );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">try</span></pre>
          <pre style="MARGIN: 0px">        {</pre>
          <pre style="MARGIN: 0px">          <span style="COLOR: #0000ff">using</span>(
      AutoBatchUpdate auto = <span style="COLOR: #0000ff">new</span> AutoBatchUpdate( zip,
      events, <span style="COLOR: #0000ff">null</span> ) )</pre>
          <pre style="MARGIN: 0px">          {</pre>
          <pre style="MARGIN: 0px">            DiskFolder source = <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"d:\Data" );</pre>
          <pre style="MARGIN: 0px">            source.CopyTo( events, <span style="COLOR: #0000ff">null</span>,
      zip, <span style="COLOR: #0000ff">true</span> );</pre>
          <pre style="MARGIN: 0px">          }</pre>
          <pre style="MARGIN: 0px">        }</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">finally</span></pre>
          <pre style="MARGIN: 0px">        {</pre>
          <pre style="MARGIN: 0px">          zip.TempFolder.Delete();</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">          <span style="BACKGROUND: #ffffff; COLOR: #008000">//
      Clean up events.</span></pre>
          <pre style="MARGIN: 0px">          events.ByteProgression -= </pre>
          <pre style="MARGIN: 0px">            <span style="COLOR: #0000ff">new</span> ByteProgressionEventHandler(
      CheckAbort_ByteProgression );</pre>
          <pre style="MARGIN: 0px">          events.GatheringZipContentByteProgression -= </pre>
          <pre style="MARGIN: 0px">            <span style="COLOR: #0000ff">new</span> GatheringZipContentByteProgressionEventHandler(
      CheckAbort_ByteProgression );</pre>
          <pre style="MARGIN: 0px">          events.BuildingZipByteProgression -= </pre>
          <pre style="MARGIN: 0px">            <span style="COLOR: #0000ff">new</span> BuildingZipByteProgressionEventHandler(
      CheckAbort_ByteProgression );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">          events.ByteProgression -= </pre>
          <pre style="MARGIN: 0px">            <span style="COLOR: #0000ff">new</span> ByteProgressionEventHandler(
      UpdateUI_ByteProgression );</pre>
          <pre style="MARGIN: 0px">        }</pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">catch</span>(
      System.Reflection.TargetInvocationException except )</pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        MessageBox.Show( except.InnerException.Message, "Abort" );</pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">catch</span>(
      Exception except )</pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        MessageBox.Show( except.Message, "Error" );</pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">finally</span></pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        AbortButton.Enabled = <span style="COLOR: #0000ff">false</span>;</pre>
          <pre style="MARGIN: 0px">        StartButton.Enabled = <span style="COLOR: #0000ff">true</span>;</pre>
          <pre style="MARGIN: 0px">        m_abort = <span style="COLOR: #0000ff">false</span>;</pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px">    }</pre>
        </div>
        <p>
      Things to notice:
   </p>
        <ul>
          <li>
         I'm passing my "events" instance to:</li>
          <ul>
            <li>
            The ZipArchive's ctor. You could handle the ReadingZipItemProgression events.</li>
            <li>
            The AutoBatchUpdate ctor, which will in turn pass it to both BeginUpdate and EndUpdate.
            The later method will generate the GatheringZipContentByteProgression and BuildingZipByteProgression
            events.</li>
            <li>
            The CopyTo method. It will generate the ByteProgression events.</li>
          </ul>
          <li>
         I'm advising two times for the ByteProgression events, once for handling abort conditions,
         and another for updating my UI. This is a cool way to leverage delegates and separate
         the logic from the UI.<!--EndFragment--></li>
        </ul>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=cff8fc14-76a1-4fde-a4f0-a49ab582a21a" />
      </body>
      <title>Aborting a zip operation</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,cff8fc14-76a1-4fde-a4f0-a49ab582a21a.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,cff8fc14-76a1-4fde-a4f0-a49ab582a21a.aspx</link>
      <pubDate>Thu, 19 May 2005 20:53:12 GMT</pubDate>
      <description>&lt;p&gt;
   Lately, people have been asking us how to abort a zipping operation with Xceed Zip
   for .NET. The official answer is "you can't", as there is no method or property exposed
   for this task, as opposed to Xceed Zip ActiveX with its simple Abort property. But
   the truth is you can, with relatively little coding.
&lt;/p&gt;
&lt;p&gt;
   Before we get into how to abort, let's talk a little bit about the ZipArchive's TempFolder
   property. By default, it points to the same folder as the static ZipArchive.DefaultTempFolder
   property, which itself points to the user's temp folder, as exposed by System.IO.Path.GetTempPath().
&lt;/p&gt;
&lt;p&gt;
   Though the library is designed to delete any file it creates in the temporary folder,
   this can occur only when instances get finalized if the operation failed in the middle
   of the process.
&lt;/p&gt;
&lt;p&gt;
   A good coding pattern I like to use is the following:
&lt;/p&gt;
&lt;pre style="MARGIN: 0px"&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ"&gt;&lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; ZipArchive zip = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive( &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFile(
   @"d:\temp\backup.zip" ) );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; zip.TempFolder = zip.TempFolder.CreateFolder( Guid.NewGuid().ToString() );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;(
   AutoBatchUpdate auto = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; AutoBatchUpdate( zip
   ) )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; DiskFolder source = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"d:\Data" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; source.CopyTo( zip, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt; );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;finally&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; zip.TempFolder.Delete();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;&lt;/pre&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   This makes sure no temp file survive a zipping cycle. And with that pattern, I can
   set the "default" temporary location once using the static DefaultTempFolder property,
   and each instance will use a unique folder within this starting point.
&lt;/p&gt;
&lt;p dir=ltr&gt;
   Now that my zipping operations are cleaning their traces, we're ready to talk about
   aborting. Some key concepts:
&lt;/p&gt;
&lt;ul dir=ltr&gt;
   &lt;li&gt;
      &lt;div&gt;The library isn't pumping messages, and does not offer async operations. If you
         want your WinForms application's "Abort" button to react, you will have to pump messages
         yourself somewhere.
      &lt;/div&gt;
   &lt;/li&gt;
   &lt;li&gt;
      &lt;div&gt;There are three major operations behind&amp;nbsp;the creation or modification of
         a zip file:
      &lt;/div&gt;
   &lt;/li&gt;
   &lt;ul&gt;
      &lt;li&gt;
         &lt;div&gt;Compressing each new file.
         &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
         &lt;div&gt;Moving each file to keep from the original zip file (if updating an existing
            zip file).
         &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
         &lt;div&gt;Building the target zip file by appending data created by the above two steps.
         &lt;/div&gt;
      &lt;/li&gt;
   &lt;/ul&gt;
   &lt;li&gt;
      &lt;div&gt;Zip and FileSystem events get raised at many levels, so you should pass your
         ZipEvents instance everywhere an overload accepting a FileSystemEvents or ZipEvents
         instance exists.
      &lt;/div&gt;
   &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   Your "Abort" button (or any abort input you like) will simply raise a flag. It can't
   do more.
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ"&gt;&lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;bool&lt;/span&gt; m_abort
   = &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; AbortButton_Click(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; sender,
   System.EventArgs e)&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; m_abort = &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;!--EndFragment--&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   Then you handle three events matching the&amp;nbsp;forementioned three steps, pump messages
   to keep a responsive application, and check if the flag is raised. You can safely
   use the same method for handling the three events.
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ"&gt;&lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; CheckAbort_ByteProgression(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; sender,
   ByteProgressionEventArgs e)&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(
   m_abort )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ApplicationException(
   "The user aborted the operation." );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Application.DoEvents();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   As you can see, if the flag is raised, I'm throwing an ApplicationException. This
   will result in a System.Reflection.TargetInvocationException being thrown by the originally
   called method. To get a well-behaved application, you obviously want to trap any exception
   the FileSystem could throw. You can catch any TargetInvocationException to display
   an "operation aborted" message. Here's my code for the full operation:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ"&gt;&lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; StartButton_Click(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; sender,
   System.EventArgs e)&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; m_abort = &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; StartButton.Enabled = &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; AbortButton.Enabled = &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ZipEvents events = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipEvents();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="BACKGROUND: #ffffff; COLOR: #008000"&gt;//
   Advise for the three main events for checking abort flag.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; events.ByteProgression += &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ByteProgressionEventHandler(
   CheckAbort_ByteProgression );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; events.GatheringZipContentByteProgression += &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; GatheringZipContentByteProgressionEventHandler(
   CheckAbort_ByteProgression );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; events.BuildingZipByteProgression += &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; BuildingZipByteProgressionEventHandler(
   CheckAbort_ByteProgression );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="BACKGROUND: #ffffff; COLOR: #008000"&gt;//
   What's cool with delegates is that you can separate logic from UI.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; events.ByteProgression += &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;          &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ByteProgressionEventHandler(
   UpdateUI_ByteProgression );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ZipArchive zip = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive( &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;          events, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFile(
   @"d:\temp\backup.zip" ) );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; zip.TempFolder = zip.TempFolder.CreateFolder( Guid.NewGuid().ToString() );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;(
   AutoBatchUpdate auto = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; AutoBatchUpdate( zip,
   events, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; ) )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; DiskFolder source = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"d:\Data" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; source.CopyTo( events, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;,
   zip, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt; );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;finally&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; zip.TempFolder.Delete();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="BACKGROUND: #ffffff; COLOR: #008000"&gt;//
   Clean up events.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; events.ByteProgression -= &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ByteProgressionEventHandler(
   CheckAbort_ByteProgression );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; events.GatheringZipContentByteProgression -= &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; GatheringZipContentByteProgressionEventHandler(
   CheckAbort_ByteProgression );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; events.BuildingZipByteProgression -= &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; BuildingZipByteProgressionEventHandler(
   CheckAbort_ByteProgression );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; events.ByteProgression -= &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ByteProgressionEventHandler(
   UpdateUI_ByteProgression );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;catch&lt;/span&gt;(
   System.Reflection.TargetInvocationException except )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; MessageBox.Show( except.InnerException.Message, "Abort" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;catch&lt;/span&gt;(
   Exception except )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; MessageBox.Show( except.Message, "Error" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;finally&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AbortButton.Enabled = &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; StartButton.Enabled = &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; m_abort = &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
   Things to notice:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      I'm passing my "events" instance to:&lt;/li&gt;
   &lt;ul&gt;
      &lt;li&gt;
         The ZipArchive's ctor. You could handle the ReadingZipItemProgression events.&lt;/li&gt;
      &lt;li&gt;
         The AutoBatchUpdate ctor, which will in turn pass it to both BeginUpdate and EndUpdate.
         The later method will generate the GatheringZipContentByteProgression and BuildingZipByteProgression
         events.&lt;/li&gt;
      &lt;li&gt;
         The CopyTo method. It will generate the ByteProgression events.&lt;/li&gt;
   &lt;/ul&gt;
   &lt;li&gt;
      I'm advising two times for the ByteProgression events, once for handling abort conditions,
      and another for updating my UI. This is a cool way to leverage delegates and separate
      the logic from the UI.&lt;!--EndFragment--&gt;
   &lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=cff8fc14-76a1-4fde-a4f0-a49ab582a21a" /&gt;</description>
      <category>.NET;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p dir="ltr" style="MARGIN-RIGHT: 0px">
      I just got bitten by the .NET Framework COM interrop. We had a problem with Xceed
      Zip ActiveX used in a .NET application. If the application was handling the ZipPreprocessingFile
      event and changed the sFilename parameter (BSTR*, or ByRef String if you wish), <strong>sometimes</strong> the
      library did not change the filename in the resulting zip file.
   </p>
        <p>
      That "sometimes" was the mysterious part, though I had a good idea where the problem
      was. The method which fires the ZipPreprocessingFile event makes a dangerous, but
      up until now valid assumption. The kind of assumption that would make <a href="http://blogs.msdn.com/oldnewthing/">Raymond
      Chen</a> or <a href="http://pluralsight.com/blogs/dbox/">Don Box</a> real mad. It
      took for granted that the BSTR address would change if the callee was to change the
      BSTR. I made this assumption based on two facts:
   </p>
        <ol>
          <li>
         A BSTR is an immutable entity. If you need to modify one, you <strong>should</strong> create
         a copy with the new content. 
      </li>
          <li>
            <p dir="ltr">
            If the implementation of a function that takes a BSTR reference parameter assigns
            a new BSTR to the parameter, it must free the previously referenced BSTR. (written
            "as is" in MSDN)
         </p>
          </li>
        </ol>
        <p>
      The .NET code that reproduces the problem does a very simple thing:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
      sFilename = sFilename &amp; "new"
   </p>
        </blockquote>
        <p dir="ltr">
      Normally, languages will work with the provided BSTR* as is. And if a modification
      occurs, they will allocate the required new BSTR, copy chars from the old BSTR, then
      free it. The new string cannot have the same address as the old one.
   </p>
        <p dir="ltr">
      In .NET, the COM interrop is actually making a copy of the BSTR to create a System.String,
      work with that System.String throughout the function, then checks if the
      string changed before returning control to the COM caller, making either a call to
      SysReAllocString on the old BSTR, using the String as the "psz" parameter, or simply
      freeing the old BSTR, then allocate the new one based on the String.
   </p>
        <p dir="ltr">
      Bam! Turns out SysReAllocString or SysAllocString <strong>sometimes</strong> reallocate
      the new BSTR at the <strong>same address</strong> as the old one. Can't argue against
      that. My bad.
   </p>
        <p dir="ltr">
      Three things to conclude with that:
   </p>
        <ol dir="ltr">
          <li>
            <div>You can never use what you experiment as a proof of concept. Experiments and
            tests are always a subset of the big picture.
         </div>
          </li>
          <li>
            <div>Don't try to make assumptions larger than the initial statement. Assuming that
            a pointer wouldn't change just because a BSTR* parameter must be freed if changed
            was stretching the actual fact.
         </div>
          </li>
          <li>
            <div>Optimizations may sound good, but can always introduce more problems. Simplicity
            is bliss.
         </div>
          </li>
        </ol>
        <p>
      By the way, I realized I could try a very simple VB6 test. If once the old BSTR is
      freed any new BSTR can end-up at the same address, does it mean that a VB6 application
      modifying the sFilename parameter <strong>twice</strong> can reproduce the same
      bug? Absolutely! My VB6 sample application did this in ZipPreprocessingFile:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
      sFilename = sFilename &amp; ".foo"<br />
      sFilename = sFilename &amp; ".bar"
   </p>
        </blockquote>
        <p dir="ltr">
      Turns out files are <strong>sometimes</strong> renamed, <strong>sometimes</strong> not...
      Sometimes, I feel like an...
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d" />
      </body>
      <title>Bitten by the .NET Framework COM interrop</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d.aspx</link>
      <pubDate>Tue, 19 Apr 2005 13:17:39 GMT</pubDate>
      <description>&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   I just got bitten by the .NET Framework COM interrop. We had a problem with Xceed
   Zip ActiveX used in a .NET application. If the application was handling the ZipPreprocessingFile
   event and changed the sFilename parameter (BSTR*, or ByRef String if you wish), &lt;strong&gt;sometimes&lt;/strong&gt; the
   library did not change the filename in the resulting zip file.
&lt;/p&gt;
&lt;p&gt;
   That "sometimes" was the mysterious part, though I had a good idea where the problem
   was. The method which fires the ZipPreprocessingFile event makes a dangerous, but
   up until now valid assumption. The kind of assumption that would make &lt;a href="http://blogs.msdn.com/oldnewthing/"&gt;Raymond
   Chen&lt;/a&gt; or &lt;a href="http://pluralsight.com/blogs/dbox/"&gt;Don Box&lt;/a&gt; real mad. It
   took for granted that the BSTR address would change if the callee was to change the
   BSTR. I made this assumption based on two facts:
&lt;/p&gt;
&lt;ol&gt;
   &lt;li&gt;
      A&amp;nbsp;BSTR is an immutable entity. If you need to modify one, you &lt;strong&gt;should&lt;/strong&gt; create
      a copy with&amp;nbsp;the new content. 
   &lt;li&gt;
      &lt;p dir=ltr&gt;
         If the implementation of a function that takes a BSTR reference parameter assigns
         a new BSTR to the parameter, it must free the previously referenced BSTR. (written
         "as is" in MSDN)
      &lt;/p&gt;
   &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   The .NET code that reproduces the problem does a very simple thing:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   sFilename = sFilename &amp;amp; "new"
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   Normally, languages will work with the provided BSTR* as is. And if a modification
   occurs, they will allocate the required new BSTR, copy chars from the old BSTR, then
   free it. The new string cannot have the same address as the old one.
&lt;/p&gt;
&lt;p dir=ltr&gt;
   In .NET, the COM interrop is actually making a copy of the BSTR to create a System.String,
   work with&amp;nbsp;that System.String&amp;nbsp;throughout the function, then checks if the
   string changed before returning control to the COM caller, making either a call to
   SysReAllocString on the old BSTR, using the String as the "psz" parameter, or simply
   freeing the old BSTR, then allocate the new one based on the String.
&lt;/p&gt;
&lt;p dir=ltr&gt;
   Bam! Turns out SysReAllocString or SysAllocString&amp;nbsp;&lt;strong&gt;sometimes&lt;/strong&gt; reallocate
   the new BSTR at the &lt;strong&gt;same address&lt;/strong&gt; as the old one. Can't argue against
   that. My bad.
&lt;/p&gt;
&lt;p dir=ltr&gt;
   Three things to conclude with that:
&lt;/p&gt;
&lt;ol dir=ltr&gt;
   &lt;li&gt;
      &lt;div&gt;You can never use what you experiment as a proof of concept. Experiments and
         tests are always a subset of the big picture.
      &lt;/div&gt;
   &lt;li&gt;
      &lt;div&gt;Don't try to make assumptions larger than the initial statement. Assuming that
         a pointer wouldn't change just because a BSTR* parameter must be freed if changed
         was stretching the actual fact.
      &lt;/div&gt;
   &lt;li&gt;
      &lt;div&gt;Optimizations may sound good, but can always introduce more problems. Simplicity
         is bliss.
      &lt;/div&gt;
   &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   By the way, I realized I could try a very simple VB6 test. If once the old BSTR is
   freed any new BSTR can end-up at the same address, does it mean that a VB6 application
   modifying the sFilename parameter &lt;strong&gt;twice&lt;/strong&gt; can&amp;nbsp;reproduce the same
   bug? Absolutely! My VB6 sample application did this in ZipPreprocessingFile:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   sFilename = sFilename &amp;amp; ".foo"&lt;br&gt;
   sFilename = sFilename &amp;amp; ".bar"
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   Turns out files are &lt;strong&gt;sometimes&lt;/strong&gt; renamed, &lt;strong&gt;sometimes&lt;/strong&gt; not...
   Sometimes, I feel like an...
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d" /&gt;</description>
      <category>COM;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=c9b4cafc-a492-4523-9318-94908ec79546</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,c9b4cafc-a492-4523-9318-94908ec79546.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <strong>
            <font color="#a52a2a">
              <u>Warning</u>: Do not try this at home!</font>
          </strong>
        </p>
        <p>
      A few days ago, Pierre-Luc at support asked me if Xceed Zip for .NET was thread safe.
      I knew from his look that he was expecting a "yes" or a "no". At least, that's what
      the client who asked him the same question expected.
   </p>
        <p>
      My first answer was more in nuances: <em>Though the library was made to be safely
      accessible from multiple threads at the same time, by the nature of the sequential
      format of the zip file, it is not possible to work on the same zip file from multiple
      threads.</em></p>
        <p>
      He nodded with approbation, confirming me his client wasn't trying such crazy action,
      but simply dealing with a multi-threaded application where each thread may be zipping
      in its own private file. I gave him my benediction: <em>In that case, yes, Xceed
      Zip for .NET is thread safe.</em></p>
        <p>
      Pierre-Luc wasn't two feet away when I was illuminated by an idea. It wouldn't be
      that crazy to try zipping into the same zip file from multiple threads. How neat would
      it be to benefit from multi processor or hyperthreading machines for zipping a single
      file? Guess what... you can! You shouldn't... but you can! Don't ask us to support
      this scenario... but you can!
   </p>
        <p>
      Here's the deal. Any ZipArchive you modify gets updated when the <a href="http://blogs.xceedsoft.com/plantem/PermaLink.aspx?guid=a4ea2021-91ce-482d-a54d-b3dd04f18f2d">last
      modify operation occurs</a>. If you know you're about to make more than one modification
      to a single zip file, you should first call BeginUpdate, do all modifications, and
      finally call EndUpdate. The zip file will only get rebuilt on that final call. The
      files you copy into the zip file before EndUpdate will be compressed and stored in
      temp files within the ZipArchive's TempFolder.
   </p>
        <p>
      That means any copy operation you perform within a BeginUpdate/EndUpdate block are
      atomic, and only involve compressing the sources into independant temp files. You
      see where I'm heading? How about spawning threads within that block, each thread copying
      its own source, and waiting for all threads to finish before calling EndUpdate?
   </p>
        <p>
      I had to try it. I started with a class implementing IAsyncResult, which would be
      managing the copy operation on a separate thread:
   </p>
        <font size="2">
          <div class="cf" style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New">
            <p style="MARGIN: 0px">
           <span style="COLOR: #0000ff">internal</span><span style="COLOR: #0000ff">class</span> AsyncCopyResult
         : IAsyncResult
      </p>
            <p style="MARGIN: 0px">
           {
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">public</span> AsyncCopyResult( 
      </p>
            <p style="MARGIN: 0px">
               AbstractFolder source, 
      </p>
            <p style="MARGIN: 0px">
               AbstractFolder dest, 
      </p>
            <p style="MARGIN: 0px">
               AsyncCallback callback, 
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">object</span> state )
      </p>
            <p style="MARGIN: 0px">
             {
      </p>
            <p style="MARGIN: 0px">
               m_source = source;
      </p>
            <p style="MARGIN: 0px">
               m_dest = dest;
      </p>
            <p style="MARGIN: 0px">
               m_callback = callback;
      </p>
            <p style="MARGIN: 0px">
               m_state = state;
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
               m_thread = <span style="COLOR: #0000ff">new</span> Thread( <span style="COLOR: #0000ff">new</span> ThreadStart( <span style="COLOR: #0000ff">this</span>.ThreadProc
         ) );
      </p>
            <p style="MARGIN: 0px">
               m_completed = <span style="COLOR: #0000ff">new</span> ManualResetEvent( <span style="COLOR: #0000ff">false</span> );
      </p>
            <p style="MARGIN: 0px">
             }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">void</span> Begin()
      </p>
            <p style="MARGIN: 0px">
             {
      </p>
            <p style="MARGIN: 0px">
               m_completed.Reset();
      </p>
            <p style="MARGIN: 0px">
               m_thread.Start();
      </p>
            <p style="MARGIN: 0px">
             }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">void</span> End()
      </p>
            <p style="MARGIN: 0px">
             {
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #008000">// We must not join thread since
         we may get called by callback, itself</span></p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #008000">// within thread.</span></p>
            <p style="MARGIN: 0px">
               m_completed.WaitOne();
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">if</span>( m_result != <span style="COLOR: #0000ff">null</span> )
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">throw</span> m_result;
      </p>
            <p style="MARGIN: 0px">
             }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
              <span style="COLOR: #0000ff">    #region</span> IAsyncResult IMPLEMENTATION
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">object</span> AsyncState
      </p>
            <p style="MARGIN: 0px">
             {
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">get</span> { <span style="COLOR: #0000ff">return</span> m_state;
         }
      </p>
            <p style="MARGIN: 0px">
             }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">bool</span> CompletedSynchronously
      </p>
            <p style="MARGIN: 0px">
             {
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">get</span> { <span style="COLOR: #0000ff">return</span><span style="COLOR: #0000ff">false</span>;
         }
      </p>
            <p style="MARGIN: 0px">
             }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">public</span> WaitHandle AsyncWaitHandle
      </p>
            <p style="MARGIN: 0px">
             {
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">get</span> { <span style="COLOR: #0000ff">return</span> m_completed;
         }
      </p>
            <p style="MARGIN: 0px">
             }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">bool</span> IsCompleted
      </p>
            <p style="MARGIN: 0px">
             {
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">get</span> { <span style="COLOR: #0000ff">return</span> m_completed.WaitOne(
         1, <span style="COLOR: #0000ff">false</span> ); }
      </p>
            <p style="MARGIN: 0px">
             }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
              <span style="COLOR: #0000ff">    #endregion</span>
            </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">private</span><span style="COLOR: #0000ff">void</span> ThreadProc()
      </p>
            <p style="MARGIN: 0px">
             {
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">try</span></p>
            <p style="MARGIN: 0px">
               {
      </p>
            <p style="MARGIN: 0px">
                 m_result = <span style="COLOR: #0000ff">null</span>;
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">if</span>( m_source == <span style="COLOR: #0000ff">null</span> )
      </p>
            <p style="MARGIN: 0px">
                   <span style="COLOR: #0000ff">throw</span><span style="COLOR: #0000ff">new</span> ArgumentNullException(
         "source" );
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">if</span>( m_dest == <span style="COLOR: #0000ff">null</span> )
      </p>
            <p style="MARGIN: 0px">
                   <span style="COLOR: #0000ff">throw</span><span style="COLOR: #0000ff">new</span> ArgumentNullException(
         "dest" );
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">if</span>( m_source.IsRoot
         )
      </p>
            <p style="MARGIN: 0px">
                 {
      </p>
            <p style="MARGIN: 0px">
                   m_source.CopyFilesTo( m_dest, <span style="COLOR: #0000ff">true</span>, <span style="COLOR: #0000ff">true</span> );
      </p>
            <p style="MARGIN: 0px">
                 }
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">else</span></p>
            <p style="MARGIN: 0px">
                 {
      </p>
            <p style="MARGIN: 0px">
                   m_source.CopyTo( m_dest, <span style="COLOR: #0000ff">true</span> );
      </p>
            <p style="MARGIN: 0px">
                 }
      </p>
            <p style="MARGIN: 0px">
               }
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">catch</span>( Exception except )
      </p>
            <p style="MARGIN: 0px">
               {
      </p>
            <p style="MARGIN: 0px">
                 m_result = except;
      </p>
            <p style="MARGIN: 0px">
               }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
               m_completed.Set();
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">if</span>( m_callback != <span style="COLOR: #0000ff">null</span> )
      </p>
            <p style="MARGIN: 0px">
               {
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">try</span></p>
            <p style="MARGIN: 0px">
                 {
      </p>
            <p style="MARGIN: 0px">
                   <span style="COLOR: #008000">// Important note:
         This callback may be calling End.</span></p>
            <p style="MARGIN: 0px">
                   <span style="COLOR: #008000">// Thus End's implementation
         should not wait for thread,</span></p>
            <p style="MARGIN: 0px">
                   <span style="COLOR: #008000">// but for handle.</span></p>
            <p style="MARGIN: 0px">
                   m_callback( <span style="COLOR: #0000ff">this</span> );
      </p>
            <p style="MARGIN: 0px">
                 }
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">catch</span></p>
            <p style="MARGIN: 0px">
                 {
      </p>
            <p style="MARGIN: 0px">
                   System.Diagnostics.Debug.WriteLine( "Unhandled
         exception within callback." );
      </p>
            <p style="MARGIN: 0px">
                 }
      </p>
            <p style="MARGIN: 0px">
               }
      </p>
            <p style="MARGIN: 0px">
             }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">private</span> Thread m_thread = <span style="COLOR: #0000ff">null</span>;
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">private</span> ManualResetEvent m_completed
         = <span style="COLOR: #0000ff">null</span>;
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">private</span> AbstractFolder m_source
         = <span style="COLOR: #0000ff">null</span>;
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">private</span> AbstractFolder m_dest = <span style="COLOR: #0000ff">null</span>;
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">private</span> AsyncCallback m_callback
         = <span style="COLOR: #0000ff">null</span>;
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">private</span><span style="COLOR: #0000ff">object</span> m_state
         = <span style="COLOR: #0000ff">null</span>;
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">private</span> Exception m_result = <span style="COLOR: #0000ff">null</span>;
      </p>
            <p style="MARGIN: 0px">
           }
      </p>
          </div>
          <p>
      The ThreadProc method is simply copying the source folder into the destination folder.
      The rest is plumbing for implementing IAsyncResult. In my main class, I created a
      static method that uses the AsyncCopyResult class like this:
   </p>
          <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New">
            <p style="MARGIN: 0px">
             <span style="COLOR: #0000ff">private</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #0000ff">void</span> CopyMultipleFolders( 
      </p>
            <p style="MARGIN: 0px">
               AbstractFolder[] sources, 
      </p>
            <p style="MARGIN: 0px">
               AbstractFolder dest )
      </p>
            <p style="MARGIN: 0px">
             {
      </p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #008000">// I'm using AutoBatchUpdate with
         the using directive, an easy way </span></p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #008000">// to call BeginUpdate and EndUpdate
         only if the folder implements </span></p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #008000">// IBatchUpdateable.</span></p>
            <p style="MARGIN: 0px">
               <span style="COLOR: #0000ff">using</span>( AutoBatchUpdate auto
         = <span style="COLOR: #0000ff">new</span> AutoBatchUpdate( dest ) )
      </p>
            <p style="MARGIN: 0px">
               {
      </p>
            <p style="MARGIN: 0px">
                 AsyncCopyResult[] results = <span style="COLOR: #0000ff">new</span> AsyncCopyResult[
         sources.Length ];
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #008000">// First create the threads
         and state objects.</span></p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">for</span>( <span style="COLOR: #0000ff">int</span> i=0;
         i&lt;sources.Length; i++ )
      </p>
            <p style="MARGIN: 0px">
                 {
      </p>
            <p style="MARGIN: 0px">
                   results[ i ] = <span style="COLOR: #0000ff">new</span> AsyncCopyResult(
         sources[ i ], dest, <span style="COLOR: #0000ff">null</span>, <span style="COLOR: #0000ff">null</span> );
      </p>
            <p style="MARGIN: 0px">
                 }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #008000">// Then launch each thread</span></p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">foreach</span>( AsyncCopyResult
         result <span style="COLOR: #0000ff">in</span> results )
      </p>
            <p style="MARGIN: 0px">
                 {
      </p>
            <p style="MARGIN: 0px">
                   result.Begin();
      </p>
            <p style="MARGIN: 0px">
                 }
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #008000">// We can't call WaitAll
         on an STA thread, but it doesn't matter.</span></p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #008000">// We wait for each one separately.</span></p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">foreach</span>( AsyncCopyResult
         result <span style="COLOR: #0000ff">in</span> results )
      </p>
            <p style="MARGIN: 0px">
                 {
      </p>
            <p style="MARGIN: 0px">
                   result.AsyncWaitHandle.WaitOne();
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                   <span style="COLOR: #0000ff">try</span></p>
            <p style="MARGIN: 0px">
                   {
      </p>
            <p style="MARGIN: 0px">
                     result.End();
      </p>
            <p style="MARGIN: 0px">
                   }
      </p>
            <p style="MARGIN: 0px">
                   <span style="COLOR: #0000ff">catch</span>( Exception
         except )
      </p>
            <p style="MARGIN: 0px">
                   {
      </p>
            <p style="MARGIN: 0px">
                     Console.WriteLine( except.Message );
      </p>
            <p style="MARGIN: 0px">
                   }
      </p>
            <p style="MARGIN: 0px">
                 }
      </p>
            <p style="MARGIN: 0px">
               }
      </p>
            <p style="MARGIN: 0px">
             }
      </p>
          </div>
          <p>
      Once each thread is done copying its own source folder into the destination folder,
      the AutoBatchUpdate class calls EndUpdate on the destination folder (if it implements
      IBatchUpdateable). In the case of a zip file destination, the final zip file is built
      by reassembling already compressed temp files. Here's an example of how to call CopyMultipleFolders:
   </p>
          <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New">
            <p style="MARGIN: 0px">
                 AbstractFile target = <span style="COLOR: #0000ff">new</span> DiskFile(
         @"d:\temp\multi.zip" );
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                 <span style="COLOR: #0000ff">if</span>( target.Exists
         )
      </p>
            <p style="MARGIN: 0px">
                   target.Delete();
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                 ZipArchive zip = <span style="COLOR: #0000ff">new</span> ZipArchive(
         target );
      </p>
            <p style="MARGIN: 0px">
                 AbstractFolder firstSource = <span style="COLOR: #0000ff">new</span> DiskFolder(
         @"d:\Downloads" );
      </p>
            <p style="MARGIN: 0px">
                 AbstractFolder secondSource = <span style="COLOR: #0000ff">new</span> DiskFolder(
         @"d:\Music" );
      </p>
            <p style="MARGIN: 0px">
          
      </p>
            <p style="MARGIN: 0px">
                 CopyMultipleFolders( <span style="COLOR: #0000ff">new</span> AbstractFolder[]
         { firstSource, secondSource }, zip );
      </p>
          </div>
          <p>
      The best thing is that this method works for any kind of AbstractFolder, source or
      destination. If you're confident the size of the zip file isn't too large, you can
      improve performance by setting the ZipArchive's TempFolder to a new MemoryFolder. 
   </p>
          <p>
      But remember: Don't try this! I didn't tell you it was possible.<!--EndFragment--></p>
        </font>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=c9b4cafc-a492-4523-9318-94908ec79546" />
      </body>
      <title>Multi-threaded zipping</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,c9b4cafc-a492-4523-9318-94908ec79546.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,c9b4cafc-a492-4523-9318-94908ec79546.aspx</link>
      <pubDate>Tue, 08 Mar 2005 15:56:48 GMT</pubDate>
      <description>&lt;p&gt;
   &lt;strong&gt;&lt;font color=#a52a2a&gt;&lt;u&gt;Warning&lt;/u&gt;: Do not try this at home!&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
   A few days ago, Pierre-Luc at support asked me if Xceed Zip for .NET was thread safe.
   I knew from his look that he was expecting a "yes" or a "no". At least, that's what
   the client who asked him the same question expected.
&lt;/p&gt;
&lt;p&gt;
   My first answer was more in nuances: &lt;em&gt;Though the library was made to be safely
   accessible from multiple threads at the same time, by the nature of the sequential
   format of the zip file, it is not possible to work on the same zip file from multiple
   threads.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
   He nodded with approbation, confirming me his client wasn't trying such crazy action,
   but simply dealing with a multi-threaded application where each thread may be&amp;nbsp;zipping
   in its own private&amp;nbsp;file. I gave him my benediction: &lt;em&gt;In that case, yes, Xceed
   Zip for .NET is thread safe.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
   Pierre-Luc wasn't two feet away when I was illuminated by an idea. It wouldn't be
   that crazy to try zipping into the same zip file from multiple threads. How neat would
   it be to benefit from multi processor or hyperthreading machines for zipping a single
   file? Guess what... you can! You shouldn't... but you can! Don't ask us to support
   this scenario... but you can!
&lt;/p&gt;
&lt;p&gt;
   Here's the deal. Any ZipArchive you modify gets updated when the &lt;a href="http://blogs.xceedsoft.com/plantem/PermaLink.aspx?guid=a4ea2021-91ce-482d-a54d-b3dd04f18f2d"&gt;last
   modify operation occurs&lt;/a&gt;. If you know you're about to make more than one modification
   to a single zip file, you should first call BeginUpdate, do all modifications, and
   finally call EndUpdate. The zip file will only get rebuilt on that final call. The
   files you copy into the zip file before EndUpdate will be compressed and stored in
   temp files within the ZipArchive's TempFolder.
&lt;/p&gt;
&lt;p&gt;
   That means any copy operation you perform within a BeginUpdate/EndUpdate block are
   atomic, and only involve compressing the sources into independant temp files. You
   see where I'm heading? How about spawning threads within that block, each thread copying
   its own source, and waiting for all threads to finish before calling EndUpdate?
&lt;/p&gt;
&lt;p&gt;
   I had to try it. I started with a class implementing IAsyncResult, which would be
   managing the copy operation on a separate thread:
&lt;/p&gt;
&lt;font size=2&gt; 
&lt;div class=cf style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New"&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;class&lt;/span&gt; AsyncCopyResult
      : IAsyncResult
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; AsyncCopyResult( 
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; AbstractFolder source, 
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; AbstractFolder dest, 
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; AsyncCallback callback, 
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; state )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_source = source;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_dest = dest;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_callback = callback;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_state = state;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_thread = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; Thread( &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ThreadStart( &lt;span style="COLOR: #0000ff"&gt;this&lt;/span&gt;.ThreadProc
      ) );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_completed = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ManualResetEvent( &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt; );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; Begin()
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_completed.Reset();
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_thread.Start();
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; End()
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// We must not join thread since
      we may get called by callback, itself&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// within thread.&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_completed.WaitOne();
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( m_result != &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;throw&lt;/span&gt; m_result;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &lt;span style="COLOR: #0000ff"&gt;&amp;nbsp; &amp;nbsp; #region&lt;/span&gt; IAsyncResult IMPLEMENTATION
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; AsyncState
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; m_state;
      }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;bool&lt;/span&gt; CompletedSynchronously
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;;
      }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; WaitHandle AsyncWaitHandle
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; m_completed;
      }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;bool&lt;/span&gt; IsCompleted
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; m_completed.WaitOne(
      1, &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt; ); }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &lt;span style="COLOR: #0000ff"&gt;&amp;nbsp; &amp;nbsp; #endregion&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; ThreadProc()
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; m_result = &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( m_source == &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ArgumentNullException(
      "source" );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( m_dest == &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ArgumentNullException(
      "dest" );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( m_source.IsRoot
      )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; m_source.CopyFilesTo( m_dest, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt; );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;else&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; m_source.CopyTo( m_dest, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt; );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;catch&lt;/span&gt;( Exception except )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; m_result = except;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; m_completed.Set();
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( m_callback != &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Important note:
      This callback may be calling End.&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Thus End's implementation
      should not wait for thread,&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// but for handle.&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; m_callback( &lt;span style="COLOR: #0000ff"&gt;this&lt;/span&gt; );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;catch&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; System.Diagnostics.Debug.WriteLine( "Unhandled
      exception within callback." );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; Thread m_thread = &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; ManualResetEvent m_completed
      = &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; AbstractFolder m_source
      = &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; AbstractFolder m_dest = &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; AsyncCallback m_callback
      = &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; m_state
      = &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; Exception m_result = &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; }
   &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
   The ThreadProc method is simply copying the source folder into the destination folder.
   The rest is plumbing for implementing IAsyncResult. In my main class, I created a
   static method that uses the AsyncCopyResult class like this:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New"&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; CopyMultipleFolders( 
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; AbstractFolder[] sources, 
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; AbstractFolder dest )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// I'm using AutoBatchUpdate with
      the using directive, an easy way &lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// to call BeginUpdate and EndUpdate
      only if the folder implements &lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// IBatchUpdateable.&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;( AutoBatchUpdate auto
      = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; AutoBatchUpdate( dest ) )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AsyncCopyResult[] results = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; AsyncCopyResult[
      sources.Length ];
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// First create the threads
      and state objects.&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;for&lt;/span&gt;( &lt;span style="COLOR: #0000ff"&gt;int&lt;/span&gt; i=0;
      i&amp;lt;sources.Length; i++ )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; results[ i ] = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; AsyncCopyResult(
      sources[ i ], dest, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Then launch each thread&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;foreach&lt;/span&gt;( AsyncCopyResult
      result &lt;span style="COLOR: #0000ff"&gt;in&lt;/span&gt; results )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; result.Begin();
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// We can't call WaitAll
      on an STA thread, but it doesn't matter.&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// We wait for each one separately.&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;foreach&lt;/span&gt;( AsyncCopyResult
      result &lt;span style="COLOR: #0000ff"&gt;in&lt;/span&gt; results )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; result.AsyncWaitHandle.WaitOne();
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; result.End();
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;catch&lt;/span&gt;( Exception
      except )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Console.WriteLine( except.Message );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; }
   &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
   Once each thread is done copying its own source folder into the destination folder,
   the AutoBatchUpdate class calls EndUpdate on the destination folder (if it implements
   IBatchUpdateable). In the case of a zip file destination, the final zip file is built
   by reassembling already compressed temp files. Here's an example of how to call CopyMultipleFolders:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New"&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AbstractFile target = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFile(
      @"d:\temp\multi.zip" );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( target.Exists
      )
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; target.Delete();
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ZipArchive zip = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive(
      target );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AbstractFolder firstSource = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
      @"d:\Downloads" );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AbstractFolder secondSource = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
      @"d:\Music" );
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp;
   &lt;/p&gt;
   &lt;p style="MARGIN: 0px"&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; CopyMultipleFolders( &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; AbstractFolder[]
      { firstSource, secondSource }, zip );
   &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
   The best thing is that this method works for any kind of AbstractFolder, source or
   destination. If you're confident the size of the zip file isn't too large, you can
   improve performance by setting the ZipArchive's TempFolder to a new MemoryFolder. 
&lt;/p&gt;
&lt;p&gt;
   But remember: Don't try this! I didn't tell you it was possible.&lt;!--EndFragment--&gt;
&lt;/font&gt;&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=c9b4cafc-a492-4523-9318-94908ec79546" /&gt;</description>
      <category>FileSystem;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=6b797461-1616-4147-929d-eb41bfc96405</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,6b797461-1616-4147-929d-eb41bfc96405.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I had to take a look at an issue with a spanned zip file. The client graciously sent
      us the set of zip files he had on floppies. He copied each floppy in subfolders named
      "Disk1", "Disk2", "Disk3" and "Disk4", zipped those folders and sent us the resulting
      single huge zip file. Pretty standard.
   </p>
        <p>
      I was about to copy each part back on floppies when I realized I was passing by a
      huge feature Xceed Zip for .NET offers regarding spanning and splitting: the ability
      to specify any AbstractFile, wherever it's located, when a new "disk" is required.
   </p>
        <p>
      Before I show you how I skipped the unpleasant task of copying each part on separate
      floppies, let's first take a look at how you can support traditional spanning using
      Xceed Zip for .NET. The code below is what I call a minimum spanning implementation:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 9pt; BACKGROUND: #f7f7f1; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New">
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">private</span>
            <span style="COLOR: #0000ff">static</span>
            <span style="COLOR: #0000ff">void</span> Zip(
      AbstractFile zipFile, AbstractFolder sourceFolder )</pre>
          <pre style="MARGIN: 0px">{</pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #008000">// Prepare ZipEvents
      object that will be passed to every method call.</span></pre>
          <pre style="MARGIN: 0px">  ZipEvents events = <span style="COLOR: #0000ff">new</span> ZipEvents();</pre>
          <pre style="MARGIN: 0px">  events.DiskRequired += <span style="COLOR: #0000ff">new</span> DiskRequiredEventHandler(
      ZipEvents_DiskRequired );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #008000">// Create the target
      ZipArchive, and prepare for batch modifications.</span></pre>
          <pre style="MARGIN: 0px">  ZipArchive zip = <span style="COLOR: #0000ff">new</span> ZipArchive(
      events, <span style="COLOR: #0000ff">null</span>, zipFile );</pre>
          <pre style="MARGIN: 0px">  zip.BeginUpdate( events, <span style="COLOR: #0000ff">null</span> );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">try</span></pre>
          <pre style="MARGIN: 0px">  {</pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #008000">// Allow this
      zip file to span.</span></pre>
          <pre style="MARGIN: 0px">    zip.AllowSpanning = <span style="COLOR: #0000ff">true</span>;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #008000">// Zip this folder's
      contents</span></pre>
          <pre style="MARGIN: 0px">    sourceFolder.CopyFilesTo( events, <span style="COLOR: #0000ff">null</span>,
      zip, <span style="COLOR: #0000ff">true</span>, <span style="COLOR: #0000ff">true</span> );</pre>
          <pre style="MARGIN: 0px">  }</pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">finally</span></pre>
          <pre style="MARGIN: 0px">  {</pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #008000">// Complete the
      batch modification of this zip file.</span></pre>
          <pre style="MARGIN: 0px">    zip.EndUpdate( events, <span style="COLOR: #0000ff">null</span> );</pre>
          <pre style="MARGIN: 0px">    events.DiskRequired -= <span style="COLOR: #0000ff">new</span> DiskRequiredEventHandler(
      ZipEvents_DiskRequired );</pre>
          <pre style="MARGIN: 0px">  }</pre>
          <pre style="MARGIN: 0px">}</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">private</span>
            <span style="COLOR: #0000ff">static</span>
            <span style="COLOR: #0000ff">void</span> Unzip(
      AbstractFile zipFile, AbstractFolder destFolder )</pre>
          <pre style="MARGIN: 0px">{</pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #008000">// Prepare ZipEvents
      object that will be passed to every method call.</span></pre>
          <pre style="MARGIN: 0px">  ZipEvents events = <span style="COLOR: #0000ff">new</span> ZipEvents();</pre>
          <pre style="MARGIN: 0px">  events.DiskRequired += <span style="COLOR: #0000ff">new</span> DiskRequiredEventHandler(
      ZipEvents_DiskRequired );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #008000">// Create the source
      ZipArchive.</span></pre>
          <pre style="MARGIN: 0px">  ZipArchive zip = <span style="COLOR: #0000ff">new</span> ZipArchive(
      events, <span style="COLOR: #0000ff">null</span>, zipFile );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">try</span></pre>
          <pre style="MARGIN: 0px">  {</pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #008000">// Unzip to destination
      folder.</span></pre>
          <pre style="MARGIN: 0px">    zip.CopyFilesTo( events, <span style="COLOR: #0000ff">null</span>,
      destFolder, <span style="COLOR: #0000ff">true</span>, <span style="COLOR: #0000ff">true</span> );</pre>
          <pre style="MARGIN: 0px">  }</pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">finally</span></pre>
          <pre style="MARGIN: 0px">  {</pre>
          <pre style="MARGIN: 0px">    events.DiskRequired -= <span style="COLOR: #0000ff">new</span> DiskRequiredEventHandler(
      ZipEvents_DiskRequired );</pre>
          <pre style="MARGIN: 0px">  }</pre>
          <pre style="MARGIN: 0px">}</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">private</span>
            <span style="COLOR: #0000ff">static</span>
            <span style="COLOR: #0000ff">void</span> ZipEvents_DiskRequired(<span style="COLOR: #0000ff">object</span> sender,
      DiskRequiredEventArgs e)</pre>
          <pre style="MARGIN: 0px">{</pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #008000">// Let the user know
      we need that disk and wait for feedback.</span></pre>
          <pre style="MARGIN: 0px">  Console.WriteLine( "Please insert disk #{0}, then press 
      <ENTER>
         .", 
         <br />
             e.DiskNumber.ToString() );
      </ENTER></pre>
          <pre style="MARGIN: 0px">  Console.ReadLine();</pre>
          <pre style="MARGIN: 0px">  e.Action = DiskRequiredAction.Continue;</pre>
          <pre style="MARGIN: 0px">}</pre>
        </div>
        <!--EndFragment-->
        <!--EndFragment-->
        <p>
      It's pretty straightforward. You simply give the user the time to insert the required
      disk. Don't forget that when unzipping, you must make sure the last zip file is the
      one available before creating your ZipArchive around it. There is no "insert last
      disk" event with Xceed Zip for .NET.
   </p>
        <p>
      Now, back to my task. If you take a look at the DiskRequiredEventArgs parameter of
      the DiskRequired event, you see it exposes a "ZipFile" property of type AbstractFile.
      That's the AbstractFile for the part it's trying to locate. The above implementation
      requires a pause, to give time to the user to insert the correct disk. But what if
      the correct zip part is already available somewhere else? How about this implementation:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 9pt; BACKGROUND: #f7f7f1; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New">
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">private</span>
            <span style="COLOR: #0000ff">static</span>
            <span style="COLOR: #0000ff">void</span> ZipEvents_DiskRequired(<span style="COLOR: #0000ff">object</span> sender,
      DiskRequiredEventArgs e)</pre>
          <pre style="MARGIN: 0px">{</pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #008000">// Let's check if the
      current zip file is located in a "DiskN" subfolder</span></pre>
          <pre style="MARGIN: 0px">  AbstractFolder subfolder = e.ZipFile.ParentFolder;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">if</span>(  ( !subfolder.IsRoot
      )</pre>
          <pre style="MARGIN: 0px">    &amp;&amp; ( subfolder.Name.ToUpper().StartsWith( "DISK" ) ) )</pre>
          <pre style="MARGIN: 0px">  {</pre>
          <pre style="MARGIN: 0px">    subfolder = subfolder.ParentFolder.GetFolder( 
      <br />
            "Disk" + e.DiskNumber.ToString() );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">if</span>( subfolder.Exists
      )</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      AbstractFile newZipFile = subfolder.GetFile( e.ZipFile.Name );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">if</span>(
      newZipFile.Exists )</pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #008000">//
      No need to ask the user for the correct zip part, we found it!</span></pre>
          <pre style="MARGIN: 0px">        e.ZipFile = newZipFile;</pre>
          <pre style="MARGIN: 0px">        e.Action = DiskRequiredAction.Continue;</pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px">    }</pre>
          <pre style="MARGIN: 0px">  }</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">if</span>( e.Action !=
      DiskRequiredAction.Continue )</pre>
          <pre style="MARGIN: 0px">  {</pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #008000">// Let the user
      know we need that disk and wait for feedback.</span></pre>
          <pre style="MARGIN: 0px">    Console.WriteLine( "Please insert disk #{0}, then press 
      <ENTER>
         .", 
         <br />
               e.DiskNumber.ToString() );
      </ENTER></pre>
          <pre style="MARGIN: 0px">    Console.ReadLine();</pre>
          <pre style="MARGIN: 0px">    e.Action = DiskRequiredAction.Continue;</pre>
          <pre style="MARGIN: 0px">  }</pre>
          <pre style="MARGIN: 0px">}</pre>
        </div>
        <!--EndFragment-->
        <p>
      As you can see, I have full control on what AbstractFile I provide to the library
      as the N<sup>th</sup> zip file part. Since I have unzipped my client's zip file parts
      in my "D:\temp" folder, I can now call my Unzip method like this:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 9pt; BACKGROUND: #f7f7f1; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New">
          <pre style="MARGIN: 0px">Unzip( </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">new</span> DiskFile(
      @"d:\temp\Disk4\test.zip" ), </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"d:\temp\Unzipped" ) );</pre>
        </div>
        <!--EndFragment-->
        <p>
      Then, the obvious striked me! Why did I unzip his "Floppies.zip" zip file in my "D:\temp"
      folder??? It's even simpler than I thought:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 9pt; BACKGROUND: #f7f7f1; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New">
          <pre style="MARGIN: 0px">Unzip( </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">new</span> ZippedFile( <span style="COLOR: #0000ff">new</span> DiskFile(
      @"d:\temp\floppies.zip" ), @"\Disk4\test.zip" ), </pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"d:\temp\Unzipped" ) );</pre>
        </div>
        <!--EndFragment-->
        <p>
      I'm unzipping zip file parts stored in a single zip file, without the need to have
      those parts really on floppies or even on disk. Wow! Files are files, folders are
      folders, no matter where they reside. Are you starting to get the idea behind the
      FileSystem? :-)
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=6b797461-1616-4147-929d-eb41bfc96405" />
      </body>
      <title>The DiskRequired event - Much more than mere spanning</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,6b797461-1616-4147-929d-eb41bfc96405.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,6b797461-1616-4147-929d-eb41bfc96405.aspx</link>
      <pubDate>Wed, 23 Feb 2005 22:12:59 GMT</pubDate>
      <description>&lt;p&gt;
   I had to take a look at an issue with a spanned zip file. The client graciously sent
   us the set of zip files he had on floppies. He copied each floppy in subfolders named
   "Disk1", "Disk2", "Disk3" and "Disk4", zipped those folders and sent us the resulting
   single huge zip file. Pretty standard.
&lt;/p&gt;
&lt;p&gt;
   I was about to copy each part back on floppies when I realized I was passing by a
   huge feature Xceed Zip for .NET offers regarding spanning and splitting: the ability
   to specify any AbstractFile, wherever it's located, when a new "disk" is required.
&lt;/p&gt;
&lt;p&gt;
   Before I show you how I skipped the unpleasant task of copying each part on separate
   floppies, let's first take a look at how you can support traditional spanning using
   Xceed Zip for .NET. The code below is what I call a minimum spanning implementation:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 9pt; BACKGROUND: #f7f7f1; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New"&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; Zip(
   AbstractFile zipFile, AbstractFolder sourceFolder )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Prepare ZipEvents
   object that will be passed to every method call.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; ZipEvents events = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipEvents();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; events.DiskRequired += &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskRequiredEventHandler(
   ZipEvents_DiskRequired );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Create the target
   ZipArchive, and prepare for batch modifications.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; ZipArchive zip = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive(
   events, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;, zipFile );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; zip.BeginUpdate( events, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Allow this
   zip file to span.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; zip.AllowSpanning = &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Zip this folder's
   contents&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; sourceFolder.CopyFilesTo( events, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;,
   zip, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt; );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;finally&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Complete the
   batch modification of this zip file.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; zip.EndUpdate( events, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; events.DiskRequired -= &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskRequiredEventHandler(
   ZipEvents_DiskRequired );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;}&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; Unzip(
   AbstractFile zipFile, AbstractFolder destFolder )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Prepare ZipEvents
   object that will be passed to every method call.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; ZipEvents events = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipEvents();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; events.DiskRequired += &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskRequiredEventHandler(
   ZipEvents_DiskRequired );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Create the source
   ZipArchive.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; ZipArchive zip = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive(
   events, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;, zipFile );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Unzip to destination
   folder.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; zip.CopyFilesTo( events, &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;,
   destFolder, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt; );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;finally&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; events.DiskRequired -= &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskRequiredEventHandler(
   ZipEvents_DiskRequired );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;}&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; ZipEvents_DiskRequired(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; sender,
   DiskRequiredEventArgs e)&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Let the user know
   we need that disk and wait for feedback.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; Console.WriteLine( "Please insert disk #{0}, then press 
   &lt;ENTER&gt;
      .", 
      &lt;br&gt;
      &amp;nbsp; &amp;nbsp; e.DiskNumber.ToString() );
   &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; Console.ReadLine();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; e.Action = DiskRequiredAction.Continue;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   It's pretty straightforward. You simply give the user the time to insert the required
   disk. Don't forget that when unzipping, you must make sure the last zip file is the
   one available before creating your ZipArchive around it. There is no "insert last
   disk" event with Xceed Zip for .NET.
&lt;/p&gt;
&lt;p&gt;
   Now, back to my task. If you take a look at the DiskRequiredEventArgs parameter of
   the DiskRequired event, you see it exposes a "ZipFile" property of type AbstractFile.
   That's the AbstractFile for the part it's trying to locate. The above implementation
   requires a pause, to give time to the user to insert the correct disk. But what if
   the correct zip part is already available somewhere else? How about this implementation:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 9pt; BACKGROUND: #f7f7f1; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New"&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; ZipEvents_DiskRequired(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; sender,
   DiskRequiredEventArgs e)&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Let's check if the
   current zip file is located in a "DiskN" subfolder&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; AbstractFolder subfolder = e.ZipFile.ParentFolder;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(&amp;nbsp; ( !subfolder.IsRoot
   )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;amp;&amp;amp; ( subfolder.Name.ToUpper().StartsWith( "DISK" ) ) )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; subfolder = subfolder.ParentFolder.GetFolder( 
   &lt;br&gt;
   &amp;nbsp; &amp;nbsp; &amp;nbsp; "Disk" + e.DiskNumber.ToString() );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( subfolder.Exists
   )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; AbstractFile newZipFile = subfolder.GetFile( e.ZipFile.Name );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(
   newZipFile.Exists )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;//
   No need to ask the user for the correct zip part, we found it!&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; e.ZipFile = newZipFile;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; e.Action = DiskRequiredAction.Continue;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( e.Action !=
   DiskRequiredAction.Continue )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #008000"&gt;// Let the user
   know we need that disk and wait for feedback.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; Console.WriteLine( "Please insert disk #{0}, then press 
   &lt;ENTER&gt;
      .", 
      &lt;br&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; e.DiskNumber.ToString() );
   &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; Console.ReadLine();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; e.Action = DiskRequiredAction.Continue;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   As you can see, I have full control on what AbstractFile I provide to the library
   as the N&lt;sup&gt;th&lt;/sup&gt; zip file part. Since I have unzipped my client's zip file parts
   in my "D:\temp" folder, I can now call my Unzip method like this:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 9pt; BACKGROUND: #f7f7f1; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New"&gt;&lt;pre style="MARGIN: 0px"&gt;Unzip( &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFile(
   @"d:\temp\Disk4\test.zip" ), &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"d:\temp\Unzipped" ) );&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   Then, the obvious striked me! Why did I unzip his "Floppies.zip" zip file in my "D:\temp"
   folder??? It's even simpler than I thought:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 9pt; BACKGROUND: #f7f7f1; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Courier New"&gt;&lt;pre style="MARGIN: 0px"&gt;Unzip( &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZippedFile( &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFile(
   @"d:\temp\floppies.zip" ), @"\Disk4\test.zip" ), &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"d:\temp\Unzipped" ) );&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   I'm unzipping zip file parts stored in a single zip file, without the need to have
   those parts really on floppies or even on disk. Wow! Files are files, folders are
   folders, no matter where they reside. Are you starting to get the idea behind the
   FileSystem? :-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=6b797461-1616-4147-929d-eb41bfc96405" /&gt;</description>
      <category>FileSystem;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=364108a3-9abd-48b8-ab8a-60596cae14f0</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,364108a3-9abd-48b8-ab8a-60596cae14f0.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      A <a href="http://www.mono-project.com/news/index.html2-2f17-2f2005-202-3a00-3a00-20PM">new
      Mono release</a> today! As usual, I uninstall the previous release, install the new
      one, and test a few Xceed Zip for .NET console samples. Works perfectly!
   </p>
        <p>
      But today I decided to try my <a href="http://blogs.xceedsoft.com/plantem/PermaLink.aspx?guid=f5dfed4f-92c5-4f60-b301-b3483c6cabec">Xceed
      FileSystem-based <!--StartFragment -->Command Prompt</a> under Mono. Wow! Everything
      works almost perfectly. Zip, Ftp, Ram drive. Only a glitch with the Isolated Storage.
      This sample uses <a href="http://www.mentalis.org/soft/class.qpx?id=2">Mentalis.org's
      ConsoleAttributes library</a> to customize the look and feel of the console.
      It works perfectly well with Mono (on Windows).
   </p>
        <p>
      Any Mono users out there using Xceed products?
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=364108a3-9abd-48b8-ab8a-60596cae14f0" />
      </body>
      <title>Mono 1.1.4 and Xceed Zip for .NET</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,364108a3-9abd-48b8-ab8a-60596cae14f0.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,364108a3-9abd-48b8-ab8a-60596cae14f0.aspx</link>
      <pubDate>Fri, 18 Feb 2005 15:33:14 GMT</pubDate>
      <description>&lt;p&gt;
   A &lt;a href="http://www.mono-project.com/news/index.html2-2f17-2f2005-202-3a00-3a00-20PM"&gt;new
   Mono release&lt;/a&gt; today! As usual, I uninstall the previous release, install the new
   one, and test a few Xceed Zip for .NET console samples. Works perfectly!
&lt;/p&gt;
&lt;p&gt;
   But today I decided to try my &lt;a href="http://blogs.xceedsoft.com/plantem/PermaLink.aspx?guid=f5dfed4f-92c5-4f60-b301-b3483c6cabec"&gt;Xceed
   FileSystem-based&amp;nbsp;&lt;!--StartFragment --&gt;Command Prompt&lt;/a&gt; under Mono. Wow! Everything
   works almost perfectly. Zip, Ftp, Ram drive. Only a glitch with the Isolated Storage.
   This sample uses &lt;a href="http://www.mentalis.org/soft/class.qpx?id=2"&gt;Mentalis.org's
   ConsoleAttributes library&lt;/a&gt;&amp;nbsp;to customize the look and feel of the console.
   It works perfectly well with Mono (on Windows).
&lt;/p&gt;
&lt;p&gt;
   Any Mono users out there using Xceed products?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=364108a3-9abd-48b8-ab8a-60596cae14f0" /&gt;</description>
      <category>FileSystem;FTP;Zip;Mono</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=f5dfed4f-92c5-4f60-b301-b3483c6cabec</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,f5dfed4f-92c5-4f60-b301-b3483c6cabec.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I've been working part time (translation: I should be working on something else) on
      a new sample: my own Command Prompt. I know, I'm reinventing the wheel, not to count
      that Microsoft will launch a new one called msh (codename Monad). But it was more
      a concept or proof around exposing AbstractFolder and AbstractFile within a command
      prompt.
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p>
            <font face="Courier New" color="#000000">  Directory of E:\</font>
          </p>
          <p>
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      27/12/2004  4:23 PM         [FOLDER]
      Backup<br />
      03/11/2004 10:33 AM         [FOLDER] Chart30<br />
      24/11/2004 10:09 AM         [FOLDER] CLR Profiler<br />
      11/01/2005  5:24 PM         [FOLDER]
      Config.Msi<br />
      24/11/2004 10:10 AM         [FOLDER] My Music<br />
      12/01/2005  4:13 PM         [FOLDER]
      My Pictures<br />
      10/09/2004  1:52 PM         [FOLDER]
      RECYCLER<br />
      30/09/2004  8:40 PM         [FOLDER]
      System Volume Information<br />
      02/02/2005  2:49 PM         [FOLDER]
      temp<br />
      03/11/2004 10:33 AM         [FOLDER] XceedProjectsNET<br />
      25/01/2005  7:06 AM             
      143 toto.txt</font>
          </p>
          <p>
            <font face="Courier New" color="#000000">  Files: 1  Folders: 14  Total
      file size: 143</font>
          </p>
          <p>
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\&gt;</font>
              <strong>copy
      toto.txt temp</strong>
              <br />
       100%<br /><font color="#006400">E:\&gt;</font><strong>cd temp</strong><br /><font color="#006400">E:\temp\&gt;</font></font>
          </p>
        </blockquote>
        <p>
      As you can see, I can list the contents of folders, copy files, and change the working
      folder. The application simply manages a working "AbstractFolder", and enables commands
      to act on that folder (or an AbstractFolder obtained from an absolute path).
   </p>
        <p>
      The sample quicky evolved into a prototype for upcoming features. Among other things,
      I needed a way to recognize a path like "E:\temp\test.zip\images" as a ZippedFolder
      within a zip file. Let's stop the talking, and show some traces:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\&gt;</font>
              <strong>md
      test.zip<br /></strong>
              <font color="#006400">E:\temp\&gt;</font>
              <strong>md test.zip\images<br /></strong>
              <font color="#006400">E:\temp\&gt;</font>
              <strong>copy "..\My Pictures\Chalet\*"
      test.zip\images<br /></strong> 100%<br /><font color="#006400">E:\temp\&gt;</font></font>
          </p>
        </blockquote>
        <p dir="ltr">
      What have I done here? Create a folder named "test.zip"? Well, the "md" command recognized
      the ".zip" extension as a request to create a new empty zip file. The second "md"
      command actually created a new folder within the zip file. And the paths can freely
      use the zip filename as a folder part for any command, as shown with the copy example.
      If we display the contents of "E:\temp", we see the two expected files:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of E:\temp\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      02/02/2005  3:00 PM         40068736
      test.zip<br />
      25/01/2005  7:06 AM             
      143 toto.txt</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 2  Folders: 0  Total
      file size: 40068879</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#006400">E:\temp\&gt;</font>
          </p>
        </blockquote>
        <p dir="ltr">
      As you can see, "test.zip" is really a file (DiskFile) within "E:\temp" (DiskFolder).
      What happens if I try changing the current folder into that zip file?
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\&gt;</font>
              <strong>cd
      test.zip</strong>
              <br />
              <font color="#006400">E:\temp\test.zip\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of E:\temp\test.zip\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      02/02/2005  3:00 PM         [FOLDER]
      images</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 0  Folders: 1  Total
      file size: 0</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\test.zip\&gt;</font>
              <strong>cd
      images<br /></strong>
              <font color="#006400">E:\temp\test.zip\images\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of E:\temp\test.zip\images\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      06/08/2000  4:40 PM          6400006
      Chaises.bmp<br />
      06/08/2000  4:35 PM          6348550
      Chute.bmp<br />
      06/08/2000  4:29 PM          6337678
      Ciel1.bmp<br />
      06/08/2000  4:30 PM          6396226
      Ciel2.bmp<br />
      06/08/2000  4:33 PM          6414418
      Ciel3.bmp<br />
      06/08/2000  4:38 PM          6524278
      Couple.bmp<br />
      06/08/2000  4:37 PM          6388054
      Martine.bmp<br />
      06/08/2000  4:32 PM          6405478
      Ombre.bmp<br />
      06/08/2000  4:41 PM          6359254
      Rochers.bmp</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 9  Folders: 0  Total
      file size: 57573942</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#006400">E:\temp\test.zip\images\&gt;</font>
          </p>
        </blockquote>
        <p dir="ltr" style="MARGIN-RIGHT: 0px">
      The zip file is exposed as a folder, because the path "E:\temp\test.zip" was recognized
      and mapped to a ZippedFolder around a DiskFile. And "images" is nothing more than
      a subfolder within that root ZippedFolder, actually something like:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New">new ZippedFolder( new DiskFile( @"E:\temp\test.zip" ), @"\images"
      );</font>
          </p>
        </blockquote>
        <p dir="ltr" style="MARGIN-RIGHT: 0px">
      Ok, let's get into serious things:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\test.zip\images\&gt;</font>
              <strong>cd
      ..\..<br /></strong>
              <font color="#006400">E:\temp\&gt;</font>
              <strong>copy *.zip RAM:\<br /></strong> 100%<br /><font color="#006400">E:\temp\&gt;</font><strong>cd RAM:\test.zip\images<br /></strong><font color="#006400">RAM:\test.zip\images\&gt;</font><strong>dir m*.bmp</strong></font>
          </p>
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#000000">  Directory of RAM:\test.zip\images\</font>
          </p>
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      06/08/2000  4:37 PM          6388054
      Martine.bmp</font>
          </p>
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#000000">  Files: 1  Folders: 0  Total
      file size: 6388054</font>
          </p>
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#006400">RAM:\test.zip\images\&gt;</font>
          </p>
        </blockquote>
        <p dir="ltr">
      My Command Prompt exposes a root MemoryFolder called "RAM:\", which I can freely use.
      The commands act the same, no matter if I'm deeling with a ZippedFolder around a DiskFile
      or a MemoryFile. Want more?
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">RAM:\test.zip\images\&gt;</font>
              <strong>cd </strong>
            </font>
            <strong>
              <font face="Courier New">ftp://vermouth</font>
              <br />
            </strong>
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of </font>
            <font face="Courier New" color="#000000">ftp://vermouth\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 0  Folders: 0  Total
      file size: 0</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>md</strong>
            </font>
            <font face="Courier New" color="#000000">
              <strong> foobar.zip<br /></strong>
            </font>
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>copy</strong>
            </font>
            <font face="Courier New" color="#000000">
              <strong> "E:\My
      Music\WMA\Mes Aieux" foobar.zip<br /></strong> 100%<br /></font>
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of </font>
            <font face="Courier New" color="#000000">ftp://vermouth\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      02/02/2005  3:20 PM         62936759
      foobar.zip</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 1  Folders: 0  Total
      file size: 62936759</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>dir</strong>
            </font>
            <font face="Courier New" color="#000000">
              <strong> c:\inetpub\ftproot</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of c:\inetpub\ftproot\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      02/02/2005  3:20 PM         62936759
      foobar.zip</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 1  Folders: 0  Total
      file size: 62936759</font>
          </p>
          <p dir="ltr">
            <font color="#006400">
              <font face="Courier New">ftp://vermouth\</font>
              <font face="Courier New">&gt;</font>
            </font>
          </p>
        </blockquote>
        <p dir="ltr">
      FTP servers are threated as any other kind of AbstractFolder. The application simply
      recognize the "FTP:" prefix as a signature for a root FtpFolder, as it did with
      "RAM:" exposed as a MemoryFolder. The command implementations don't care what kind
      of AbstractFolder or AbstractFile they are dealing with.
   </p>
        <p dir="ltr">
      The engine behind this involves FileSystemMapper-derived classes. They mainly
      get asked two kinds of questions:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <strong>Question 1</strong>: Do you recognize this path as a root?
   </p>
          <p>
      If so, they remove the part of the path they could recognize as a root folder, and
      return the matching AbstractFolder.
   </p>
          <p>
      Examples of mappers and their responsability:
   </p>
          <ul>
            <li>
              <div>
                <strong>DiskMapper</strong> : Drive letters and UNC paths (yes, you can "cd"
            into a UNC path!)
         </div>
            </li>
            <li>
              <div>
                <strong>FtpMapper</strong> : The "FTP:" prefix with server name, and optional
            username and password (e.g. ftp://user:pass@vermouth:9999)
         </div>
            </li>
            <li>
              <div>
                <strong>IsolatedStorageMapper</strong> : A custom prefix name like "STORE:" (that's
            the one my sample app supports).
         </div>
            </li>
            <li>
              <div>
                <strong>MemoryMapper</strong> : A custom prefix used to create the initial root
            MemoryFolder, like "RAM:" (that's the one my app supports). You can create more than
            one MemoryMapper to have more than one ram drive.
         </div>
            </li>
          </ul>
          <p>
            <strong>Question 2</strong>: Can you represent this AbstractFile as an AbstractFolder?
   </p>
          <p>
      If so, they simply return the matching AbstractFolder.
   </p>
          <p>
      An example of such a mapper:
   </p>
          <ul>
            <li>
              <div>
                <strong>ZipFileMapper</strong> : It simply checks if the provided AbstractFile
            exists, then tries to create a ZipArchive around that AbstractFile in a try/catch.
            If it succeeds, it returns this ZipArchive (which derives from ZippedFolder).
         </div>
            </li>
          </ul>
          <p>
      Curiously, today I came across <a href="http://www.xceedsoft.com/Forums/ShowPost.aspx?PostID=2326">a
      post on our forums</a> asking how to detect if a file is really a zip file. I gave
      this man the "new ZipArchive within a try/catch" solution, and he came back, as I
      feared, with concerns with the time wasted catching an exception for all those non-zip
      files. It's actually one of the bottlenecks of my Command Prompt sample. A lot of
      time is wasted throwing an exception for all non-zip files my app comes across. Well,
      I guess I'll have to work sooner than later on a new "ZipArchive.IsZipFile" method!
      :-)
   </p>
        </blockquote>
        <p dir="ltr">
      Now, you have to convince my boss I should put more time on this sample and these
      new FileSystem features! Does mapping absolute paths like shown above to their proper
      AbstractFolder or AbstractFile something that could be usefull for you?
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=f5dfed4f-92c5-4f60-b301-b3483c6cabec" />
      </body>
      <title>Mapping absolute paths to an AbstractFolder or AbstractFile</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,f5dfed4f-92c5-4f60-b301-b3483c6cabec.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,f5dfed4f-92c5-4f60-b301-b3483c6cabec.aspx</link>
      <pubDate>Wed, 02 Feb 2005 20:55:51 GMT</pubDate>
      <description>&lt;p&gt;
   I've been working part time (translation: I should be working on something else) on
   a new sample: my own Command Prompt. I know, I'm reinventing the wheel, not to count
   that Microsoft will launch a new one called msh (codename Monad). But it was more
   a concept or proof around exposing AbstractFolder and AbstractFile within a command
   prompt.
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of E:\&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   27/12/2004&amp;nbsp; 4:23 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   Backup&lt;br&gt;
   03/11/2004 10:33 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER] Chart30&lt;br&gt;
   24/11/2004 10:09 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER] CLR Profiler&lt;br&gt;
   11/01/2005&amp;nbsp; 5:24 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   Config.Msi&lt;br&gt;
   24/11/2004 10:10 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER] My Music&lt;br&gt;
   12/01/2005&amp;nbsp; 4:13 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   My Pictures&lt;br&gt;
   10/09/2004&amp;nbsp; 1:52 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   RECYCLER&lt;br&gt;
   30/09/2004&amp;nbsp; 8:40 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   System Volume Information&lt;br&gt;
   02/02/2005&amp;nbsp; 2:49 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   temp&lt;br&gt;
   03/11/2004 10:33 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER] XceedProjectsNET&lt;br&gt;
   25/01/2005&amp;nbsp; 7:06 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   143 toto.txt&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 1&amp;nbsp; Folders: 14&amp;nbsp; Total
   file size: 143&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\&amp;gt;&lt;/font&gt;&lt;strong&gt;copy
   toto.txt temp&lt;/strong&gt;
   &lt;br&gt;
   &amp;nbsp;100%&lt;br&gt;
   &lt;font color=#006400&gt;E:\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd temp&lt;/strong&gt;
   &lt;br&gt;
   &lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   As you can see, I can list the contents of folders, copy files, and change the working
   folder. The application simply manages a working "AbstractFolder", and enables commands
   to act on that folder (or an AbstractFolder obtained from an absolute path).
&lt;/p&gt;
&lt;p&gt;
   The sample quicky evolved into a prototype for upcoming features. Among other things,
   I needed a way to recognize a path like "E:\temp\test.zip\images" as a ZippedFolder
   within a zip file. Let's stop the talking, and show some traces:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;md
   test.zip&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;md test.zip\images&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;copy "..\My Pictures\Chalet\*"
   test.zip\images&lt;br&gt;
   &lt;/strong&gt;&amp;nbsp;100%&lt;br&gt;
   &lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   What have I done here? Create a folder named "test.zip"? Well, the "md" command recognized
   the ".zip" extension as a request to create a new empty zip file. The second "md"
   command actually created a new folder within the zip file. And the paths can freely
   use the zip filename as a folder part for any command, as shown with the copy example.
   If we display the contents of "E:\temp", we see the two expected files:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of E:\temp\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   02/02/2005&amp;nbsp; 3:00 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 40068736
   test.zip&lt;br&gt;
   25/01/2005&amp;nbsp; 7:06 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   143 toto.txt&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 2&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 40068879&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   As you can see,&amp;nbsp;"test.zip" is really a file (DiskFile) within "E:\temp" (DiskFolder).
   What happens if I try changing the current folder into that zip file?
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd
   test.zip&lt;/strong&gt;
   &lt;br&gt;
   &lt;font color=#006400&gt;E:\temp\test.zip\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of E:\temp\test.zip\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   02/02/2005&amp;nbsp; 3:00 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   images&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 0&amp;nbsp; Folders: 1&amp;nbsp; Total
   file size: 0&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\test.zip\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd
   images&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;E:\temp\test.zip\images\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of E:\temp\test.zip\images\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   06/08/2000&amp;nbsp; 4:40 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6400006
   Chaises.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:35 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6348550
   Chute.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:29 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6337678
   Ciel1.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:30 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6396226
   Ciel2.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:33 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6414418
   Ciel3.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:38 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6524278
   Couple.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:37 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6388054
   Martine.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:32 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6405478
   Ombre.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:41 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6359254
   Rochers.bmp&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 9&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 57573942&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#006400&gt;E:\temp\test.zip\images\&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   The zip file is exposed as a folder, because the path "E:\temp\test.zip" was recognized
   and mapped to a ZippedFolder around a DiskFile. And "images" is nothing more than
   a subfolder within that root ZippedFolder, actually something like:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New"&gt;new ZippedFolder( new DiskFile( @"E:\temp\test.zip" ), @"\images"
   );&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   Ok, let's get into serious things:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\test.zip\images\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd
   ..\..&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;copy *.zip RAM:\&lt;br&gt;
   &lt;/strong&gt;&amp;nbsp;100%&lt;br&gt;
   &lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd RAM:\test.zip\images&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;RAM:\test.zip\images\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir m*.bmp&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of RAM:\test.zip\images\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   06/08/2000&amp;nbsp; 4:37 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6388054
   Martine.bmp&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 1&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 6388054&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#006400&gt;RAM:\test.zip\images\&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   My Command Prompt exposes a root MemoryFolder called "RAM:\", which I can freely use.
   The commands act the same, no matter if I'm deeling with a ZippedFolder around a DiskFile
   or a MemoryFile. Want more?
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;RAM:\test.zip\images\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd &lt;/strong&gt;&lt;/font&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;ftp://vermouth&lt;/font&gt;
   &lt;br&gt;
   &lt;/strong&gt;&lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of &lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;ftp://vermouth\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 0&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 0&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;md&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;strong&gt; foobar.zip&lt;br&gt;
   &lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;copy&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;strong&gt; "E:\My
   Music\WMA\Mes Aieux" foobar.zip&lt;br&gt;
   &lt;/strong&gt;&amp;nbsp;100%&lt;br&gt;
   &lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of &lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;ftp://vermouth\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   02/02/2005&amp;nbsp; 3:20 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 62936759
   foobar.zip&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 1&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 62936759&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;strong&gt; c:\inetpub\ftproot&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of c:\inetpub\ftproot\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   02/02/2005&amp;nbsp; 3:20 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 62936759
   foobar.zip&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 1&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 62936759&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font color=#006400&gt;&lt;font face="Courier New"&gt;ftp://vermouth\&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   FTP servers are threated as any other kind of AbstractFolder. The application simply
   recognize the "FTP:" prefix as a signature for a root&amp;nbsp;FtpFolder, as it did with
   "RAM:" exposed as a MemoryFolder. The command implementations don't care what kind
   of AbstractFolder or AbstractFile they are dealing with.
&lt;/p&gt;
&lt;p dir=ltr&gt;
   The&amp;nbsp;engine behind this involves FileSystemMapper-derived classes. They mainly
   get asked two kinds of questions:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;strong&gt;Question 1&lt;/strong&gt;: Do you recognize this path as a root?
&lt;/p&gt;
&lt;p&gt;
   If so, they remove the part of the path they could recognize as a root folder, and
   return the matching AbstractFolder.
&lt;/p&gt;
&lt;p&gt;
   Examples of mappers and their responsability:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;DiskMapper&lt;/strong&gt; : Drive letters and UNC paths (yes, you can "cd"
         into a UNC path!)
      &lt;/div&gt;
   &lt;/li&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;FtpMapper&lt;/strong&gt; : The "FTP:" prefix with server name, and optional
         username and password (e.g. ftp://user:pass@vermouth:9999)
      &lt;/div&gt;
   &lt;/li&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;IsolatedStorageMapper&lt;/strong&gt; : A custom prefix name like "STORE:" (that's
         the one my sample app supports).
      &lt;/div&gt;
   &lt;/li&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;MemoryMapper&lt;/strong&gt; : A custom prefix used to create the initial root
         MemoryFolder, like "RAM:" (that's the one my app supports). You can create more than
         one MemoryMapper to have more than one ram drive.
      &lt;/div&gt;
   &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   &lt;strong&gt;Question 2&lt;/strong&gt;: Can you represent this AbstractFile as an AbstractFolder?
&lt;/p&gt;
&lt;p&gt;
   If so, they simply return the matching AbstractFolder.
&lt;/p&gt;
&lt;p&gt;
   An example of such a mapper:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;ZipFileMapper&lt;/strong&gt; : It simply checks if the provided AbstractFile
         exists, then tries to create a ZipArchive around that AbstractFile in a try/catch.
         If it succeeds, it returns this ZipArchive (which derives from ZippedFolder).
      &lt;/div&gt;
   &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   Curiously, today I came across &lt;a href="http://www.xceedsoft.com/Forums/ShowPost.aspx?PostID=2326"&gt;a
   post on our forums&lt;/a&gt; asking how to detect if a file is really a zip file. I gave
   this man the "new ZipArchive within a try/catch" solution, and he came back, as I
   feared, with concerns with the time wasted catching an exception for all those non-zip
   files. It's actually one of the bottlenecks of my Command Prompt sample. A lot of
   time is wasted throwing an exception for all non-zip files my app comes across. Well,
   I guess I'll have to work sooner than later on a new "ZipArchive.IsZipFile" method!
   :-)
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   Now, you have to convince my boss I should put more time on this sample and these
   new FileSystem features! Does mapping absolute paths like shown above to their proper
   AbstractFolder or AbstractFile something that could be usefull for you?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=f5dfed4f-92c5-4f60-b301-b3483c6cabec" /&gt;</description>
      <category>FileSystem;FTP;Samples;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=3b850e06-d464-4338-8b09-93cafae0e87a</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,3b850e06-d464-4338-8b09-93cafae0e87a.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://www.hanselman.com/blog/default.aspx">Scott Hanselman</a> just posted
      about a <a href="http://www.hanselman.com/blog/PermaLink,guid,a393244f-bd14-49d3-b76e-ac94753e00d8.aspx">case-{in}sensitivity</a> problem
      he just went through. That reminded me I wanted to talk to you about case-sensitivity
      in Xceed Zip for .NET and the FileSystem. I remember back in the design days, we debated
      long and hard on if the FileSystem should be case-sensitive or not. Once we decided
      to support both, the debate continued about what should be the default behavior.
   </p>
        <p>
      The conclusions were simple:
   </p>
        <ol>
          <li>
         Immitate by default. 
      </li>
          <li>
         Uniformity within single product. 
      </li>
          <li>
         Know the differences.</li>
        </ol>
        <p>
      Since System.IO was case-insensitive (and moreover the whole Windows operating
      system), we had to be case-insensitive by default. Thus, if you have files "<font face="Courier New">first.txt</font>"
      and "<font face="Courier New">second.TXT</font>" in a folder, the code below will
      return you two files:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">DiskFolder disk = <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"t:\" );</pre>
          <pre style="MARGIN: 0px">AbstractFile[] files = disk.GetFiles( <span style="COLOR: #0000ff">false</span>,
      "*.txt" );</pre>
        </div>
        <p>
      The same way, if you have both files in a zip file, the following code will return
      both:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">ZipArchive zip = <span style="COLOR: #0000ff">new</span> ZipArchive( <span style="COLOR: #0000ff">new</span> DiskFile(
      @"t:\texts.zip" ) );</pre>
          <pre style="MARGIN: 0px">AbstractFile[] files = zip.GetFiles( <span style="COLOR: #0000ff">false</span>,
      "*.txt" );</pre>
        </div>
        <!--EndFragment-->
        <p>
      Now, where it's getting tricky is that you will never have a folder on disk containing
      both "second.TXT" and "second.txt". The system won't let you create the second one.
      Thus the following code returns an <strong>existing</strong> file who's FullName is
      all lower case, even if the real file has an upper-case extension:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">DiskFolder disk = <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"t:\" );</pre>
          <pre style="MARGIN: 0px">AbstractFile file1 = disk.GetFile( "second.txt" );</pre>
        </div>
        <!--EndFragment-->
        <p>
      You asked the "Disk" world for file "second.txt", and this world has recognized "second.TXT"
      as matching your request.
   </p>
        <p>
      To obey to rule #2, the following code does exactly the same, even though the file
      stored in the zip file has its extension all upper case:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">ZipArchive zip = <span style="COLOR: #0000ff">new</span> ZipArchive( <span style="COLOR: #0000ff">new</span> DiskFile(
      @"t:\texts.zip" ) );</pre>
          <pre style="MARGIN: 0px">AbstractFile file2 = zip.GetFile( "second.txt" );</pre>
        </div>
        <!--EndFragment-->
        <p>
      But in a zip file, which can come from a different operating system, you potentially
      could end up with a zip file containing both. What would happen? I've created such
      a zip file for our tests, by adding "second.TXT" and "foobar.txt" to a zip file, and
      hex-editing "foobar" to "second":
   </p>
        <p>
          <a href="http://blogs.xceedsoft.com/plantem/content/binary/second.zip">second.zip
      (.23 KB)</a>
        </p>
        <p>
          <img src="http://blogs.xceedsoft.com/plantem/content/binary/second.jpg" border="0" />
        </p>
        <p>
      When opening this file in WinZip, I can see both files. But when unzipping, it will
      unzip the first, then try to unzip the second over the first. You just can't unzip
      both in two separate files. Furthermore, trying to unzip any single one from within
      the classic view will always unzip both over the same file on disk.
   </p>
        <p>
      How does Xceed Zip for .NET deal with such zip fles? Try the following code:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">ZipArchive zip = <span style="COLOR: #0000ff">new</span> ZipArchive( <span style="COLOR: #0000ff">new</span> DiskFile(
      @"t:\second.zip" ) );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">foreach</span>( AbstractFile
      file <span style="COLOR: #0000ff">in</span> zip.GetFiles( <span style="COLOR: #0000ff">false</span> )
      )</pre>
          <pre style="MARGIN: 0px">{</pre>
          <pre style="MARGIN: 0px">  Console.WriteLine( file.FullName );</pre>
          <pre style="MARGIN: 0px">}</pre>
        </div>
        <p>
      The output is:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
      \second(1).txt<br />
      \second.TXT
   </p>
        </blockquote>
        <p dir="ltr">
      Any file that case-insensitively matches another file gets appended a number. This
      is not a perfect solution, as there is never a perfect solution. To support rule
      #2, DiskFolder and ZippedFolder instances had to behave the same. This post and the
      documentation tries to address rule #3 :-)
   </p>
        <p dir="ltr">
      Now, some of you want to always look for exact matches. You simply need to prepend
      the string mask with a "&gt;", as in "I want a <strong>more</strong> precise
      match" <sup>(1)</sup>. The following code will match a single file:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">DiskFolder disk = <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"t:\" );</pre>
          <pre style="MARGIN: 0px">AbstractFile[] files = disk.GetFiles( <span style="COLOR: #0000ff">false</span>,
      "&gt;*.txt" );</pre>
        </div>
        <p>
      The idea with System.String filter parameters is that we replace them with a <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.namefilterconstructor1.html">NameFilter</a>,
      which is the one responsible for that "&gt;" trick. It only works with methods accepting
      filters (<a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.getfiles_overloads.html">GetFiles</a>, <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.getfolders_overloads.html">GetFolders</a>, <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.copyfilesto_overloads.html">CopyFilesTo</a>, <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.movefilesto_overloads.html">MoveFilesTo</a>).
      Methods like <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.getfile_overloads.html">GetFile</a> can
      only return a single instance (actually always returns an instance which may exist
      or not). Those methods return <strong>the single and unique</strong> AbstractFile
      matching your string, based on the world this AbstractFolder belongs to.
   </p>
        <p>
          <a name="#one">
            <sup>(1)</sup>
          </a>: We actually debated between using "&lt;" as in
      "match <strong>less</strong> items" or "&gt;" as in "a <strong>more</strong> precise
      match". I think we ended up tossing a coin! :-)
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=3b850e06-d464-4338-8b09-93cafae0e87a" />
      </body>
      <title>Case sensitivity in Xceed Zip for .NET</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,3b850e06-d464-4338-8b09-93cafae0e87a.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,3b850e06-d464-4338-8b09-93cafae0e87a.aspx</link>
      <pubDate>Wed, 19 Jan 2005 15:50:47 GMT</pubDate>
      <description>&lt;p&gt;
   &lt;a href="http://www.hanselman.com/blog/default.aspx"&gt;Scott Hanselman&lt;/a&gt; just posted
   about a &lt;a href="http://www.hanselman.com/blog/PermaLink,guid,a393244f-bd14-49d3-b76e-ac94753e00d8.aspx"&gt;case-{in}sensitivity&lt;/a&gt;&amp;nbsp;problem
   he just went through. That reminded me I wanted to talk to you about case-sensitivity
   in Xceed Zip for .NET and the FileSystem. I remember back in the design days, we debated
   long and hard on if the FileSystem should be case-sensitive or not. Once we decided
   to support both, the debate continued about what should be the default behavior.
&lt;/p&gt;
&lt;p&gt;
   The conclusions were simple:
&lt;/p&gt;
&lt;ol&gt;
   &lt;li&gt;
      Immitate by default. 
   &lt;li&gt;
      Uniformity within single product. 
   &lt;li&gt;
      Know the differences.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   Since System.IO was case-insensitive (and moreover the&amp;nbsp;whole Windows operating
   system), we had to be case-insensitive by default. Thus, if you have files "&lt;font face="Courier New"&gt;first.txt&lt;/font&gt;"
   and "&lt;font face="Courier New"&gt;second.TXT&lt;/font&gt;" in a folder, the code below will
   return you two files:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;DiskFolder disk = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"t:\" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;AbstractFile[] files = disk.GetFiles( &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;,
   "*.txt" );&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
   The same way, if you have both files in a zip file, the following code will return
   both:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;ZipArchive zip = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive( &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFile(
   @"t:\texts.zip" ) );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;AbstractFile[] files = zip.GetFiles( &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;,
   "*.txt" );&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   Now, where it's getting tricky is that you will never have a folder on disk containing
   both "second.TXT" and "second.txt". The system won't let you create the second one.
   Thus the following code returns an &lt;strong&gt;existing&lt;/strong&gt; file who's FullName is
   all lower case, even if the real file has an upper-case extension:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;DiskFolder disk = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"t:\" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;AbstractFile file1 = disk.GetFile( "second.txt" );&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   You asked the "Disk" world for file "second.txt", and this world has recognized "second.TXT"
   as matching your request.
&lt;/p&gt;
&lt;p&gt;
   To obey to rule #2, the following code does exactly the same, even though the file
   stored in the zip file has its extension all upper case:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;ZipArchive zip = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive( &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFile(
   @"t:\texts.zip" ) );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;AbstractFile file2 = zip.GetFile( "second.txt" );&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   But in a zip file, which can come from a different operating system, you potentially
   could end up with a zip file containing both. What would happen? I've created such
   a zip file for our tests, by adding "second.TXT" and "foobar.txt" to a zip file, and
   hex-editing "foobar" to "second":
&lt;/p&gt;
&lt;p&gt;
   &lt;a href="http://blogs.xceedsoft.com/plantem/content/binary/second.zip"&gt;second.zip
   (.23 KB)&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;img src="http://blogs.xceedsoft.com/plantem/content/binary/second.jpg" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
   When opening this file in WinZip, I can see both files. But when unzipping, it will
   unzip the first, then try to unzip the second over the first. You just can't unzip
   both in two separate files. Furthermore, trying to unzip any single one from within
   the classic view will always unzip&amp;nbsp;both over the same file on disk.
&lt;/p&gt;
&lt;p&gt;
   How does Xceed Zip for .NET deal with such zip fles? Try the following code:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;ZipArchive zip = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive( &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFile(
   @"t:\second.zip" ) );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;foreach&lt;/span&gt;( AbstractFile
   file &lt;span style="COLOR: #0000ff"&gt;in&lt;/span&gt; zip.GetFiles( &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt; )
   )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; Console.WriteLine( file.FullName );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
   The output is:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   \second(1).txt&lt;br&gt;
   \second.TXT
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   Any file that case-insensitively matches another file gets appended a number. This
   is not a perfect solution, as there is never a&amp;nbsp;perfect solution. To support rule
   #2, DiskFolder and ZippedFolder instances had to behave the same. This post and the
   documentation tries to address rule #3 :-)
&lt;/p&gt;
&lt;p dir=ltr&gt;
   Now, some of you want to always look for exact matches. You simply need to prepend
   the string mask with a "&amp;gt;", as in "I want&amp;nbsp;a &lt;strong&gt;more&lt;/strong&gt; precise
   match" &lt;sup&gt;(1)&lt;/sup&gt;. The following code will match a single file:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;DiskFolder disk = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"t:\" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;AbstractFile[] files = disk.GetFiles( &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;,
   "&amp;gt;*.txt" );&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
   The idea with System.String filter parameters is that we replace them with a &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.namefilterconstructor1.html"&gt;NameFilter&lt;/a&gt;,
   which is the one responsible for that "&amp;gt;" trick. It only works with methods accepting
   filters (&lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.getfiles_overloads.html"&gt;GetFiles&lt;/a&gt;, &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.getfolders_overloads.html"&gt;GetFolders&lt;/a&gt;, &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.copyfilesto_overloads.html"&gt;CopyFilesTo&lt;/a&gt;, &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.movefilesto_overloads.html"&gt;MoveFilesTo&lt;/a&gt;).
   Methods like &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.abstractfolder.getfile_overloads.html"&gt;GetFile&lt;/a&gt; can
   only return a single instance (actually always returns an instance which may exist
   or not). Those methods return &lt;strong&gt;the single and unique&lt;/strong&gt; AbstractFile
   matching your string, based on the world this AbstractFolder belongs to.
&lt;/p&gt;
&lt;p&gt;
   &lt;a name=#one&gt;&lt;sup&gt;(1)&lt;/sup&gt;&lt;/a&gt;: We actually debated between using "&amp;lt;" as in "match &lt;strong&gt;less&lt;/strong&gt; items"
   or "&amp;gt;" as in "a &lt;strong&gt;more&lt;/strong&gt; precise match". I think we ended up&amp;nbsp;tossing
   a coin!&amp;nbsp;:-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=3b850e06-d464-4338-8b09-93cafae0e87a" /&gt;</description>
      <category>FileSystem;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=37b2f647-00c0-4dc9-bd3d-6b7ce8870d3c</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,37b2f647-00c0-4dc9-bd3d-6b7ce8870d3c.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I'm currently doing some tests on an alpha version of Xceed FTP for .NET, supporting
      the Xceed FileSystem. It's so wonderful to be able to manipulate files and folders
      no mather where they reside. Take this generic directory listing method:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">private</span>
            <span style="COLOR: #0000ff">static</span>
            <span style="COLOR: #0000ff">void</span> DisplayListing(
      AbstractFolder folder )</pre>
          <pre style="MARGIN: 0px">{</pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">if</span>( !folder.Exists
      )</pre>
          <pre style="MARGIN: 0px">  {</pre>
          <pre style="MARGIN: 0px">    Console.WriteLine( "\n  Folder {0} does not exist.\n", folder.FullName );</pre>
          <pre style="MARGIN: 0px">  }</pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">else</span></pre>
          <pre style="MARGIN: 0px">  {</pre>
          <pre style="MARGIN: 0px">    FileSystemItem[] items = folder.GetItems( <span style="COLOR: #0000ff">false</span> );</pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">long</span> totalSize
      = 0;</pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">int</span> fileCount
      = 0;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    Console.WriteLine( "\n  Folder listing of {0}\n", folder.FullName );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">foreach</span>(
      FileSystemItem item <span style="COLOR: #0000ff">in</span> items )</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      Console.Write( "{0} {1} ", </pre>
          <pre style="MARGIN: 0px">        item.LastWriteDateTime.ToShortDateString(),</pre>
          <pre style="MARGIN: 0px">        item.LastWriteDateTime.ToShortTimeString() );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      AbstractFile file = item <span style="COLOR: #0000ff">as</span> AbstractFile;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">if</span>(
      file == <span style="COLOR: #0000ff">null</span> )</pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        Console.Write( "  
      <dir>
                   " );</dir></pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">else</span></pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        Console.Write( "{0,16} ", file.Size.ToString( "N0" ) );</pre>
          <pre style="MARGIN: 0px">        totalSize += file.Size;</pre>
          <pre style="MARGIN: 0px">        ++fileCount;</pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      Console.WriteLine( item.Name );</pre>
          <pre style="MARGIN: 0px">    }</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">int</span> folderCount
      = items.Length - fileCount;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    Console.WriteLine( "\n  {0} file{1}, {2} folder{3}, {4} bytes\n",</pre>
          <pre style="MARGIN: 0px">      fileCount.ToString(),</pre>
          <pre style="MARGIN: 0px">      ( fileCount == 1 ) ? <span style="COLOR: #0000ff">string</span>.Empty
      : "s",</pre>
          <pre style="MARGIN: 0px">      folderCount.ToString(),</pre>
          <pre style="MARGIN: 0px">      ( folderCount == 1 ) ? <span style="COLOR: #0000ff">string</span>.Empty
      : "s",</pre>
          <pre style="MARGIN: 0px">      totalSize.ToString() );</pre>
          <pre style="MARGIN: 0px">  }</pre>
          <pre style="MARGIN: 0px">}</pre>
        </div>
        <!--EndFragment-->
        <!--EndFragment-->
        <p>
      As you can see, the code does not need to know what exactly is that AbstractFolder.
      People familiar with Xceed Zip for .NET already know we could call the above method
      like this:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">DiskFolder folder = <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"C:\Program Files\Microsoft SDKs\WinFX" );</pre>
          <pre style="MARGIN: 0px">DisplayListing( folder );</pre>
        </div>
        <!--EndFragment-->
        <!--EndFragment-->
        <!--EndFragment-->
        <p>
      And obtain this kind of output:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <br />
     Folder listing of C:\Program Files\Microsoft SDKs\WinFX\</pre>
          <pre> 24/11/2004   9:29 AM   &lt;DIR&gt;          bin<br />
    24/11/2004   9:27 AM   &lt;DIR&gt;         
   Help<br />
    24/11/2004   9:27 AM   &lt;DIR&gt;         
   License<br />
    24/11/2004   9:27 AM   &lt;DIR&gt;         
   misc<br />
    24/11/2004   9:29 AM   &lt;DIR&gt;         
   Setup<br />
    24/11/2004   9:29 AM   &lt;DIR&gt;         
   VS Install Directory<br />
    11/11/2004   6:03 PM          
   16,001 ReleaseNotes.htm<br />
    12/01/2005   2:58 PM          
   17,297 SetEnv.cmd</pre>
          <pre>  2 files, 6 folders, 33298 bytes<br /></pre>
        </blockquote>
        <!--EndFragment-->
        <p>
      Or call the same method like this:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">ZippedFolder folder = <span style="COLOR: #0000ff">new</span> ZippedFolder( 
      <br />
        <span style="COLOR: #0000ff">new</span> DiskFile( @"D:\sample.zip" ), "ContMenuExt"
      );</pre>
          <pre style="MARGIN: 0px">DisplayListing( folder );</pre>
        </div>
        <!--EndFragment-->
        <p>
      To get this output:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <br />
     Folder listing of \ContMenuExt\</pre>
          <pre> 08/01/2001  11:29 AM            8,091 ContextMenu.cpp<br />
    02/01/2001   4:15 PM           
   1,005 ContextMenu.h<br />
    08/01/2001  11:32 AM           
   7,820 ContextMenuExt.cpp<br />
    28/11/2000  11:23 AM             
   225 ContextMenuExt.def<br />
    02/01/2001   5:02 PM           
   5,301 ContextMenuExt.dsp<br />
    28/11/2000  11:23 AM             
   551 ContextMenuExt.dsw<br />
    28/11/2000  11:23 AM             
   742 ContextMenuExt.h<br />
    02/01/2001   4:12 PM           
   1,440 ContextMenuExt.rc<br />
    08/01/2001   3:29 PM               
   2 ReadMe.txt<br />
    02/01/2001   4:12 PM           
   1,195 resource.h</pre>
          <pre>  10 files, 0 folders, 26372 bytes<br /></pre>
        </blockquote>
        <p>
      With the upcoming version of Xceed FTP for .NET, it won't be more difficult to display
      the contents of a folder located on an FTP server:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">FtpConnectionInfo info = <span style="COLOR: #0000ff">new</span> FtpConnectionInfo(
      "ftp.microsoft.com" );</pre>
          <pre style="MARGIN: 0px">FtpFolder folder = <span style="COLOR: #0000ff">new</span> FtpFolder(
      info );</pre>
          <pre style="MARGIN: 0px">DisplayListing( folder );</pre>
        </div>
        <!--EndFragment-->
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <br />
     Folder listing of \</pre>
          <pre> 25/11/2002  12:00 AM   &lt;DIR&gt;          bussys<br />
    21/05/2001  12:00 AM   &lt;DIR&gt;         
   deskapps<br />
    20/04/2001  12:00 AM   &lt;DIR&gt;         
   developr<br />
    18/11/2002  12:00 AM   &lt;DIR&gt;         
   KBHelp<br />
    02/07/2002  12:00 AM   &lt;DIR&gt;         
   MISC<br />
    16/12/2002  12:00 AM   &lt;DIR&gt;         
   MISC1<br />
    25/02/2000  12:00 AM   &lt;DIR&gt;         
   peropsys<br />
    02/01/2001  12:00 AM   &lt;DIR&gt;         
   Products<br />
    04/04/2003  12:00 AM   &lt;DIR&gt;         
   PSS<br />
    21/09/2000  12:00 AM   &lt;DIR&gt;         
   ResKit<br />
    25/02/2000  12:00 AM   &lt;DIR&gt;         
   Services<br />
    25/02/2000  12:00 AM   &lt;DIR&gt;         
   Softlib</pre>
          <pre>  0 files, 12 folders, 0 bytes<br /></pre>
        </blockquote>
        <p>
      As a mather of fact, stuff like this already works fine on my machine:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console">
          <pre style="MARGIN: 0px">FtpConnectionInfo info = <span style="COLOR: #0000ff">new</span> FtpConnectionInfo(
      "ftp.cam.org", "***", "***" );</pre>
          <pre style="MARGIN: 0px">FtpFile ftpFile = <span style="COLOR: #0000ff">new</span> FtpFile(
      info, @"\pub\Photos.zip" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">if</span>( ftpFile.Exists )</pre>
          <pre style="MARGIN: 0px">  ftpFile.Delete();</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">DiskFolder sourceFolder = <span style="COLOR: #0000ff">new</span> DiskFolder(
      @"E:\My Pictures\Clément\Petites" );</pre>
          <pre style="MARGIN: 0px">ZipArchive destFolder = <span style="COLOR: #0000ff">new</span> ZipArchive(
      ftpFile );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">sourceFolder.CopyFilesTo( destFolder, <span style="COLOR: #0000ff">true</span>, <span style="COLOR: #0000ff">true</span> );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">DisplayListing( destFolder );</pre>
          <pre style="MARGIN: 0px">DisplayListing( ftpFile.ParentFolder );</pre>
        </div>
        <!--EndFragment-->
        <p>
      This is the output:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <br />
     Folder listing of \</pre>
          <pre> 16/09/2004   9:39 AM           11,820 Buzz.jpg<br />
    16/09/2004   9:40 AM          
   11,143 Chalet - Bercé.jpg<br />
    16/09/2004   9:42 AM          
   15,749 Clément et Michel.jpg<br />
    16/09/2004   9:43 AM          
   18,473 Clément et Papa.jpg<br />
    16/09/2004   9:42 AM          
   15,004 Clément et Valérie.jpg<br />
    14/02/2003   4:17 PM           
   7,984 clément1.jpg<br />
    14/02/2003   4:18 PM          
   11,288 clément2.jpg<br />
    14/02/2003   4:18 PM          
   10,648 clément3.jpg<br />
    11/08/2004   3:25 PM          
   18,499 Famille.jpg<br />
    11/08/2004   3:23 PM          
   36,734 Fier.jpg<br />
    16/09/2004   9:40 AM          
   14,959 Grande discussion.jpg<br />
    16/09/2004   9:41 AM          
   13,426 Maman et Clément.jpg<br />
    11/08/2004   3:25 PM          
   24,594 Piscine.jpg</pre>
          <pre>  13 files, 0 folders, 210321 bytes</pre>
          <pre>
            <br />
     Folder listing of \pub\</pre>
          <pre> 27/12/2004  11:06 AM            7,986 Builds du 2004-09-27.htm<br />
    12/01/2005   4:13 PM         
   208,439 Clement.zip<br />
    27/12/2004  11:06 AM           
   1,068 FileSystem.txt<br />
    18/01/2005   2:44 PM         
   208,423 Photos.zip<br />
    27/12/2004  11:06 AM   &lt;DIR&gt;         
   Second<br />
    27/12/2004  11:06 AM          
   11,723 VSSWarning.jpg<br />
    27/12/2004  11:06 AM         
   117,695 appnote.txt<br />
    27/12/2004  11:06 AM              
   96 vssver.scc</pre>
          <pre>  7 files, 1 folder, 555430 bytes<br /></pre>
        </blockquote>
        <p>
      Am I the only one to find this cool? q;-)
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=37b2f647-00c0-4dc9-bd3d-6b7ce8870d3c" />
      </body>
      <title>Adding FTP support to the Xceed FileSystem</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,37b2f647-00c0-4dc9-bd3d-6b7ce8870d3c.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,37b2f647-00c0-4dc9-bd3d-6b7ce8870d3c.aspx</link>
      <pubDate>Tue, 18 Jan 2005 19:49:50 GMT</pubDate>
      <description>&lt;p&gt;
   I'm currently doing some tests on an alpha version of Xceed FTP for .NET, supporting
   the Xceed FileSystem. It's so wonderful to be able to manipulate files and folders
   no mather where they reside. Take this generic directory listing method:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; DisplayListing(
   AbstractFolder folder )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( !folder.Exists
   )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; Console.WriteLine( "\n&amp;nbsp; Folder {0} does not exist.\n", folder.FullName );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; FileSystemItem[] items = folder.GetItems( &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt; );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;long&lt;/span&gt; totalSize
   = 0;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;int&lt;/span&gt; fileCount
   = 0;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; Console.WriteLine( "\n&amp;nbsp; Folder listing of {0}\n", folder.FullName );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;foreach&lt;/span&gt;(
   FileSystemItem item &lt;span style="COLOR: #0000ff"&gt;in&lt;/span&gt; items )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Console.Write( "{0} {1} ", &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; item.LastWriteDateTime.ToShortDateString(),&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; item.LastWriteDateTime.ToShortTimeString() );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; AbstractFile file = item &lt;span style="COLOR: #0000ff"&gt;as&lt;/span&gt; AbstractFile;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(
   file == &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Console.Write( "&amp;nbsp; 
   &lt;dir&gt;
      &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; " );&lt;/dir&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Console.Write( "{0,16} ", file.Size.ToString( "N0" ) );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; totalSize += file.Size;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ++fileCount;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Console.WriteLine( item.Name );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;int&lt;/span&gt; folderCount
   = items.Length - fileCount;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; Console.WriteLine( "\n&amp;nbsp; {0} file{1}, {2} folder{3}, {4} bytes\n",&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; fileCount.ToString(),&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ( fileCount == 1 ) ? &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;.Empty
   : "s",&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; folderCount.ToString(),&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ( folderCount == 1 ) ? &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;.Empty
   : "s",&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; totalSize.ToString() );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   As you can see, the code does not need to know what exactly is that AbstractFolder.
   People familiar with Xceed Zip for .NET already know we could call the above method
   like this:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;DiskFolder folder = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"C:\Program Files\Microsoft SDKs\WinFX" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;DisplayListing( folder );&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;!--EndFragment--&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   And obtain this kind of output:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;
&lt;br&gt;
&amp;nbsp; Folder listing of C:\Program Files\Microsoft SDKs\WinFX\&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;24/11/2004&amp;nbsp;&amp;nbsp; 9:29 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bin&lt;br&gt;
&amp;nbsp;24/11/2004&amp;nbsp;&amp;nbsp; 9:27 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Help&lt;br&gt;
&amp;nbsp;24/11/2004&amp;nbsp;&amp;nbsp; 9:27 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
License&lt;br&gt;
&amp;nbsp;24/11/2004&amp;nbsp;&amp;nbsp; 9:27 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
misc&lt;br&gt;
&amp;nbsp;24/11/2004&amp;nbsp;&amp;nbsp; 9:29 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Setup&lt;br&gt;
&amp;nbsp;24/11/2004&amp;nbsp;&amp;nbsp; 9:29 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
VS Install Directory&lt;br&gt;
&amp;nbsp;11/11/2004&amp;nbsp;&amp;nbsp; 6:03 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
16,001 ReleaseNotes.htm&lt;br&gt;
&amp;nbsp;12/01/2005&amp;nbsp;&amp;nbsp; 2:58 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
17,297 SetEnv.cmd&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp; 2 files, 6 folders, 33298 bytes&lt;br&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   Or call the same method like this:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;ZippedFolder folder = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZippedFolder( 
   &lt;br&gt;
   &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFile( @"D:\sample.zip" ), "ContMenuExt"
   );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;DisplayListing( folder );&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   To get this output:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;
&lt;br&gt;
&amp;nbsp; Folder listing of \ContMenuExt\&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;08/01/2001&amp;nbsp; 11:29 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8,091 ContextMenu.cpp&lt;br&gt;
&amp;nbsp;02/01/2001&amp;nbsp;&amp;nbsp; 4:15 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
1,005 ContextMenu.h&lt;br&gt;
&amp;nbsp;08/01/2001&amp;nbsp; 11:32 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
7,820 ContextMenuExt.cpp&lt;br&gt;
&amp;nbsp;28/11/2000&amp;nbsp; 11:23 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
225 ContextMenuExt.def&lt;br&gt;
&amp;nbsp;02/01/2001&amp;nbsp;&amp;nbsp; 5:02 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
5,301 ContextMenuExt.dsp&lt;br&gt;
&amp;nbsp;28/11/2000&amp;nbsp; 11:23 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
551 ContextMenuExt.dsw&lt;br&gt;
&amp;nbsp;28/11/2000&amp;nbsp; 11:23 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
742 ContextMenuExt.h&lt;br&gt;
&amp;nbsp;02/01/2001&amp;nbsp;&amp;nbsp; 4:12 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
1,440 ContextMenuExt.rc&lt;br&gt;
&amp;nbsp;08/01/2001&amp;nbsp;&amp;nbsp; 3:29 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
2 ReadMe.txt&lt;br&gt;
&amp;nbsp;02/01/2001&amp;nbsp;&amp;nbsp; 4:12 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
1,195 resource.h&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp; 10 files, 0 folders, 26372 bytes&lt;br&gt;
&lt;/pre&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   With the upcoming version of Xceed FTP for .NET, it won't be more difficult to display
   the contents of a folder located on an FTP server:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;FtpConnectionInfo info = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; FtpConnectionInfo(
   "ftp.microsoft.com" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;FtpFolder folder = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; FtpFolder(
   info );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;DisplayListing( folder );&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;
&lt;br&gt;
&amp;nbsp; Folder listing of \&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;25/11/2002&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bussys&lt;br&gt;
&amp;nbsp;21/05/2001&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
deskapps&lt;br&gt;
&amp;nbsp;20/04/2001&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
developr&lt;br&gt;
&amp;nbsp;18/11/2002&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
KBHelp&lt;br&gt;
&amp;nbsp;02/07/2002&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MISC&lt;br&gt;
&amp;nbsp;16/12/2002&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MISC1&lt;br&gt;
&amp;nbsp;25/02/2000&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
peropsys&lt;br&gt;
&amp;nbsp;02/01/2001&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Products&lt;br&gt;
&amp;nbsp;04/04/2003&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PSS&lt;br&gt;
&amp;nbsp;21/09/2000&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ResKit&lt;br&gt;
&amp;nbsp;25/02/2000&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Services&lt;br&gt;
&amp;nbsp;25/02/2000&amp;nbsp; 12:00 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Softlib&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp; 0 files, 12 folders, 0 bytes&lt;br&gt;
&lt;/pre&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   As a mather of fact, stuff like this already works fine on my machine:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5pt; FONT-SIZE: 10pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 5pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 5pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: Lucida Console"&gt;&lt;pre style="MARGIN: 0px"&gt;FtpConnectionInfo info = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; FtpConnectionInfo(
   "ftp.cam.org", "***", "***" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;FtpFile ftpFile = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; FtpFile(
   info, @"\pub\Photos.zip" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;( ftpFile.Exists )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; ftpFile.Delete();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;DiskFolder sourceFolder = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DiskFolder(
   @"E:\My Pictures\Clément\Petites" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;ZipArchive destFolder = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ZipArchive(
   ftpFile );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;sourceFolder.CopyFilesTo( destFolder, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt; );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;DisplayListing( destFolder );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;DisplayListing( ftpFile.ParentFolder );&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;
&lt;p&gt;
   This is the output:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;
&lt;br&gt;
&amp;nbsp; Folder listing of \&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;16/09/2004&amp;nbsp;&amp;nbsp; 9:39 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11,820 Buzz.jpg&lt;br&gt;
&amp;nbsp;16/09/2004&amp;nbsp;&amp;nbsp; 9:40 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
11,143 Chalet - Bercé.jpg&lt;br&gt;
&amp;nbsp;16/09/2004&amp;nbsp;&amp;nbsp; 9:42 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
15,749 Clément et Michel.jpg&lt;br&gt;
&amp;nbsp;16/09/2004&amp;nbsp;&amp;nbsp; 9:43 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
18,473 Clément et Papa.jpg&lt;br&gt;
&amp;nbsp;16/09/2004&amp;nbsp;&amp;nbsp; 9:42 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
15,004 Clément et Valérie.jpg&lt;br&gt;
&amp;nbsp;14/02/2003&amp;nbsp;&amp;nbsp; 4:17 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
7,984 clément1.jpg&lt;br&gt;
&amp;nbsp;14/02/2003&amp;nbsp;&amp;nbsp; 4:18 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
11,288 clément2.jpg&lt;br&gt;
&amp;nbsp;14/02/2003&amp;nbsp;&amp;nbsp; 4:18 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
10,648 clément3.jpg&lt;br&gt;
&amp;nbsp;11/08/2004&amp;nbsp;&amp;nbsp; 3:25 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
18,499 Famille.jpg&lt;br&gt;
&amp;nbsp;11/08/2004&amp;nbsp;&amp;nbsp; 3:23 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
36,734 Fier.jpg&lt;br&gt;
&amp;nbsp;16/09/2004&amp;nbsp;&amp;nbsp; 9:40 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
14,959 Grande discussion.jpg&lt;br&gt;
&amp;nbsp;16/09/2004&amp;nbsp;&amp;nbsp; 9:41 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
13,426 Maman et Clément.jpg&lt;br&gt;
&amp;nbsp;11/08/2004&amp;nbsp;&amp;nbsp; 3:25 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
24,594 Piscine.jpg&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp; 13 files, 0 folders, 210321 bytes&lt;/pre&gt;
&lt;pre&gt;
&lt;br&gt;
&amp;nbsp; Folder listing of \pub\&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;27/12/2004&amp;nbsp; 11:06 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7,986 Builds du 2004-09-27.htm&lt;br&gt;
&amp;nbsp;12/01/2005&amp;nbsp;&amp;nbsp; 4:13 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
208,439 Clement.zip&lt;br&gt;
&amp;nbsp;27/12/2004&amp;nbsp; 11:06 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
1,068 FileSystem.txt&lt;br&gt;
&amp;nbsp;18/01/2005&amp;nbsp;&amp;nbsp; 2:44 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
208,423 Photos.zip&lt;br&gt;
&amp;nbsp;27/12/2004&amp;nbsp; 11:06 AM&amp;nbsp;&amp;nbsp; &amp;lt;DIR&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Second&lt;br&gt;
&amp;nbsp;27/12/2004&amp;nbsp; 11:06 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
11,723 VSSWarning.jpg&lt;br&gt;
&amp;nbsp;27/12/2004&amp;nbsp; 11:06 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
117,695 appnote.txt&lt;br&gt;
&amp;nbsp;27/12/2004&amp;nbsp; 11:06 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
96 vssver.scc&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp; 7 files, 1 folder, 555430 bytes&lt;br&gt;
&lt;/pre&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   Am I the only one to find this cool? q;-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=37b2f647-00c0-4dc9-bd3d-6b7ce8870d3c" /&gt;</description>
      <category>FileSystem;FTP;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=79c0a728-6d72-4b97-9973-74333e4df44d</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,79c0a728-6d72-4b97-9973-74333e4df44d.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I admit, I'm working in zip file compression, and I'm not even using something home
      made for unzipping zip files I run into. I'm using <a href="http://www.winzip.com/">WinZip</a>'s
      context menu.
   </p>
        <p>
      Well, I should talk to the past. I've made a man of myself and implemented my own
      "Unzip Here" context menu, which is using Xceed Zip ActiveX 5.x. Why reinvent the
      wheel when it works fine? Because it didn't work that fine for me.
   </p>
        <p>
      How many times have I right-clicked on a zip file, went to the <strong><em>WinZip</em></strong> menu,
      stared at <strong><em>Extract to here</em></strong> and <strong><em>Extract to d:\someplace\somewhere\zipfilename</em></strong> just
      to find asking myself: <em>"Does that zip file already contain paths?"</em>. If it
      does, I don't need to create a "zipfilename" subfolder, thus I should select the first
      menu item. But if it doesn't, I sure don't want all unzipped files to end up in the
      current folder, thus I want to select the second menu item. I end up opening the zip
      file just to view file paths.
   </p>
        <p>
      That's what I just implemented. You right-click on a zip file, you click on <strong><em>Unzip
      Here</em></strong>, and it will automatically detect if it needs to create a subfolder
      (using the zip filename) or not, then unzip everything.
   </p>
        <p>
      I won't go into the full details of how to create a Windows Shell Extension component,
      the sample is pretty self-explanatory, and the web is filled with tutorials. In short,
      you:
   </p>
        <ul>
          <li>
         Create a new <strong><em>ATL COM AppWizard</em></strong> project (VC++ 6). 
      </li>
          <li>
         Add a new <strong><em>Simple Object</em></strong> with default names and attributes
         (make sure not to select "Free Threaded"). 
      </li>
          <li>
         Remove references to the newly created interface, you don't need it. (I left the IDL
         in there instead of copying the CLSID somewhere else... I'm lazy). 
      </li>
          <li>
         Remove the type library from the resources and RGS file, you don't need it. 
      </li>
          <li>
         Implement <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/ishellextinit/ishellextinit.asp">IShellExtInit</a> and <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/icontextmenu/icontextmenu.asp">IContextMenu</a> interfaces
         (see UnzipHereExtension.cpp). 
      </li>
          <li>
         Add the required registry keys (see "DllRegisterServer" in UnzipHere.cpp).</li>
        </ul>
        <p>
      The heart of the extension resides in <strong><em>IContextMenu::InvokeCommand</em></strong>.
      Don't forget more than one file can be selected when your context menu gets called.
   </p>
        <p>
      While debugging, you'll often need to restart the <strong><em>explorer.exe</em></strong> in
      order to release usage of your DLL. Use the Task Manager's run menu to reload it.
      If you don't like ending a task via the Task Manager, try this: Start Menu -&gt; Shutdown,
      press Ctrl-Alt-Shift and click Cancel. The explorer.exe process will end.
   </p>
        <p>
      On my TODO list:
   </p>
        <ul>
          <li>
         Support zip files not ending with the ZIP extension (like self-extracting zip files). 
      </li>
          <li>
         Implement a "Zip This" menu. 
      </li>
          <li>
         Add a "File already exists. Do you want to overwrite?" prompt. 
      </li>
          <li>
         Hide the "aborted" error on non-zip files.</li>
        </ul>
        <p>
      Comments welcomed! Have fun!
   </p>
        <a href="http://blogs.xceedsoft.com/plantem/content/binary/UnzipHere.zip">UnzipHere.zip
   (21 KB)</a>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=79c0a728-6d72-4b97-9973-74333e4df44d" />
      </body>
      <title>Implementing my own "Unzip Here" context menu</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,79c0a728-6d72-4b97-9973-74333e4df44d.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,79c0a728-6d72-4b97-9973-74333e4df44d.aspx</link>
      <pubDate>Mon, 13 Dec 2004 20:57:24 GMT</pubDate>
      <description>&lt;p&gt;
   I admit, I'm working in zip file compression, and I'm not even using something home
   made for unzipping zip files I run into. I'm using &lt;a href="http://www.winzip.com/"&gt;WinZip&lt;/a&gt;'s
   context menu.
&lt;/p&gt;
&lt;p&gt;
   Well, I should talk to the past. I've made a man of myself and implemented my own
   "Unzip Here" context menu, which is using Xceed Zip ActiveX 5.x. Why reinvent the
   wheel when it works fine? Because it didn't work that fine for me.
&lt;/p&gt;
&lt;p&gt;
   How many times have I right-clicked on a zip file, went to the &lt;strong&gt;&lt;em&gt;WinZip&lt;/em&gt;&lt;/strong&gt; menu,
   stared at &lt;strong&gt;&lt;em&gt;Extract to here&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;Extract to d:\someplace\somewhere\zipfilename&lt;/em&gt;&lt;/strong&gt; just
   to find asking myself: &lt;em&gt;"Does that zip file already contain paths?"&lt;/em&gt;. If it
   does, I don't need to create a "zipfilename" subfolder, thus I should select the first
   menu item. But if it doesn't, I sure don't want all unzipped files to end up in the
   current folder, thus I want to select the second menu item. I end up opening the zip
   file just to view file paths.
&lt;/p&gt;
&lt;p&gt;
   That's what I just implemented. You right-click on a zip file, you click on &lt;strong&gt;&lt;em&gt;Unzip
   Here&lt;/em&gt;&lt;/strong&gt;, and it will automatically detect if it needs to create a subfolder
   (using the zip filename) or not, then unzip everything.
&lt;/p&gt;
&lt;p&gt;
   I won't go into the full details of how to create a Windows Shell Extension component,
   the sample is pretty self-explanatory, and the web is filled with tutorials. In short,
   you:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      Create a new &lt;strong&gt;&lt;em&gt;ATL COM AppWizard&lt;/em&gt;&lt;/strong&gt; project (VC++ 6). 
   &lt;li&gt;
      Add a new &lt;strong&gt;&lt;em&gt;Simple Object&lt;/em&gt;&lt;/strong&gt; with default names and attributes
      (make sure not to select "Free Threaded"). 
   &lt;li&gt;
      Remove references to the newly created interface, you don't need it. (I left the IDL
      in there instead of copying the CLSID somewhere else... I'm lazy). 
   &lt;li&gt;
      Remove the type library from the resources and RGS file, you don't need it. 
   &lt;li&gt;
      Implement &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/ishellextinit/ishellextinit.asp"&gt;IShellExtInit&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/icontextmenu/icontextmenu.asp"&gt;IContextMenu&lt;/a&gt; interfaces
      (see UnzipHereExtension.cpp). 
   &lt;li&gt;
      Add the required registry keys (see "DllRegisterServer" in UnzipHere.cpp).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   The heart of the extension resides in &lt;strong&gt;&lt;em&gt;IContextMenu::InvokeCommand&lt;/em&gt;&lt;/strong&gt;.
   Don't forget more than one file can be selected when your context menu gets called.
&lt;/p&gt;
&lt;p&gt;
   While debugging, you'll often need to restart the &lt;strong&gt;&lt;em&gt;explorer.exe&lt;/em&gt;&lt;/strong&gt; in
   order to release usage of your DLL. Use the Task Manager's run menu to reload it.
   If you don't like ending a task via the Task Manager, try this: Start Menu -&amp;gt; Shutdown,
   press Ctrl-Alt-Shift and click Cancel. The explorer.exe process will end.
&lt;/p&gt;
&lt;p&gt;
   On my TODO list:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      Support zip files not ending with the ZIP extension (like self-extracting zip files). 
   &lt;li&gt;
      Implement a "Zip This" menu. 
   &lt;li&gt;
      Add a "File already exists. Do you want to overwrite?" prompt. 
   &lt;li&gt;
      Hide the "aborted" error on non-zip files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   Comments welcomed! Have fun!
&lt;/p&gt;
&lt;a href="http://blogs.xceedsoft.com/plantem/content/binary/UnzipHere.zip"&gt;UnzipHere.zip
(21 KB)&lt;/a&gt;&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=79c0a728-6d72-4b97-9973-74333e4df44d" /&gt;</description>
      <category>Zip;Samples</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=a4ea2021-91ce-482d-a54d-b3dd04f18f2d</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,a4ea2021-91ce-482d-a54d-b3dd04f18f2d.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <h4>Non-Transactional by defaut
   </h4>
        <p>
      The ZIP file format dictates by its nature that the creation of a zip file is a transactional
      operation. We cumulate a list of files to compress, with all metadata information,
      and we create the zip file in a single step, compressing each file sequentially, making
      sure to comply with a storage format that does not leave room for punctual updates.
      Imagine having to change the contents of a single file within a zip file. You have
      to rebuild the zip file from the beginning, by copying untouched files' compressed
      data to a new copy of the zip file, then append the modified file's compressed data,
      and complete the zip file with the new central directory and ending header.
   </p>
        <p>
      On the opposite side, changing the contents of a file stored on your hard disk is
      simple. Each file is accessible randomly, and changing one's contents does not require
      moving or updating others. Take this for example:
   </p>
        <pre>  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile file = new DiskFile( @"d:\mydata.txt" );

  if( !file.Exists )
    file.Create();

  using( Stream stream = file.OpenWrite( true ) )
  {
    stream.Write( mydata, 0, mydata.Length );
  }</pre>
        <p>
      The operation is atomic on the file. The Xceed FileSystem's goal is to mimic this
      random file access to any possible representation of a file. Thus, exposing compressed
      files stored in a zip file is no simple task. With the above code, if you replace <strong><em>new
      DiskFile(...)</em></strong> with <strong><em>new ZippedFile(...)</em></strong>, it
      will work as expected. What you don't see is that only when the stream gets closed
      will the zip file get rebuilt. All data that you write to the stream is compressed
      and stored in a temp file, until the last "modify" operation is completed on that
      zip file. Another example:
   </p>
        <pre>  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile file1 = new DiskFile( @"d:\mydata.txt" );
  AbstractFile file2 = new DiskFile( @"d:\mydatatoo.txt" );
  
  if( !file1.Exists )
    file1.Create();
    
  if( !file2.Exists )
    file2.Create();
    
  using( Stream stream1 = file1.OpenWrite( true ) )
  {
    using( Stream stream2 = file2.OpenWrite( true ) )
    {
      stream1.Write( mydata, 0, mydata.Length );
      stream2.Write( mydata, 0, mydata.Length );
    }
  }</pre>
        <p>
      In the atomic world of disk files, both files have no influence on the other. But
      again, replace DiskFile instances with ZippedFiles, and it's another story. The two
      files are stored in a zip file, which can only get rebuilt when the last "modify"
      operation completes, thus when "stream1.Close" is called. Will the above code work?
      Sure! But the zip file will be rebuilt three times. Try it!
   </p>
        <pre>  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile zipFile = new DiskFile( @"d:\mydatafiles.zip" );
  AbstractFile file1 = new ZippedFile( zipFile, @"\mydata.txt" );
  AbstractFile file2 = new ZippedFile( zipFile, @"\mydatatoo.txt" );

  if( !file1.Exists )
    file1.Create();

  Console.WriteLine( "Check the zip file with WinZip!" );
  Console.WriteLine( "It should contain one empty file named 'mydata.txt'." );
  Console.ReadLine();

  if( !file2.Exists )
    file2.Create();

  Console.WriteLine( "Check the zip file with WinZip!" );
  Console.WriteLine( "It should contain two empty files now." );
  Console.ReadLine();

  using( Stream stream1 = file1.OpenWrite( true ) )
  {
    using( Stream stream2 = file2.OpenWrite( true ) )
    {
      stream1.Write( mydata, 0, mydata.Length );
      stream2.Write( mydata, 0, mydata.Length );
    }

    Console.WriteLine( "Check the zip file with WinZip!" );
    Console.WriteLine( "It still contains two empty files." );
    Console.ReadLine();
  }

  Console.WriteLine( "Check the zip file with WinZip!" );
  Console.WriteLine( "Now it contains both files with their data." );
  Console.ReadLine();</pre>
        <p>
      The first call to <strong><em>file1.Create</em></strong> increments the "modify" count
      to 1, then down to 0, so the zip file is built, containing an empty file. After the
      second call to <strong><em>Create</em></strong>, the zip file is again rebuilt, containing
      two empty files. When the first call to <strong><em>OpenWrite</em></strong> is made,
      the "modify" count gets up to 1. After the second call to <strong><em>OpenWrite</em></strong>,
      it's up to 2. Then <strong><em>stream2</em></strong> is closed, and the count gets
      down to 1. Finally <strong><em>stream1</em></strong> is closed, the count gets to
      0, and the zip file is rebuilt, containing two files with compressed data.
   </p>
        <p>
      In this simple example, the cost is not that much. Let's imagine worse:
   </p>
        <pre>  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile zipFile = new DiskFile( @"d:\mydatafiles.zip" );

  if( zipFile.Exists )
    zipFile.Delete();

  for( int i=0; i&lt;1000; i++ )
  {
    Console.WriteLine( "Loop {0}", i );
    AbstractFile file = new ZippedFile( zipFile, @"\data" + i.ToString() + ".txt" );

    if( !file.Exists ) 
      file.Create(); 

    using( Stream stream = file.OpenWrite( true ) ) 
    {
      stream.Write( mydata, 0, mydata.Length ); 
    }
  }</pre>
        <p>
      If you try this, you'll notice that each loop takes more time than the previous. Actually,
      when I tried this, I wasn't patient enough to wait until completion. The zip file
      would get rebuilt 2000 times, with more and more files already in the zip file. This
      is plainly unacceptable.
   </p>
        <h4>Transactional on demand
   </h4>
        <p>
      That's where the <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.ibatchupdateable.html">IBatchUpdateable</a> interface
      comes to the rescue. It contains two simple methods: <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.ibatchupdateable.beginupdate.html">BeginUpdate</a> and <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.ibatchupdateable.endupdate.html">EndUpdate</a>.
      Any AbstractFile or AbstractFolder's derived class can implement this interface, though
      you can limit this to the root folder. Once BeginUpdate is called, the implementor
      can hold any modifications to the underlying media until EndUpdate is called. <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.ziparchive.html">ZipArchive</a>,
      which represents the root ZippedFolder for a zip file, implement this interface. In
      short, BeginUpdate artificially increments the "modify" count to 1, and EndUpdate
      decrements it. If it gets to 0, the underlying zip file is rebuilt. You can call BeginUpdate
      and EndUpdate as many times as you want, but every call to BeginUpdate must be matched
      with a call to EndUpdate. The above code could now look like this:
   </p>
        <pre>  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile zipFile = new DiskFile( @"d:\mydatafiles.zip" );
  ZipArchive zip = new ZipArchive( zipFile );

  if( zipFile.Exists )
    zipFile.Delete();

  zip.BeginUpdate();

  try
  {       
    for( int i=0; i&lt;1000; i++ )
    {
      Console.WriteLine( "Loop {0}", i );
      AbstractFile file = new ZippedFile( zipFile, @"\data" + i.ToString() + ".txt" );

      if( !file.Exists ) 
        file.Create(); 

      using( Stream stream = file.OpenWrite( true ) ) 
      {
        stream.Write( mydata, 0, mydata.Length ); 
      }
    }
  }
  finally
  {
    zip.EndUpdate();
  }</pre>
        <p>
      Now that's better. On my machine, this takes a few seconds.
   </p>
        <p>
      The FileSystem's main goal was to offer a unique and consistent interface for manipulating
      any kind of file or folder. That's why we decided that ZippedFile and ZippedFolder
      were to be non-transactional by default, even though in most cases, it will end-up
      producing less efficient code. It's the user's job to call BeginUpdate before modifying
      the zip file, and EndUpdate once completed, to achieve better performance.
   </p>
        <p>
      By the way, for those who like the <strong><em>using( IDisposable )</em></strong> pattern
      in C#, you can use the <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.autobatchupdate.html">AutoBatchUpdate</a> class
      like this:
   </p>
        <pre>  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile zipFile = new DiskFile( @"d:\mydatafiles.zip" );
  ZipArchive zip = new ZipArchive( zipFile );

  if( zipFile.Exists )
    zipFile.Delete();

  using( AutoBatchUpdate auto = new AutoBatchUpdate( zip ) )
  {
    for( int i=0; i&lt;1000; i++ )
    {
      Console.WriteLine( "Loop {0}", i );
      AbstractFile file = new ZippedFile( zipFile, @"\data" + i.ToString() + ".txt" );

      if( !file.Exists ) 
        file.Create(); 

      using( Stream stream = file.OpenWrite( true ) ) 
      {
        stream.Write( mydata, 0, mydata.Length ); 
      }
    }
  }</pre>
        <p>
      The AutoBatchUpdate implements IDisposable, making sure to call BeginUpdate on the
      object at construction, and EndUpdate when disposed. What's even better is that you
      can pass any <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.filesystemitem.html">FileSystemItem</a>:
      it will do nothing if the item's <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.filesystemitem.rootfolder.html">RootFolder</a> does
      not implement IBatchUpdateable. Thus, you can use AutoBatchUpdate without having to
      know if the AbstractFile or AbstractFolder you're working with implements IBatchUpdateable
      or not.
   </p>
        <h4>Temp storage
   </h4>
        <p>
      Now, it's good to know that when using BeginUpdate and EndUpdate, the zip file is
      rebuilt only at the very last moment, but where goes the compressed data I'm writing
      to the streams? It must be stored somewhere, right? The ZipArchive class exposes two
      important properties: <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.ziparchive.defaulttempfolder.html">DefaultTempFolder</a> (static)
      and <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.ziparchive.tempfolder.html">TempFolder</a>.
      By default, the first is equal to <strong><em>new DiskFolder( System.IO.Path.GetTempPath()
      )</em></strong>, the temp folder of the currently logged-in user. You can assign to
      it any AbstractFolder, as long as AbstractFile instances created in that folder yield
      seekable streams (<a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.zippedfile.openwrite.html">ZippedFile.OpenWrite</a> does
      not return a seekable stream).
   </p>
        <p>
      Everytime you create the first instance of a ZipArchive for a given zip file, its
      TempFolder property is initialized to the value of DefaultTempFolder. Thus, if you
      assign a folder to the static DefaultTempFolder property, it will apply to all new
      instances of ZipArchive. If you assign a folder to the TempFolder property, it will
      only affect ZippedFile, ZippedFolder and ZipArchive instances dealing with that zip
      file.
   </p>
        <p>
      If you run the above code while watching your temporary folder using Explorer (hit
      F5 a few times), you'll see appear and disapear filenames like "XFS330fe108-13b8-4ebb-2299-cace5fa0100a.tmp".
      Those files are holding the compressed data until the zip file gets rebuilt. Most
      serious zip libraries allow to use memory instead of a disk folder while zipping.
      For example, the Xceed Zip ActiveX exposes the <a href="http://doc.xceedsoft.com/products/Zip/sources/usetempfile_property.htm">UseTempFile</a> property.
      When set to false, the library stores temp data in memory while building the zip file.
      With Xceed Zip for .NET, you achieve this by setting ZipArchive.DefaultTempFolder
      to <strong><em>new MemoryFolder()</em></strong>. Voilà! You are storing temporary
      data in memory. This is very useful for ASP.NET applications that cannot write on
      disk. And even better: it also works when updating existing zip files. But watch out!
      Don't zip gigabytes of files while using a MemoryFolder. There is a time for a MemoryFolder,
      and there is a time for a DiskFolder.
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=a4ea2021-91ce-482d-a54d-b3dd04f18f2d" />
      </body>
      <title>Zipping: A transactional operation in a non-transactional world</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,a4ea2021-91ce-482d-a54d-b3dd04f18f2d.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,a4ea2021-91ce-482d-a54d-b3dd04f18f2d.aspx</link>
      <pubDate>Wed, 13 Oct 2004 16:18:38 GMT</pubDate>
      <description>&lt;h4&gt;Non-Transactional by defaut
&lt;/h4&gt;
&lt;p&gt;
   The ZIP file format dictates by its nature that the creation of a zip file is a transactional
   operation. We cumulate a list of files to compress, with all metadata information,
   and we create the zip file in a single step, compressing each file sequentially, making
   sure to comply with a storage format that does not leave room for punctual updates.
   Imagine having to change the contents of a single file within a zip file. You have
   to rebuild the zip file from the beginning, by copying untouched files' compressed
   data to a new copy of the zip file, then append the modified file's compressed data,
   and complete the zip file with the new central directory and ending header.
&lt;/p&gt;
&lt;p&gt;
   On the opposite side, changing the contents of a file stored on your hard disk is
   simple. Each file is accessible randomly, and changing one's contents does not require
   moving or updating others. Take this for example:
&lt;/p&gt;
&lt;pre&gt;  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile file = new DiskFile( @"d:\mydata.txt" );

  if( !file.Exists )
    file.Create();

  using( Stream stream = file.OpenWrite( true ) )
  {
    stream.Write( mydata, 0, mydata.Length );
  }&lt;/pre&gt;
&lt;p&gt;
   The operation is atomic on the file. The Xceed FileSystem's goal is to mimic this
   random file access to any possible representation of a file. Thus, exposing compressed
   files stored in a zip file is no simple task. With the above code, if you replace &lt;strong&gt;&lt;em&gt;new
   DiskFile(...)&lt;/em&gt;&lt;/strong&gt; with &lt;strong&gt;&lt;em&gt;new ZippedFile(...)&lt;/em&gt;&lt;/strong&gt;, it
   will work as expected. What you don't see is that only when the stream gets closed
   will the zip file get rebuilt. All data that you write to the stream is compressed
   and stored in a temp file, until the last "modify" operation is completed on that
   zip file. Another example:
&lt;/p&gt;
&lt;pre&gt;  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile file1 = new DiskFile( @"d:\mydata.txt" );
  AbstractFile file2 = new DiskFile( @"d:\mydatatoo.txt" );
  
  if( !file1.Exists )
    file1.Create();
    
  if( !file2.Exists )
    file2.Create();
    
  using( Stream stream1 = file1.OpenWrite( true ) )
  {
    using( Stream stream2 = file2.OpenWrite( true ) )
    {
      stream1.Write( mydata, 0, mydata.Length );
      stream2.Write( mydata, 0, mydata.Length );
    }
  }&lt;/pre&gt;
&lt;p&gt;
   In the atomic world of disk files, both files have no influence on the other. But
   again, replace DiskFile instances with ZippedFiles, and it's another story. The two
   files are stored in a zip file, which can only get rebuilt when the last "modify"
   operation completes, thus when "stream1.Close" is called. Will the above code work?
   Sure! But the zip file will be rebuilt three times. Try it!
&lt;/p&gt;
&lt;pre&gt;  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile zipFile = new DiskFile( @"d:\mydatafiles.zip" );
  AbstractFile file1 = new ZippedFile( zipFile, @"\mydata.txt" );
  AbstractFile file2 = new ZippedFile( zipFile, @"\mydatatoo.txt" );

  if( !file1.Exists )
    file1.Create();

  Console.WriteLine( "Check the zip file with WinZip!" );
  Console.WriteLine( "It should contain one empty file named 'mydata.txt'." );
  Console.ReadLine();

  if( !file2.Exists )
    file2.Create();

  Console.WriteLine( "Check the zip file with WinZip!" );
  Console.WriteLine( "It should contain two empty files now." );
  Console.ReadLine();

  using( Stream stream1 = file1.OpenWrite( true ) )
  {
    using( Stream stream2 = file2.OpenWrite( true ) )
    {
      stream1.Write( mydata, 0, mydata.Length );
      stream2.Write( mydata, 0, mydata.Length );
    }

    Console.WriteLine( "Check the zip file with WinZip!" );
    Console.WriteLine( "It still contains two empty files." );
    Console.ReadLine();
  }

  Console.WriteLine( "Check the zip file with WinZip!" );
  Console.WriteLine( "Now it contains both files with their data." );
  Console.ReadLine();&lt;/pre&gt;
&lt;p&gt;
   The first call to &lt;strong&gt;&lt;em&gt;file1.Create&lt;/em&gt;&lt;/strong&gt; increments the "modify" count
   to 1, then down to 0, so the zip file is built, containing an empty file. After the
   second call to &lt;strong&gt;&lt;em&gt;Create&lt;/em&gt;&lt;/strong&gt;, the zip file is again rebuilt, containing
   two empty files. When the first call to &lt;strong&gt;&lt;em&gt;OpenWrite&lt;/em&gt;&lt;/strong&gt; is made,
   the "modify" count gets up to 1. After the second call to &lt;strong&gt;&lt;em&gt;OpenWrite&lt;/em&gt;&lt;/strong&gt;,
   it's up to 2. Then &lt;strong&gt;&lt;em&gt;stream2&lt;/em&gt;&lt;/strong&gt; is closed, and the count gets
   down to 1. Finally &lt;strong&gt;&lt;em&gt;stream1&lt;/em&gt;&lt;/strong&gt; is closed, the count gets to
   0, and the zip file is rebuilt, containing two files with compressed data.
&lt;/p&gt;
&lt;p&gt;
   In this simple example, the cost is not that much. Let's imagine worse:
&lt;/p&gt;
&lt;pre&gt;  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile zipFile = new DiskFile( @"d:\mydatafiles.zip" );

  if( zipFile.Exists )
    zipFile.Delete();

  for( int i=0; i&amp;lt;1000; i++ )
  {
    Console.WriteLine( "Loop {0}", i );
    AbstractFile file = new ZippedFile( zipFile, @"\data" + i.ToString() + ".txt" );

    if( !file.Exists ) 
      file.Create(); 

    using( Stream stream = file.OpenWrite( true ) ) 
    {
      stream.Write( mydata, 0, mydata.Length ); 
    }
  }&lt;/pre&gt;
&lt;p&gt;
   If you try this, you'll notice that each loop takes more time than the previous. Actually,
   when I tried this, I wasn't patient enough to wait until completion. The zip file
   would get rebuilt 2000 times, with more and more files already in the zip file. This
   is plainly unacceptable.
&lt;/p&gt;
&lt;h4&gt;Transactional on demand
&lt;/h4&gt;
&lt;p&gt;
   That's where the &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.ibatchupdateable.html"&gt;IBatchUpdateable&lt;/a&gt; interface
   comes to the rescue. It contains two simple methods: &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.ibatchupdateable.beginupdate.html"&gt;BeginUpdate&lt;/a&gt; and &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.ibatchupdateable.endupdate.html"&gt;EndUpdate&lt;/a&gt;.
   Any AbstractFile or AbstractFolder's derived class can implement this interface, though
   you can limit this to the root folder. Once BeginUpdate is called, the implementor
   can hold any modifications to the underlying media until EndUpdate is called. &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.ziparchive.html"&gt;ZipArchive&lt;/a&gt;,
   which represents the root ZippedFolder for a zip file, implement this interface. In
   short, BeginUpdate artificially increments the "modify" count to 1, and EndUpdate
   decrements it. If it gets to 0, the underlying zip file is rebuilt. You can call BeginUpdate
   and EndUpdate as many times as you want, but every call to BeginUpdate must be matched
   with a call to EndUpdate. The above code could now look like this:
&lt;/p&gt;
&lt;pre&gt;  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile zipFile = new DiskFile( @"d:\mydatafiles.zip" );
  ZipArchive zip = new ZipArchive( zipFile );

  if( zipFile.Exists )
    zipFile.Delete();

  zip.BeginUpdate();

  try
  {       
    for( int i=0; i&amp;lt;1000; i++ )
    {
      Console.WriteLine( "Loop {0}", i );
      AbstractFile file = new ZippedFile( zipFile, @"\data" + i.ToString() + ".txt" );

      if( !file.Exists ) 
        file.Create(); 

      using( Stream stream = file.OpenWrite( true ) ) 
      {
        stream.Write( mydata, 0, mydata.Length ); 
      }
    }
  }
  finally
  {
    zip.EndUpdate();
  }&lt;/pre&gt;
&lt;p&gt;
   Now that's better. On my machine, this takes a few seconds.
&lt;/p&gt;
&lt;p&gt;
   The FileSystem's main goal was to offer a unique and consistent interface for manipulating
   any kind of file or folder. That's why we decided that ZippedFile and ZippedFolder
   were to be non-transactional by default, even though in most cases, it will end-up
   producing less efficient code. It's the user's job to call BeginUpdate before modifying
   the zip file, and EndUpdate once completed, to achieve better performance.
&lt;/p&gt;
&lt;p&gt;
   By the way, for those who like the &lt;strong&gt;&lt;em&gt;using( IDisposable )&lt;/em&gt;&lt;/strong&gt; pattern
   in C#, you can use the &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.autobatchupdate.html"&gt;AutoBatchUpdate&lt;/a&gt; class
   like this:
&lt;/p&gt;
&lt;pre&gt;  byte[] mydata = System.Text.Encoding.Default.GetBytes( "This is important!" );
  AbstractFile zipFile = new DiskFile( @"d:\mydatafiles.zip" );
  ZipArchive zip = new ZipArchive( zipFile );

  if( zipFile.Exists )
    zipFile.Delete();

  using( AutoBatchUpdate auto = new AutoBatchUpdate( zip ) )
  {
    for( int i=0; i&amp;lt;1000; i++ )
    {
      Console.WriteLine( "Loop {0}", i );
      AbstractFile file = new ZippedFile( zipFile, @"\data" + i.ToString() + ".txt" );

      if( !file.Exists ) 
        file.Create(); 

      using( Stream stream = file.OpenWrite( true ) ) 
      {
        stream.Write( mydata, 0, mydata.Length ); 
      }
    }
  }&lt;/pre&gt;
&lt;p&gt;
   The AutoBatchUpdate implements IDisposable, making sure to call BeginUpdate on the
   object at construction, and EndUpdate when disposed. What's even better is that you
   can pass any &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.filesystemitem.html"&gt;FileSystemItem&lt;/a&gt;:
   it will do nothing if the item's &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.filesystem.filesystemitem.rootfolder.html"&gt;RootFolder&lt;/a&gt;&amp;nbsp;does
   not implement IBatchUpdateable. Thus, you can use AutoBatchUpdate without having to
   know if the AbstractFile or AbstractFolder you're working with implements IBatchUpdateable
   or not.
&lt;/p&gt;
&lt;h4&gt;Temp storage
&lt;/h4&gt;
&lt;p&gt;
   Now, it's good to know that when using BeginUpdate and EndUpdate, the zip file is
   rebuilt only at the very last moment, but where goes the compressed data I'm writing
   to the streams? It must be stored somewhere, right? The ZipArchive class exposes two
   important properties: &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.ziparchive.defaulttempfolder.html"&gt;DefaultTempFolder&lt;/a&gt; (static)
   and &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.ziparchive.tempfolder.html"&gt;TempFolder&lt;/a&gt;.
   By default, the first is equal to &lt;strong&gt;&lt;em&gt;new DiskFolder( System.IO.Path.GetTempPath()
   )&lt;/em&gt;&lt;/strong&gt;, the temp folder of the currently logged-in user. You can assign to
   it any AbstractFolder, as long as AbstractFile instances created in that folder yield
   seekable streams (&lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.zip.zippedfile.openwrite.html"&gt;ZippedFile.OpenWrite&lt;/a&gt; does
   not return a seekable stream).
&lt;/p&gt;
&lt;p&gt;
   Everytime you create the first instance of a ZipArchive for a given zip file, its
   TempFolder property is initialized to the value of DefaultTempFolder. Thus, if you
   assign a folder to the static DefaultTempFolder property, it will apply to all new
   instances of ZipArchive. If you assign a folder to the TempFolder property, it will
   only affect ZippedFile, ZippedFolder and ZipArchive instances dealing with that zip
   file.
&lt;/p&gt;
&lt;p&gt;
   If you run the above code while watching your temporary folder using Explorer (hit
   F5 a few times), you'll see appear and disapear filenames like "XFS330fe108-13b8-4ebb-2299-cace5fa0100a.tmp".
   Those files are holding the compressed data until the zip file gets rebuilt. Most
   serious zip libraries allow to use memory instead of a disk folder while zipping.
   For example, the Xceed Zip ActiveX exposes the &lt;a href="http://doc.xceedsoft.com/products/Zip/sources/usetempfile_property.htm"&gt;UseTempFile&lt;/a&gt; property.
   When set to false, the library stores temp data in memory while building the zip file.
   With Xceed Zip for .NET, you achieve this by setting ZipArchive.DefaultTempFolder
   to &lt;strong&gt;&lt;em&gt;new MemoryFolder()&lt;/em&gt;&lt;/strong&gt;. Voil&amp;#224;! You are storing temporary
   data in memory. This is very useful for ASP.NET applications that cannot write on
   disk. And even better: it also works when updating existing zip files. But watch out!
   Don't zip gigabytes of files while using a MemoryFolder. There is a time for a MemoryFolder,
   and there is a time for a DiskFolder.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=a4ea2021-91ce-482d-a54d-b3dd04f18f2d" /&gt;</description>
      <category>FileSystem;Zip</category>
    </item>
  </channel>
</rss>