C#BinaryReaderは、「ストリームがシーク操作をサポートしていません」

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

  •  20-09-2019
  •  | 
  •  

質問

私はC#としたFtpWebRequestを使用してFTPサーバーからファイルをダウンロードしようとしています。私は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の答えは素晴らしい作品!ここで私は彼のポストを見て前に、私は最終的に動作するようになったコードです。それはむしろ、メモリストリームに比べてファイルに直接書き込んB / Cは若干異なるのです。

私はこの行を置き換えます:

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

(たBufferSize = 4096)

クイックヘルプのためにもう一度感謝!!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top