try
{
FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
}
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
Console.WriteLine(read1.ReadToEnd());
Console.WriteLine("Directory is compleate,status(0)",
res.StatusDescription);
read1.Close();
rs.Close();
}
catch (Exception e1)
{
Console.WriteLine(e1.Message);
}
我试图通过C#访问ftp服务器。
但是,代码错误有例外:
A first chance exception of type "System.ArgumentException" occured in mscorlib.dll. Stream was not readable.
任何帮助将不胜感激。
答案 0 :(得分:2)
将所有IDisposable
资源放在using(...) {...}
中。技术可以防止
资源泄漏/关闭资源调用:
try {
FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
// Response: we're going to work wuth respose within "using" block only
using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
Console.WriteLine(resp.WelcomeMessage);
// Reader: once again reader's opened once and called within using only
using (StreamReader reader = new StreamReader(resp.GetResponseStream())) {
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("Directory is complete, status(0)", resp.StatusDescription);
}
}
catch (Exception ex) { // <- Bad idea to catch all possible exceptions without "throw;"
Console.WriteLine(ex.Message);
}
答案 1 :(得分:0)
TLDR;处置FtpWebResponse
对象的状态,因此您无法读取响应流。流已关闭。
反汇编FtpWebResponse:
public override void Close()
{
if (Logging.On)
{
Logging.Enter(Logging.Web, this, "Close", "");
}
if (this.HttpProxyMode)
{
this.m_HttpWebResponse.Close();
}
else
{
Stream responseStream = this.m_ResponseStream;
if (responseStream != null)
{
responseStream.Close();
}
}
if (Logging.On)
{
Logging.Exit(Logging.Web, this, "Close", "");
}
}
您获得异常的原因是您正在阅读回复:
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
}
在下一行,您尝试再次将响应读入另一个变量:res
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
在该部分中,您还会对res.GetResponseStream()
进行两次调用,但这与发生错误无关。即使您将其更改为:
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A
或者:
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
发生错误的原因是FtpWebResponse
对象的状态,它被处理掉;并拥有StatusCode = ClosingData
。当我尝试在该状态下读取流时,我会收到您遇到的错误。在之前的使用块中,StatusCode = OpeningData
。
但是,如果你只想改变几行:
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A
Console.WriteLine(read1.ReadToEnd());
Console.WriteLine("Directory is compleate,status(0)", res.StatusDescription);
}
使用范围输入此内容时,StatusCode = OpeningData
和流可用且可读。退出范围时,StatusCode = ClosingData
和流将无法读取。
希望这是有道理的,如果我错了,请纠正我。 : - )
通过这些小的更改,您的代码将按预期运行。但是你应该研究@DmitryBychenko建议的模式。这样,您就可以访问所需范围内的资源,并在之后处理。