I'm trying to fetch a text file from an FTP server, then read it line by line, adding each line to a list.
My code seems to fit the standard pattern for this:
var response = (FtpWebResponse)request.GetResponse();
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
string line;
while((line = reader.ReadLine()) != null)
{
lines.Add(line);
}
}
}
But, for some reason, when reader.ReadLine() is called on the very last line of the file, it throws an exception, saying "Cannot access a disposed object".
This is really weirding me out. If I remember correctly, the final line of a stream when there is no further data is null, right?
In addition (while I'm not certain about this), this only seems to be happening locally; the live version of this service seems to be pootling along fine (albeit with some issues I'm trying to get to the bottom of). I certainly don't see this issue in my logs.
Anyone have an ideas?
EDIT: Here's the full text of the exception.
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.FtpDataStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadLine()
at CENSORED.CatalogueJobs.Common.FtpFileManager.ReadFile(String fileName, String directory) in C:\\Projects\\CENSORED_CatalogueJobs\\CENSORED.CatalogueJobs.Common\\FtpFileManager.cs:line 104
at CENSORED.CatalogueJobs.CENSOREDDispatchService.CENSOREDDispatchesProcess.<Process>d__12.MoveNext() in C:\\Projects\\CENSORED_CatalogueJobs\\CENSORED.CatalogueJobs.CENSOREDDispatches\\CENSOREDDispatchesProcess.cs:line 95"
Type is "System.ObjectDisposedException". Sorry for censorship, exception contains my client's name.
EDIT 2: Here's the code now, after being expanded out and removing a layer of usings (I think I've done it right).
var response = (FtpWebResponse)request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
string line = reader.ReadLine();
while(line != null)
{
lines.Add(line);
line = reader.ReadLine();
}
}
EDIT 3: A slightly more wide view of the code (temporarily reverted for my sanity). This is essentially everything in the function.
var request = (FtpWebRequest)WebRequest.Create(_settings.Host + directory + fileName);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(_settings.UserName, _settings.Password);
request.UsePassive = false;
request.UseBinary = true;
var response = (FtpWebResponse)request.GetResponse();
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
string line;
while((line = reader.ReadLine()) != null)
{
lines.Add(line);
}
}
}