C # BinaryReader “поток не поддерживает операции поиска”

StackOverflow https://stackoverflow.com/questions/1534868

  •  20-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь загрузить файлы с ftp-сервера, используя C # и ftpwebrequest.Я могу получить байты с помощью BinaryReader, но когда я пытаюсь прочитать поток с помощью br.readBytes(int), я получаю сообщение об ошибке, что BinaryReader не поддерживает операции поиска.

Кто-нибудь знает, как лучше всего прочитать байты, чтобы я мог записать их в файл?

Вот полный метод:

    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);
        }
    }

Это выполняется как часть текущей службы, поэтому я не хочу выдавать ошибки, которые могли бы остановить службу.Вместо этого я записываю в журнал.Вот содержимое журнала для этого метода:

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.

Я слишком долго работал над этим, так что буду признателен за любую помощь!

Спасибо!!

Это было полезно?

Решение

Вам не следует полагаться на Stream.Length, возможно, это может быть неправильно.Вам просто нужно прочитать все байты в цикле while до тех пор, пока не останется больше байтов для чтения.

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);
}

Оттуда все считанные данные попадают в MemoryStream, и вы можете инициализировать BinaryReader с этим.

Другие советы

Ответ Darkassassin отлично работает!Вот код, с которым я наконец-то начал работать до того, как увидел его пост.Это немного отличается, потому что он записывает непосредственно в файл, а не в поток памяти.

Я заменил эту строку:

downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length));

с этим:

var buffer = new byte[BufferSize];
int readCount = downloadStream.Read(buffer, 0, BufferSize);
while (readCount > 0)
{
    downloadWriter.Write(buffer, 0, readCount);
    readCount = downloadStream.Read(buffer, 0, BufferSize);
}

(Размер буфера = 4096)

Еще раз спасибо за быструю помощь!!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top