我的代码收到以下错误:
从String转换为Double类型无效
程序在输出正确之前正常运行但是我做了一些无效的更改并且必须还原它们,但它没有工作。
该程序用于在文本文件的列中查找min
和max
值。
如果可能,请建议一种计算文本文件中多个列的min
和max
值的方法,这些值用空格(不一致的空格)分隔,其方法与下面的代码有些相似。
Dim Textfile As String
Dim openDlg As New OpenFileDialog
If openDlg.ShowDialog() = DialogResult.OK Then
openDlg.Filter = "txt files (*.txt)| *.txt|All files (*.*)|*.*"
openDlg.FilterIndex = 2
openDlg.RestoreDirectory = True
Textfile = openDlg.FileName
Dim RECfile As New System.IO.StreamReader(Textfile)
Dim textline As String
Dim ln = 0
Dim Max As Integer
Max = 0
Dim Min As Integer
Min = 999999
Do While RECfile.Peek() <> -1
textline = RECfile.ReadLine()
If textline > Max Then
Max = textline
End If
If textline < Min Then
Min = textline
End If
ln += 1
Me.maxval.Text = Max
Me.Minval.Text = Min
Loop
RECfile.Close()
End If
样本数据1:
194787.5 194987.5 194787.5 194987.5 194987.5 195012.5 194987.5 195012.5 195012.5 2003999 195012.5 2003999 2003999 195037.5 2003999 195037.5 195037.5 195062.5 195037.5 195062.5 195062.5 195087.5 195062.5 195087.5 195087.5 195112.5 195087.5 195112.5 195112.5 195137.5 195112.5 495137.5 195137.5 195162.5 195137.5 195162.5 195162.5 194812.5 195162.5 19400012.5 194837.5 194837.5 194862.5 194862.5 194887.5 194887.5 194912.5 194912.5 194937.5 194937.5 12111 12111999
样本日期2:
194987.5 195012.5 194987.5 195012.5 195012.5 2003999 195012.5 2003999 2003999 195037.5 2003999 195037.5 195037.5 195062.5 195037.5 195062.5 195062.5 195087.5 195062.5 195087.5 195087.5 195112.5 195087.5 195112.5 195112.5 195137.5 195112.5 495137.5 195137.5 195162.5 195137.5 195162.5 195162.5 194812.5 195162.5 19400012.5 194837.5 194837.5 194862.5 194862.5 194887.5 194887.5 194912.5 194912.5 194937.5 194937.5
编辑:
这些是我收到的警告的屏幕截图,我认为它与代码相关联。
截屏2:
答案 0 :(得分:2)
根据您的示例数据,Integer
不会削减它。我建议您更改为使用Double
而不是 194787.5 不会解析为Integer
。
首先转向 Option Strict On:
将隐式数据类型转换限制为仅扩展转换,禁止后期绑定,并禁止导致Object类型的隐式类型。
接下来,我建议您创建一个新的临时变量并使用Double.TryParse:
将数字的字符串表示形式转换为其等效的双精度浮点数。返回值表示转换是成功还是失败。
对您的代码的建议看起来与此类似:
Dim temp As Double = 0
If Double.TryParse(textline, temp) Then
If temp > Max Then
Max = temp
End If
If temp < Min Then
Min = temp
End If
End If
Me.maxval.Text = Max.ToString()
Me.Minval.Text = Min.ToString()
请注意.ToString()
和Max
上的Min
。这是因为它们是Doubles
,需要转换为String
。
我想提出的另一个建议是实施Using来帮助处理对象。
而不是:
Dim RECfile As New System.IO.StreamReader(Textfile)
你会:
Using RECfile As New System.IO.StreamReader(Textfile)
...
End Using
您无需致电RECfile.Close()
,因为Using
区块会处理此问题。
我也看不到变量ln
的任何使用,所以删除它。
最后,您声明文本文件包含多个以不一致的空格分隔的列。我实际上相信它们是以制表符分隔的值。话虽如此Andrew Morton提出了一个非常好的建议:
..拆分{CChar(vbTab),“”c,以防万一值之间没有标签(例如文件是手工编辑的)。
我建议我们使用String.Split方法:
Dim textline As String() = RECfile.ReadLine().Split(New Char() {CChar(vbTab), " "c}, StringSplitOptions.RemoveEmptyEntries)
总体而言,您的代码看起来与此类似:
Using RECfile As New System.IO.StreamReader(Textfile)
Dim Max As Double = Double.MinValue
Dim Min As Double = Double.MaxValue
Do While RECfile.Peek() <> -1
Dim textline As String() = RECfile.ReadLine().Split(New Char() {CChar(vbTab), " "c}, StringSplitOptions.RemoveEmptyEntries)
For Each line In textline
Dim temp As Double = 0
If Double.TryParse(line.Trim(), temp) Then
If temp > Max Then
Max = temp
End If
If temp < Min Then
Min = temp
End If
End If
Me.maxval.Text = Max.ToString()
Me.Minval.Text = Min.ToString()
Next
Loop
End Using
我的输出是:
Max = 19400012.5
Min = 12111
根据OP的请求编辑,以获取文本文件中每列的最小值和最大值。
我已尽力尝试分析样本数据,并从中可以看出值是以制表符分隔的。如果列中缺少值,则会找到彼此相邻的两个选项卡。如果两个相邻列中存在缺失值,则会找到彼此相邻的四个选项卡。为了解决这个问题,我用一个标签替换了所有出现的两个标签。这使索引保持稳定。
首先,我创建了两个类:
ColumnValue
:
Public Class ColumnValue
Public Key As String
Public Sub New(ByVal id As Integer,
ByVal value As Double)
_id = id
_value = value
End Sub
Private _id As Integer
Public ReadOnly Property ID As Integer
Get
Return _id
End Get
End Property
Private _value As Double
Public ReadOnly Property Value As Double
Get
Return _value
End Get
End Property
End Class
ColumnValues
:
Imports System.Collections.ObjectModel
Public Class ColumnValues
Inherits KeyedCollection(Of String, ColumnValue)
Protected Overrides Function GetKeyForItem(ByVal item As ColumnValue) As String
Return item.Key
End Function
Public Function GetMax(ByVal columnId As Integer) As Double
Return (From c In Me
Where c.ID = columnId
Select c.Value).Max()
End Function
Public Function GetMin(ByVal columnId As Integer) As Double
Return (From c In Me
Where c.ID = columnId
Select c.Value).Min()
End Function
End Class
请注意,在ColumnValues
课程中,根据使用LINQ传递的Min
,我有两个函数可以返回Max
和columnId
。
这是我修改后的代码:
Dim myColumnValues As New ColumnValues
Using RECfile As New System.IO.StreamReader(Textfile)
Do While RECfile.Peek() <> -1
Dim textline As String() = RECfile.ReadLine().Replace(CChar(vbTab) & CChar(vbTab), vbTab).Split(New Char() {CChar(vbTab)})
Dim columnId As Integer = 0
For Each column In textline
columnId += 1
Dim temp As Double = 0
If Double.TryParse(column.Trim(), temp) Then
myColumnValues.Add(New ColumnValue(columnId, temp))
End If
Next
Loop
'Get a distinct list of column Ids to loop through
Dim columnIds = (From c In myColumnValues
Order By c.ID
Select c.ID).Distinct()
'Output the Max and Min for each column
For Each c In columnIds
Debug.WriteLine("Column: " & c.ToString() & " Max: " & myColumnValues.GetMax(c))
Debug.WriteLine("Column: " & c.ToString() & " Min: " & myColumnValues.GetMin(c))
Next
End Using
请注意,我必须恢复分割vbTab
而不是分割标签和空格。通过拆分空间也导致了索引的许多问题,而且数据还不够好。
样本数据1 的输出为:
Column: 1 Max: 2003999
Column: 1 Min: 194787.5
Column: 2 Max: 2003999
Column: 2 Min: 12111
Column: 3 Max: 2003999
Column: 3 Min: 194787.5
Column: 4 Max: 19400012.5
Column: 4 Min: 194837.5
样本数据2 的输出为:
Column: 1 Max: 2003999
Column: 1 Min: 194987.5
Column: 2 Max: 2003999
Column: 2 Min: 194812.5
Column: 3 Max: 2003999
Column: 3 Min: 194987.5
Column: 4 Max: 19400012.5
Column: 4 Min: 194837.5
根据OP关于屏幕截图错误的编辑进行编辑。
我会为Class
和ColumnValue
创建单独的ColumnValues
文件,如下所示:
ColumnValue
:
ColumnValues
:
将这些内容与您的Form1
代码分开。