StreamReader.ReadLine抛出已释放对象异常而非返回null问题求助
解决FTP读取最后一行时的"Cannot access a disposed object"异常
嘿,我完全懂你这种困惑——本来照着标准模式写的代码,预期ReadLine()读到末尾乖乖返回null,结果突然蹦出个已释放对象的异常,确实挺挠头的!
先给你捋清楚核心问题:你记忆里“流无更多数据时返回null”是对的,但那是流正常结束的情况。如果是网络流(比如FTP的响应流)被强制提前释放(比如服务器传输完数据后立刻断开连接),StreamReader再调用ReadLine()就会抛出ObjectDisposedException,而不是返回null。
最常见的两个触发场景
- FTP服务器主动断开连接:有些FTP服务器在传输完最后一行数据后,会立即关闭TCP连接,导致底层的响应流被自动释放,这时候后续的
ReadLine()调用就会报错。 - 代码中资源被意外提前释放:比如你没把
FtpWebResponse、响应流或者StreamReader放在using块里,或者循环过程中因为其他逻辑(比如提前return、未处理的异常)导致资源被提前Dispose。
修正后的标准代码示例
下面是能处理这种异常的安全写法,兼顾正常返回null和服务器强制断开的情况:
List<string> fileLines = new List<string>(); // 初始化FTP请求 var ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://your-ftp-server/path/to/your-file.txt"); ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile; ftpRequest.Credentials = new NetworkCredential("your-username", "your-password"); try { // 用using确保所有资源自动释放,避免内存泄漏 using (var ftpResponse = (FtpWebResponse)ftpRequest.GetResponse()) using (var responseStream = ftpResponse.GetResponseStream()) using (var reader = new StreamReader(responseStream)) { string currentLine; while (true) { try { currentLine = reader.ReadLine(); } catch (ObjectDisposedException) { // 捕获流被提前释放的异常,视为读取完毕 break; } // 正常读取到末尾的情况 if (currentLine == null) break; fileLines.Add(currentLine); } } } catch (WebException ex) { // 处理FTP请求本身的异常,比如权限不足、文件不存在等 Console.WriteLine($"FTP请求失败:{ex.Message}"); }
关键细节说明
- 所有涉及网络流的对象(
FtpWebResponse、Stream、StreamReader)都用using包裹,确保无论是否发生异常,资源都会被正确释放。 - 额外捕获
ObjectDisposedException,把它当作“服务器强制断开,读取已完成”的信号,避免程序崩溃。 - 区分了两种“读取结束”的场景:正常返回
null和流被提前释放,覆盖了大部分FTP服务器的行为差异。
这种写法既符合.NET的资源管理规范,又能兼容不同FTP服务器的行为,应该能解决你遇到的问题。
内容的提问来源于stack exchange,提问作者Mort432
相关产品推荐
相关产品推荐

