当 NewLine 是定界符时是否可以使用 String.Split() ?

Is it possible to use String.Split() when NewLine is the delimiter?

我有一个问题要求我从输入文件中计算一些东西。问题是,文件中的行没有使用任何特殊字符作为分隔符,例如 ,|。我会在下面展示。

Data Communication 
20 
Visual Basic  
40

我需要写入另一个文件的输出应该如下所示:

Data communication 20
Visual Basic 40

Total Books : 60

问题是,如何指定分隔符?就像 strArray = strLine.Split(",") 中的符号一样。由于没有任何东西可以用作分隔符,我该如何拆分文件内容?

当然.. System.IO.File.ReadAllLines() 将读取整个文件并根据换行符拆分为一个数组,因此您将得到一个包含 4 个元素的数组。您可以使用触发器布尔值处理它以获得备用行,或者您可以尝试将该行解析为一个数字,如果它有效,那么它是一个数字,如果不是,它是一个字符串。如果它是一个数字,请从上一个循环中获取您记住的字符串(使用变量)

Dim arr = File.ReadALlLines(...)

Dim isStr = True
Dim prevString = ""

For Each s as String in arr

  If isStr Then 
    prevString = s
  Else
    Console.WriteLine($"The string is {prevString} and the number is {s}")
  End If

  'flip the boolean
  isStr = Not isStr
Next s

当您可以使用标准方法逐行读取文件时,实际上没有必要拆分输入文件中的文本。

您可以使用 StreamReader to read the lines from the source file, check whether the current line is just text or it can be converted to a number, using Integer.TryParse 并排除空行。

此处,当读取的行不是数字时,它将作为 Key 添加到 Dictionary(Of String, Integer) 中,除非它已经存在(以处理源文件中的重复类别)。
如果该行代表一个数字,则将其添加到对应于先前读取的类别 KeyValue,存储在名为 previousLine.

的变量中

此设置可以处理初始空行、文本正文中的空行和重复类别,例如,

Data Communication
20 
Visual Basic  
40

C#  
100
Visual Basic  
10
Other stuff
2

C++
10000
Other stuff
1

如果在第一行找到一个数字,则将其视为一个类别。
添加任何其他检查以处理输入文件的不同结构。

Imports System.IO
Imports System.Linq

Dim basePath = "[Path where the input file is stored]"
Dim booksDict = New Dictionary(Of String, Integer)
Dim currentValue As Integer = 0
Dim previousLine As String = String.Empty

Using sr As New StreamReader(Path.Combine(basePath, "Books.txt"))

    While sr.Peek > -1
        Dim line = sr.ReadLine().Trim()
        If Not String.IsNullOrEmpty(line) Then
            If Integer.TryParse(line, currentValue) AndAlso (Not String.IsNullOrEmpty(previousLine)) Then
                booksDict(previousLine) += currentValue
            Else
                If Not booksDict.ContainsKey(line) Then
                    booksDict.Add(line, 0)
                End If
            End If
        End If
        previousLine = line
    End While
End Using

现在,您有一个字典,其中键代表类别,相关值是该类别中所有书籍的总和。

您可以 Select() 字典的每个 KeyValuePair 并将其转换为表示键及其值的字符串 (Category:Number)。
这里也用了OrderBy(),按字母顺序升序排列类别;可能会有用。

然后调用

File.WriteAllLines 来存储生成的字符串。
最后,一个新的字符串被附加到文件中,使用 File.AppendAllText, to write the sum of all books in all categories. The Sum() 方法对字典中的所有值求和。

Dim newFilePath = Path.Combine(basePath, "BooksNew.txt")

File.WriteAllLines(newFilePath, booksDict.
    Select(Function(kvp) $"{kvp.Key}:{kvp.Value}").OrderBy(Function(s) s))
File.AppendAllText(newFilePath, vbCrLf & "Total Books: " & booksDict.Sum(Function(kvp) kvp.Value).ToString())

输出为:

C#:100
C++:10000
Data Communication:20
Other stuff:3
Visual Basic:50

Total Books: 10173

我使用 File.ReadAllLines 得到一个包含文件中每一行的数组。由于文件的大小可能比显示的样本大,我使用的是 StringBuilder。这样就不必在循环的每次迭代中丢弃并创建一个新字符串。

我正在使用由引号前面的 $ 指示的内插字符串。这允许您将变量插入到用大括号包围的字符串中。

注意 For 循环中的 Step 2i 将增加 2 而不是默认的 1。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim lines = File.ReadAllLines("input.txt")
    Dim sb As New StringBuilder
    Dim total As Integer
    For i = 0 To lines.Length - 2 Step 2
        sb.AppendLine($"{lines(i)} {lines(i + 1)}")
        total += CInt(lines(i + 1))
    Next
    sb.AppendLine($"Total Books: {total}")
    TextBox1.Text = sb.ToString
End Sub