Wednesday, October 05, 2005

I'm glad to announce that Xceed FTP for .NET 2.1 is now available for download. 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.

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:

// A file on disk
AbstractFile first = new DiskFile( @"d:\FileSystem.txt" );
 
// Another file on disk
AbstractFile second = new DiskFile( @"c:\temp\AnotherFileSystem.txt" );
 
// A file compressed in a zip file on disk
AbstractFile third = new ZippedFile( 
  new DiskFile( @"c:\temp\data.zip" ), "FileSystemInAZip.txt" );;
 
// A file in the isolated storage
AbstractFile fourth = new IsolatedFile( "Isolated.txt" );
 
// A file in memory (random name)
AbstractFile fifth = new MemoryFile();
 
// A file compressed in a zip file in memory
AbstractFile sixth = new ZippedFile( 
  new MemoryFile(), "VolatileFileSystem.txt" );

You can copy files around very easily:

// Copying the first file anywhere else is always the same!
first.CopyTo( second, true );
first.CopyTo( third, true );
first.CopyTo( fourth, true );
first.CopyTo( fifth, true );
first.CopyTo( sixth, true );

And accessing the contents of any file is always the same:

private void DisplayTextFile( AbstractFile file )
{
  Console.WriteLine( "Displaying the contents of {0}, which is a {1}.", 
    file.FullName,
    file.GetType().Name );
 
  using( StreamReader reader = new StreamReader( file.OpenRead() ) )
  {
    string line;
 
    while( ( line = reader.ReadLine() ) != null )
    {
      Console.WriteLine( line );
    }
  }
 
  Console.WriteLine();
}

// Displaying the contents of those files is always the same!
DisplayTextFile( first );
DisplayTextFile( second );
DisplayTextFile( third );
DisplayTextFile( fourth );
DisplayTextFile( fifth );
DisplayTextFile( sixth );

And why not finish this demonstration by deleting the files we just created.

// And finally, deleting files is the same!
second.Delete();
third.Delete();
fourth.Delete();
fifth.Delete();
sixth.Delete();

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.

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!

AbstractFile seventh = new FtpFile( 
  new FtpConnection( "localhost" ), @"\RemoteFileSystem.txt" );
 
first.CopyTo( seventh, true );
 
DisplayTextFile( seventh );
 
seventh.Delete();

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.

using( FtpConnection connection = new FtpConnection( "ftp.xceed.com" ) )
{
  connection.TraceWriter = Console.Out;
 
  FtpFolder root = new FtpFolder( connection );
 
  foreach( AbstractFile file in root.GetFiles( false, "*.txt" ) )
  {
    DisplayTextFile( file );
  }
}

If we comment out the "Console.WriteLine( line );" line in "DisplayTextFile", we can see the FTP conversation that occurred for the above code:

Connected to 66.46.177.250:21 on 9/27/2005 @ 2:24:54 PM
< 220 Serv-U FTP Server v6.0 for WinSock ready...
> USER anonymous
< 331 User name okay, please send complete E-mail address as password.
> PASS *****
< 230 User logged in, proceed.
> PWD
< 257 "/" is current directory.
> CWD /
< 250 Directory changed to /
> CWD /
< 250 Directory changed to /
> CWD /
< 250 Directory changed to /
> TYPE A
< 200 Type set to A.
> PASV
< 227 Entering Passive Mode (66,46,177,250,6,238)
> LIST
Data connection established with 66.46.177.250:1774 on 9/27/2005 @ 2:24:56 PM
< 150 Opening ASCII mode data connection for /bin/ls.
< 226-Maximum disk quota limited to Unlimited kBytes
< Used disk quota 0 kBytes, available Unlimited kBytes
< 226 Transfer complete.
Displaying the contents of \FileSystem.txt, which is a FtpFile.
> CWD /
< 250 Directory changed to /
> TYPE I
< 200 Type set to I.
> PASV
< 227 Entering Passive Mode (66,46,177,250,6,240)
> RETR FileSystem.txt
Data connection established with 66.46.177.250:1776 on 9/27/2005 @ 2:24:57 PM
< 150 Opening BINARY mode data connection for FileSystem.txt (1198 Bytes).
< 226-Maximum disk quota limited to Unlimited kBytes
< Used disk quota 0 kBytes, available Unlimited kBytes
< 226 Transfer complete.

