Tuesday, June 15, 2010

Reading a Unix file using C#.Net

private void button1_Click(object sender, EventArgs e)
{
MyFtp ftp = new MyFtp("hostname", "username", "password");
string buffer = string.Empty;
string x;
ftp.OpenFile("filepath", AccessMode.Read, TransferMode.Ascii);

while (ftp.ReadFile(out buffer))
{
x = buffer;
}

ftp.CloseFile();
ftp.Close();
}


// Wininet.cs
using System;
using System.Text;
using System.Runtime.InteropServices;

namespace FTP
{
///
/// Summary description for WinInet.
///

internal sealed class WinInet
{
public const int INTERNET_OPEN_TYPE_PRECONFIG = 0;
public const int INTERNET_OPEN_TYPE_DIRECT = 1;
public const int INTERNET_OPEN_TYPE_PROXY = 3;
public const short INTERNET_DEFAULT_FTP_PORT = 21;
public const int INTERNET_SERVICE_FTP = 1;
public const int FTP_TRANSFER_TYPE_ASCII = 0x01;
public const int FTP_TRANSFER_TYPE_BINARY = 0x02;
public const int GENERIC_WRITE = 0x40000000;
public const int GENERIC_READ = unchecked((int)0x80000000);
public const int MAX_PATH = 260;

[DllImport("wininet.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern IntPtr InternetOpen(
string lpszAgent,
int dwAcessType,
string lpszProxyName,
string lpszProxyBypass,
int dwFlags);

[DllImport("wininet.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern IntPtr InternetConnect(
IntPtr hInternet,
string lpszServerName,
short nServerPort,
string lpszUserName,
string lpszPassword,
int dwService,
int dwFlags,
ref int dwContext);

[DllImport("wininet.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern bool FtpGetCurrentDirectory(
IntPtr hConnect,
StringBuilder lpszCurrentDirectory,
ref int lpdwCurrentDirectory);

[DllImport("wininet.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern bool FtpSetCurrentDirectory(
IntPtr hConnect,
string lpszCurrentDirectory);

[DllImport("wininet.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern IntPtr FtpOpenFile(
IntPtr hConnect,
string lpszFileName,
int dwAccess,
int dwFlags,
out int dwContext);

[DllImport("wininet.dll", SetLastError = true)]
public static extern bool InternetWriteFile(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int dwNumberOfBytesToWrite,
out int lpdwNumberOfBytesWritten);

[DllImport("wininet.dll", SetLastError = true)]
public static extern bool InternetReadFile(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int dwNumberOfBytesToRead,
out int lpdwNumberOfBytesRead
);

[DllImport("wininet.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern bool InternetCloseHandle(IntPtr hInternet);

[DllImport("wininet.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern bool FtpPutFile(
IntPtr hConnect,
string lpszLocalFile,
string lpszNewRemoteFile,
int dwFlags,
out int dwContext);

[DllImport("wininet.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern bool FtpGetFile(
IntPtr hConnect,
string lpszRemoteFile,
string lpszLocalFile,
bool failIfExists,
int dwFlagsAttributes,
int dwFlags,
out int dwContext);

[DllImport("wininet.dll", CharSet = CharSet.Auto,
SetLastError = true)]

private WinInet()
{
}
}
}


// SimpleFtp.cs
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace FTP
{
[Flags()]
public enum AccessMode
{
Read = WinInet.GENERIC_READ,
Write = WinInet.GENERIC_WRITE,
}

public enum TransferMode
{
Ascii = WinInet.FTP_TRANSFER_TYPE_ASCII,
Binary = WinInet.FTP_TRANSFER_TYPE_BINARY,
}

///
/// Summary description for SimpleFTP.
///

public sealed class MyFtp : IDisposable
{
private IntPtr internet;
private IntPtr connection;
private IntPtr fileHandle;
private int context;

private const int BUFFER_SIZE = 2048;

public MyFtp(string host, string userName, string password)
{
internet = WinInet.InternetOpen(
null,
WinInet.INTERNET_OPEN_TYPE_DIRECT,
null,
null,
0);

if (internet == IntPtr.Zero)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}

connection = WinInet.InternetConnect(
this.internet,
host,
WinInet.INTERNET_DEFAULT_FTP_PORT,
userName,
password,
WinInet.INTERNET_SERVICE_FTP,
0,
ref this.context);

if (connection == IntPtr.Zero)
{
WinInet.InternetCloseHandle(this.internet);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}

~SimpleFtp()
{
this.CleanUp();
}

void IDisposable.Dispose()
{
this.CleanUp();
GC.SuppressFinalize(this);
}

public string CurrentDirectory
{
get
{
StringBuilder path = new StringBuilder(260);
int bufferSize = path.Capacity;

if (!WinInet.FtpGetCurrentDirectory(this.connection,
path, ref bufferSize))
{
throw new
Win32Exception(Marshal.GetLastWin32Error());
}
return path.ToString();
}
set
{
if (!WinInet.FtpSetCurrentDirectory(this.connection,
value))
{
throw new
Win32Exception(Marshal.GetLastWin32Error());
}
}
}

public void Close()
{
((IDisposable)this).Dispose();
}

public void OpenFile(string fileName, AccessMode access,
TransferMode mode)
{
this.fileHandle = WinInet.FtpOpenFile(this.connection,
fileName, (int)access, (int)mode, out this.context);
if (this.fileHandle == IntPtr.Zero)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}

public void CloseFile()
{
if (this.fileHandle != IntPtr.Zero)
{
if (WinInet.InternetCloseHandle(this.fileHandle))
{
this.fileHandle = IntPtr.Zero;
}
else
{
throw new
Win32Exception(Marshal.GetLastWin32Error());
}
}
}

public int WriteFile(string buffer)
{
byte[] bytes = new ASCIIEncoding().GetBytes(buffer);
return this.WriteFile(bytes);
}

public int WriteFile(byte[] buffer)
{
int byteCount;
if (!WinInet.InternetWriteFile(this.fileHandle, buffer,
buffer.Length, out byteCount))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return byteCount;
}

public bool ReadFile(out string buffer)
{
// clear the buffer...
buffer = string.Empty;

// read from the file
int bytesRead;
byte[] readBuffer = new byte[SimpleFtp.BUFFER_SIZE];
bool success = WinInet.InternetReadFile(this.fileHandle,
readBuffer, readBuffer.Length, out bytesRead);

// the call failed!
if (!success)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}

// we got some data, so convert it for the return...
if (bytesRead != 0)
{
buffer = Encoding.ASCII.GetString(readBuffer, 0,
bytesRead);
}

return (bytesRead != 0) ? true : false;
}

public bool ReadFile(byte[] buffer)
{
int bytesRead;
bool success = WinInet.InternetReadFile(this.fileHandle,
buffer, buffer.Length, out bytesRead);
if (!success)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return (bytesRead != 0) ? true : false;
}

public void GetFile(string localFile, string remoteFile, bool
fail)
{
GetFile(localFile, remoteFile, TransferMode.Ascii, fail);
}

public void GetFile(string localFile, string remoteFile,
TransferMode mode, bool fail)
{
if (!WinInet.FtpGetFile(connection, remoteFile, localFile,
fail, 0, (int)mode, out context))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}

public void PutFile(string localFile, string remoteFile)
{
this.PutFile(localFile, remoteFile, TransferMode.Ascii);
}

public void PutFile(string localFile, string remoteFile,
TransferMode mode)
{
if (!WinInet.FtpPutFile(this.connection, localFile,
remoteFile, (int)mode, out this.context))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}

private void CleanUp()
{
if (this.fileHandle != IntPtr.Zero)
{
WinInet.InternetCloseHandle(this.fileHandle);
}

if (this.connection != IntPtr.Zero)
{
WinInet.InternetCloseHandle(this.connection);
}

if (this.internet != IntPtr.Zero)
{
WinInet.InternetCloseHandle(this.internet);
}
}
}
}