C# BinaryReader "stream does not support seek operations"

binaryreader, c#, ftpwebrequest

Solution

You shouldn't rely on `Stream.Length`, its possible it could be wrong. You just need to read all of the bytes in a while loop until there are no more bytes to read.

MemoryStream ms = new MemoryStream();
byte[] chunk = new byte[4096];
int bytesRead;
while ((bytesRead = downloadStream.Read(chunk, 0, chunk.Length)) > 0)
{
     ms.Write(chunk, 0, bytesRead);
}

From there, all the read data is in the `MemoryStream`, and you can initialize the `BinaryReader` with that.

Problem

I am trying to download files from an ftp server using C# and ftpwebrequest. I can get the bytes using BinaryReader, but when I try to read the stream using br.ReadBytes(int), I get an error that BinaryReader does not support seek operations. Does anyone know how best to read the bytes so I can write them to a file? Here's the full method: ``` public void DownloadFile(String fileName) { Logger.Info("starting to download file: " + fileName); try { var downloadFileRequest = (FtpWebRequest)WebRequest.Create(FtpServer + "//" + fileName); downloadFileRequest.Credentials = new NetworkCredential(FtpUsername,FtpPassword); downloadFileRequest.Method = WebRequestMethods.Ftp.DownloadFile; downloadFileRequest.UseBinary = true; ServicePoint sp = downloadFileRequest.ServicePoint; sp.ConnectionLimit = 2; Logger.Info("getting ftp response for download file for " + fileName); try { var downloadResponse = (FtpWebResponse)downloadFileRequest.GetResponse(); Logger.Info("getting ftp response stream for " + fileName); try { Stream downloadStream = downloadResponse.GetResponseStream(); Logger.Info("File Download status: {0}", downloadResponse.StatusDescription.Trim()); Logger.Info("getting binary reader for " + fileName); try { using ( var downloadReader = new BinaryReader(downloadStream)) { String destinationFilePath= Path.Combine(LocalFolder, fileName); Logger.Info("writing response stream to " + destinationFilePath); try { using (var downloadWriter = new BinaryWriter(System.IO.File.Open(destinationFilePath, FileMode.Create))) { downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length)); } Logger.Info("successfully saved " + destinationFilePath); } catch (Exception ex) { Logger.Info("could not save " + destinationFilePath+ " b/c: " + ex.Message); } } } catch (Exception ex) { Logger.Info("could not read " + fileName + " b/c: " + ex.Message); } } catch (Exception ex) { Logger.Info("could not open download stream for " + fileName + " b/c: " + ex.Message); } finally { downloadResponse.Close(); } } catch (Exception ex) { Logger.Info("could not get ftp response stream for " + fileName + " b/c: " + ex.Message); } } catch (Exception ex) { Logger.Info("could not get ftp request stream for " + fileName + " b/c: " + ex.Message); } } ``` This runs as part of an ongoing service, so I don't want to throw errors that would stop the service. Instead, I'm writing to a log. Here are the contents of the log for this method: ``` 2009-10-07 16:33:29.1421|INFO|xxx.Web.Controllers.FtpController|starting to download file: 2009-10-06155728Z_metadata.txt 2009-10-07 16:33:29.1421|INFO|xxx.Web.Controllers.FtpController|getting ftp response for download file for 2009-10-06155728Z_metadata.txt 2009-10-07 16:33:29.6661|INFO|xxx.Web.Controllers.FtpController|getting ftp response stream for 2009-10-06155728Z_metadata.txt 2009-10-07 16:33:29.6661|INFO|xxx.Web.Controllers.FtpController|File Download status: 125 Data connection already open; Transfer starting. 2009-10-07 16:33:29.6721|INFO|xxx.Web.Controllers.FtpController|getting binary reader for 2009-10-06155728Z_metadata.txt 2009-10-07 16:33:29.6721|INFO|xxx.Web.Controllers.FtpController|writing response stream to C:\\Resumes\\2009-10-06155728Z_metadata.txt 2009-10-07 16:33:29.6951|INFO|xxx.Web.Controllers.FtpController|could not save C:\\Resumes\\2009-10-06155728Z_metadata.txt b/c: This stream does not support seek operations. ``` I've been working on this way too long, so any help would be appreciated! Thanks!!

Original source