Displaying the contents of \appnote.txt, which is a FtpFile.
> CWD /
< 250 Directory changed to /
> TYPE I
< 200 Type set to I.
> PASV
< 227 Entering Passive Mode (66,46,177,250,6,246)
> RETR appnote.txt
Data connection established with 66.46.177.250:1782 on 9/27/2005 @ 2:24:58 PM
< 150 Opening BINARY mode data connection for appnote.txt (109785 Bytes).
< 226-Maximum disk quota limited to Unlimited kBytes
< Used disk quota 0 kBytes, available Unlimited kBytes
< 226 Transfer complete.

> QUIT
Disconnected from 66.46.177.250:21 on 9/27/2005 @ 2:25:04 PM

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).

Now what happens if I try to open two files at the same time, like this?

using( FtpConnection connection = new FtpConnection( "ftp.xceed.com" ) )
{
  connection.TraceWriter = Console.Out;
 
  AbstractFile first = new FtpFile( connection, @"\FileSystem.txt" );
  AbstractFile second = new FtpFile( connection, @"\appnote.txt" );
 
  using( Stream firstStream = first.OpenRead() )
  {
    using( Stream secondStream = second.OpenRead() )
    {
      // In an FTP conversation with an FTP server, only one command
      // at a time can be pending. Here, we clearly have two files
      // open at the same time on the same FTP server. How? Each file
      // has its own connection to the FTP server!
    }
  }
}

The FtpConnection object will create extra command channel connections as required. The output shows two command channel connections were made:

Connected to 66.46.177.250:21 on 9/27/2005 @ 2:38:06 PM
< 220 Serv-U FTP Server v6.0 for WinSock ready...
> USER anonymous
< 331 User name okay, please send complete E-mail address as password.
> PASS *****
< 230 User logged in, proceed.
> CWD /
< 250 Directory changed to /
> TYPE A
< 200 Type set to A.
> PASV
< 227 Entering Passive Mode (66,46,177,250,10,53)
> LIST
Data connection established with 66.46.177.250:2613 on 9/27/2005 @ 2:38:07 PM
< 150 Opening ASCII mode data connection for /bin/ls.
< 226-Maximum disk quota limited to Unlimited kBytes
<     Used disk quota 0 kBytes, available Unlimited kBytes
< 226 Transfer complete.
> CWD /
< 250 Directory changed to /
> TYPE I
< 200 Type set to I.
> PASV
< 227 Entering Passive Mode (66,46,177,250,10,54)
> RETR FileSystem.txt
Data connection established with 66.46.177.250:2614 on 9/27/2005 @ 2:38:08 PM
< 150 Opening BINARY mode data connection for FileSystem.txt (1198 Bytes).
Connected to 66.46.177.250:21 on 9/27/2005 @ 2:38:08 PM
< 220 Serv-U FTP Server v6.0 for WinSock ready...
> USER anonymous
< 226-Maximum disk quota limited to Unlimited kBytes
<     Used disk quota 0 kBytes, available Unlimited kBytes
< 226 Transfer complete.
< 331 User name okay, please send complete E-mail address as password.
> PASS *****
< 230 User logged in, proceed.
> CWD /
< 250 Directory changed to /
> TYPE I
< 200 Type set to I.
> PASV
< 227 Entering Passive Mode (66,46,177,250,10,55)
> RETR appnote.txt
Data connection established with 66.46.177.250:2615 on 9/27/2005 @ 2:38:09 PM
< 150 Opening BINARY mode data connection for appnote.txt (109785 Bytes).
< 426-Maximum disk quota limited to Unlimited kBytes
<     Used disk quota 0 kBytes, available Unlimited kBytes
< 426 Data connection closed, file transfer appnote.txt aborted.
> QUIT
Disconnected from 66.46.177.250:21 on 9/27/2005 @ 2:38:13 PM
> QUIT
Disconnected from 66.46.177.250:21 on 9/27/2005 @ 2:38:13 PM

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.

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.

AbstractFolder source = new DiskFolder( @"d:\Data" );
 
AbstractFolder localDest = new ZipArchive( 
  new DiskFile( @"d:\temp\local.zip" ) );
 
AbstractFolder remoteDest = new ZipArchive(
  new FtpFile( new FtpConnection( "localhost" ), @"remote.zip" ) );
 
