使用StreamReader时出现空异常 [英] Null Exception using StreamReader

查看:0
本文介绍了使用StreamReader时出现空异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个读取文本文件的程序,该程序组织得很整齐。我尝试将每行的信息存储在两个数组中。当我尝试运行该程序时,我得到一个NullReferenceException,并且该程序不运行。我不确定我做错了什么。

 Private Sub RentalCostCalculator_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim objReader As IO.StreamReader
        Dim strFileLocation As String = "location"
        Dim strErrorMessage As String = "The file is not available. Restart when ready."
        Dim strErrorHeading As String = "Error"
        Dim intCount As Integer = 0
        Dim intFill As Integer

        ' Verifies the file exists
        If IO.File.Exists(strFileLocation) = True Then
            objReader = IO.File.OpenText(strFileLocation)

            ' Assigns the cities and city rental costs to the arrays
            Do While objReader.Peek() <> -1
                _strCityName(intCount) = objReader.ReadLine()
            
        'This is where the error occurs

                _decCityRentalCost(intCount) = Convert.ToDecimal(objReader.ReadLine())
                intCount += 1
            Loop
            objReader.Close()

            ' Displays city in listbox
            For intFill = 0 To (_strCityName.Length - 1)
                lstTopTenCities.Items.Add(_strCityName(intFill))
            Next

        Else
            MsgBox(strErrorHeading, MsgBoxStyle.Exclamation, strErrorHeading)
            Close()
        End If

    End Sub

推荐答案

按索引匹配的成对数组是反模式:需要避免。最好使用自定义类类型或元组创建单个集合。


这不太直观,但是提前检查文件是否存在也是一种糟糕的做法。较好的模式在文件访问失败的情况下处理异常。文件系统是易失性的,这意味着即使Exists()检查通过,您仍然必须能够处理文件访问时的异常。我们无论如何都要编写这段代码,所以我们也可以依靠它来检查主文件是否存在。

但是处理异常不是很慢吗?我很高兴你这么问。是的,是的。事实上,展开堆栈来处理异常是您在一台计算机上可以做的最慢的事情之一,这就是为什么像这样的程序流控制通常会避免异常的原因。但你知道更糟糕的是什么吗?磁盘I/O磁盘I/O甚至比异常处理糟糕得多。在预先检查文件是否存在时,我们每次都要支付额外的磁盘提示,在异常情况下,我们只在文件访问失败时支付性能损失。

总而言之:编写更多的代码,每次都要付出更大的代价,或者有时用更少的代码,付出更糟糕但代价更低的代价。跳过File.Exists()检查应该是轻而易举的事。

最后,我不知道是谁教您对变量使用strobj这样的前缀,但这不再是一个好建议。这在VB6时代是有意义的,但从那时起,我们有了更好的类型系统和更好的工具,并且随着VB.Net的发布,早在2002年,微软(发明了这种做法)updated their own style guidelines to say not to use those prefixes。对WinForms控件类型使用前缀仍然是常见的做法,但在其他情况下最好避免使用前缀。

这里有一个合并了这些点的解决方案,并且很可能也解决了NullReferenceException。

Private Iterator Function ReadRentalFile(filePath As String) As IEnumerable(Of (String, Decimal))
    Using rdr As New IO.StreamReader(filePath)
          Dim City As String = Nothing
          While (City = rdr.ReadLine()) IsNot Nothing
                Yield (City, Decimal.Parse(rdr.ReadLine()))
          End While
    End Using
End Function

Private _cityCosts As IEnumerable(Of (String, Decimal))

Private Sub RentalCostCalculator_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim FileLocation As String = "location"
    Try
        _cityCosts = ReadRentalFile(FileLocation)
        lstTopTenCities.Items.AddRange(_cityCosts.Select(Function(c) c.Item1).ToArray())
    Catch
        MsgBox("Error", MsgBoxStyle.Exclamation, "The file is not available. Restart when ready.")
    End Try
End Sub

但查看原始代码,如果以下行出现错误:

_decCityRentalCost(intCount) = Convert.ToDecimal(objReader.ReadLine())
很可能文件没有像您期望的那样组织得很整齐,objReader.ReadLine()没有结果,或者(更有可能的)_decCityRentalCost在这一点上没有引用实际的数组,因为它从未被实际实例化过,或者变量被更改为指向其他地方。如果这是在Form_Load方法中,则很可能是前者。

这篇关于使用StreamReader时出现空异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