0

Let me explain it on an excel sheet. I have few txt files in directory (f.txt, d.txt, s.txt, a.txt and q.txt). Each file has few lines of text. And I want to combine those files but in specific way - it is shown on screenshot.

https://i.stack.imgur.com/G2ioY.png

and output should be:

https://i.stack.imgur.com/EtRL1.png

I've already made a code but it doesn't work - I don't know why.

Dim fileEntries As String() = Directory.GetFiles("D:\dir\", "*.txt")
    ' Process the list of .txt files found in the directory. '
    Dim i As Integer = 0
    Dim filesCount As Integer = Directory.GetFiles("D:\dir\", "*.txt").Count

    Do Until i = filesCount
     'do it for every file in folder'
        i = i + 1
        Dim reader As New System.IO.StreamReader(fileEntries(i))
        Dim files() As String = reader.ReadToEnd.Split({Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
        Dim lineCount = File.ReadAllLines(fileEntries(i)).Length
        Dim w As Integer = 0

        Dim dt As DataTable
        dt.Columns.Add(i)
          'add column "0" for file 1, "1" for file 2 etc.'
        Do Until w = lineCount
            dt.Rows.Add(files(w))
            'write each line in file 1 to column 0, etc.'
            w = w + 1
        Loop

    Loop

Can somebody help me?

Bjørn-Roger Kringsjå
  • 9,849
  • 6
  • 36
  • 64

2 Answers2

0

There are few problems in your code:

  • Your datatable was not initialized
  • value of w is exceed than the size of files array

Note: I use DataSet to add each DataTable, However you can remove it if it's not required.

Try following code:

Dim fileEntries As String() = Directory.GetFiles("C:\dir\", "*.txt")
' Process the list of .txt files found in the directory. '

Dim filesCount As Integer = Directory.GetFiles("C:\dir\", "*.txt").Count()

Dim ds As New DataSet()

For i As Integer = 0 To filesCount - 1
    'do it for every file in folder'
    i = i + 1
    Dim reader As New System.IO.StreamReader(fileEntries(i))

    Dim files As String() = reader.ReadToEnd().Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
    Dim lineCount = File.ReadAllLines(fileEntries(i)).Length
    Dim w As Integer = 0

    Dim dt As New DataTable()
    dt.Columns.Add(i.ToString())
    'add column "0" for file 1, "1" for file 2 etc.'
    While w <> lineCount
        If files.Length = w AndAlso w <> 0 Then
            Continue While
        End If

        dt.Rows.Add(files(w))
        'write each line in file 1 to column 0, etc.'
        w = w + 1
    End While

    ds.Tables.Add(dt)
Next
SoftSan
  • 2,482
  • 3
  • 23
  • 54
  • I have error in: `Dim lineCount As Dynamic = File.ReadAllLines(fileEntries(i)).Length` Dynamic: **Type expected.** – john.malkovitz Aug 24 '14 at 08:40
  • Oh sorry! Actually I am C# guy, so by mistake that keyword stay there. I have updated the answer by removing `dynamic` keyword. – SoftSan Aug 25 '14 at 04:55
0

Read/write

If your goal is as shown in the last image, write back to a file named output.txt, then this can be done in a single line of code.

My.Computer.FileSystem.WriteAllText("D:\dir\output.txt", String.Join(Environment.NewLine, (From path As String In Directory.GetFiles("D:\dir", "*.txt") Where IO.Path.GetFileNameWithoutExtension(path) <> "output" Select My.Computer.FileSystem.ReadAllText(path, Encoding.UTF8))), False, Encoding.UTF8)

You can of course make this a bit more readable if you don't like one-liners.

My.Computer.FileSystem.WriteAllText(
    "D:\dir\output.txt",
    String.Join(
        Environment.NewLine,
        (
            From
                path As String
            In
                Directory.GetFiles("D:\dir", "*.txt")
            Where
                IO.Path.GetFileNameWithoutExtension(path) <> "output"
            Select
                My.Computer.FileSystem.ReadAllText(path, Encoding.UTF8)
        )
    ),
    False,
    Encoding.UTF8
)

Iterate

If you need to iterate each line and/or each file, store the result in a local variable.

Dim files As IEnumerable(Of String()) = (
    From
        path As String
    In
        Directory.GetFiles("D:\dir", "*.txt")
    Select
        My.Computer.FileSystem.ReadAllText(path, Encoding.UTF8).Split({Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
)

For Each file As String() In files
    For Each line As String In file

    Next
Next

DataSet

If you need to create a DataSet from the result, then take advantage of anonymous types. This way you can store both the name of the file and its lines.

Dim files = (
    From
        path As String
    In
        Directory.GetFiles("D:\dir", "*.txt")
    Select
        New With {
            Key .Name = IO.Path.GetFileNameWithoutExtension(path),
            .Lines = My.Computer.FileSystem.ReadAllText(path, Encoding.UTF8).Split({Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
        }
)

Dim data As New DataSet()

With data
    .BeginInit()
    For Each item In files
        With data.Tables.Add(item.Name)
            .BeginInit()
            .Columns.Add("Column1", GetType(String))
            .EndInit()
            .BeginLoadData()
            For Each line As String In item.Lines
                .Rows.Add(line)
            Next
            .EndLoadData()
        End With
    Next
    .EndInit()
End With
Bjørn-Roger Kringsjå
  • 9,849
  • 6
  • 36
  • 64