// Copying is the same, no matter what is the destination
// file or folder.
source.CopyTo( localDest, true );
source.CopyTo( remoteDest, true );

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.

AbstractFolder localSource = new ZipArchive( 
  new DiskFile( @"d:\temp\local.zip" ) );
 
AbstractFolder remoteSource = new ZipArchive(
  new FtpFile( new FtpConnection( "localhost" ), @"remote.zip" ) );
 
AbstractFolder dest = new DiskFolder( @"d:\restored" );
 
// Unzipping text files from any source is the same!
localSource.CopyFilesTo( dest, true, true, "*.txt" );
remoteSource.CopyFilesTo( dest, true, true, "*.txt" );

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!


.NET | FileSystem | FTP | Zip

10/5/2005 3:09:39 PM (Eastern Daylight Time, UTC-04:00)  #   
 Tuesday, September 27, 2005

I just discovered this amasing little gem through Scott. It's called PureText, and what it does is convert the clipboard's formatted text to unformatted text before pasting it to the current window.

By default, it binds to the Win-V key sequence. For example, you select some text on a web page, then press Win-V in a new email, and it will paste the unformatted text, without the web page's formatting. I already can see great use when pasting code from VS.NET! It will save me extra steps.



9/27/2005 9:39:26 AM (Eastern Daylight Time, UTC-04:00)  #   
 Thursday, September 15, 2005

Yesterday's sessions I attented were rather disapointing. I went to many WinFS sessions, and I realize that except for ADO.NET integration, the product didn't change much. It's still the same data store, with data types, schemes, relations, and a searching APIs, or browsing APIs should I say, as I learned it wasn't mere searching… yeah, right.

I guess this year's PDC is less about listening to Microsoft, and more about installing the bits as soon as possible and play with them. Even though the bits are related to the same products as two years ago, they are more stable, and the interface has less chances to change until release.

I'm already shopping for a new machine to install Vista on. I was thinking about a laptop, as I don't have one. What do you think? Should I stick to a desktop machine?

Tags:



9/15/2005 2:04:30 PM (Eastern Daylight Time, UTC-04:00)  #   
 Wednesday, September 14, 2005

Yesterday, I went to the Mono meeting. Miguel and his crew were not prepared at all. The room was too small (that's a good sign though), the projector didn't work with two of the laptops, and Miguel ended up doing Q&A for two hours, only showing glimpses of the applications he wanted to demonstrate. I left before the end. I wanted to talk with Miguel, but I guess I'll use the email channel.

I've always been curious about Mono, because I would feel great proud seeing the software I conceived and developed being run on more and more computers. It's not because I'm a Linux advocate. I'm a "liberty-of-choice" advocate. I used to be a Windows developer (WIN32, COM). I'm now a .NET developer, whatever the platform. Why would I complain on seeing Xceed Zip for .NET work on Linux?

Tags:


Mono | PDC05

9/14/2005 2:06:55 PM (Eastern Daylight Time, UTC-04:00)  #   
 Tuesday, September 13, 2005

The keynote is now over, I just finished a speedy lunch (burp), and I'm sitting in Halls C&D for the "Lap around the Windows Communication Foundation". I'm eager to learn more about the latest state of the "Indigo" part of WinFX.

I'm left with a bitter taste about the earlier keynote. The presentation wasn't that much dynamic (except for Don Box, Anders Hejlsberg, Chris Anderson and Scott Guthrie), and the chance to get a i-mate JASJAR for only 149$, which ended up on a very sad note: 5 minutes after getting out of the keynote, there were none left… all sold out. That means you had to leave the keynote in the middle to get one, even though Jim Allchin told us there were no need to rush out. You can have an outstanding presentation, if the conclusion is disappointment, it ends up useless. This promotion was a bad idea. Someone should have told Jim!

Speaking of Jim Allchin, I thought he wasn't in a good day. He often hesitated and was searching his text a lot. Too bad because I respect him a lot.

Avalon and Indigo, I'm sorry, Windows Presentation Foundation and Windows Communication Foundation are too close from releasing to be exciting announcements this year. I feel the concepts I saw two years ago at PDC 2003 didn't change a lot since then. At most, the interfaces have changed a little bit, Visual Studio .NET has improved to expose those functionalities better, but the rest tastes like reheated contents.

I hope to get more new stuff during sessions.

Tags:



9/13/2005 5:09:47 PM (Eastern Daylight Time, UTC-04:00)  #   
 Monday, September 12, 2005

I'm currently in the plane en route for the PDC. I just spent 15 minutes trying to write my first PDC blog entry using Ink Recognition on Xceed's TabletPC. I must admit I'm not ready for this. I made many mistakes while writing, and trying to fix those errors made me only more bitter about the technology. On the other side, I'm currently writing with very little room for my arms since the guy in front of me decided to lay down and moved his seat back. Planes are not for laptops nor tablet PCs. Sure, I would have more room in first class, but I can't afford it.

I would have used my Pocket PC for blogging, has it not been out of power because I forgot the battery charger at work. A colleague travelling with me brought it, but I did not have time to recharge it yet. I'm getting pretty fast in writing with it, though I use the keyboard mode, not the handwriting.

I don't know what to expect of this PDC yet. I didn't have time to prepare my schedule. I just hope to see a lot of WinFS content. I'll probably go to the Mono meeting Tuesday, as the agenda Miguel has put forth is really promising. I can't hide that I will want to talk about Xceed Zip for .NET to the other attendees. Too bad Xceed FTP for .NET only works on the Windows platform. I tried it a few weeks ago on Linux, and it fails, as expected, because the SSL support requires some Crypt32 calls. Even if you don't need SSL, some initialization code is messing up. I'll add to my agenda to look at how to overcome such limitations without having to provide separate assemblies to Windows and non-Windows customers. I may just find my answer at the Mono meeting.

The main reason why I'm a little late on my preparation isn't my last two weeks of vacation. Actually, it should have gave me some spare time. Instead, I was busy reinstalling my home computer. Just before leaving for vacation, the hard drive crashed. 9 months old, and it died on me. Actually, it started dying, as the drive was fully seekable, but read errors were present all over the disks. I could not read it from Windows anymore. None of my data was accessible. And guess what? Yup, you're right, I didn't have a decent backup. The only backup I had was 9 months old, when I upgraded my machine. I could live without my latest emails. I could live without my Word and Excel documents, so could my wife. I could live without my recently ripped music library, as I had an exact and full quality copy on my Dell DJ. No, the bummer wasn't all that. The bummer was all my digital pictures. I had no backup. None. Well, only a few printed photos. Yikes!

I first tried SpinRite, to try to recover lost sectors, but the task was mostly vain, and it took three days to scan 3% of my 160 gigs hard drive (yawn). Then I searched for a software that could try to locate files and folders on readable sectors. It was like searching for a needle in a haystack. I had to try one, so I went for Restorer 2000. I could try it with files smaller than 64kb, and it would list all found contents. I could see all my digital gallery, so I bought it and tried to recover the most I could. Turns out most bad sectors ended up on system files or my music library. I could recover everything else, except my Money database and backup. Restorer 2000 proved a life saver. The good thing about it is that you can configure how many times it will try to read a bad sector. Since I knew there were a lot and SpinRite could not even recover them, I set this option to 1, to save me time. In an afternoon, I had everything important recovered, except for the Outlook database I forgot to locate. Now that I returned the defective hard drive to Dell, it's too late.

The hard drive was a Maxtor, and I hear a lot of bad things about them. I'm glad Dell replaced it with a Seagate. And now, I've learned my lesson the hard way: back-up, and back-up often. I'll probably buy myself a second hard drive, do regular drive to drive backups, and occasional DVD backups.



9/12/2005 5:53:30 PM (Eastern Daylight Time, UTC-04:00)  #   
 Thursday, September 08, 2005

It's been a long time since I blogged. I'm currently in vacation, that's mainly why. But I'm also preparing myself for the PDC 05. Like many other bloggers that will attend the PDC, I plan to blog every day about my experience.

Until then, back to my last days of vacation!



9/8/2005 11:16:30 PM (Eastern Daylight Time, UTC-04:00)  #   
 Friday, August 12, 2005

I just upgraded our blog engine to dasBlog 1.8. You can learn more here.

Tell me if you see anything strange.

Thank you Scott, Omar, and the rest of the project members.



8/12/2005 3:35:55 PM (Eastern Daylight Time, UTC-04:00)  #