0

I am attempting to try and write everything in the file just into console, but I keep getting Error 52: "Bad file name or number" and I'm not sure what im doing wrong. This is in VB16 in visual studio. The name of the file that is being read is "example1.txt".

Imports System
Imports System.IO

Module Program
    Sub Main()
        Dim name() As String = {}
        Dim i As Integer = 0
        FileOpen(1, "example1.txt", OpenMode.Input)
        While Not EOF(1)
            name(i) = LineInput(i)
            Console.WriteLine(name(i))
            i += 1
        End While
        FileClose(1)
        Console.ReadLine()

    End Sub
End Module
MrCasual
  • 7
  • 1
  • 6
  • If you're going to use VB.NET then use it. Stop trying to write VB6 code. If you want to work with files then use types from the `System.IO` namespace, e.g. the `File` class and the `StreamReader` class. Get rid of all that code and start again, after learning how to work with files in .NET. – jmcilhinney Apr 10 '20 at 16:37
  • As a specific example, if you want to create an array containing the lines of a text file in its elements then it's a one-liner: `Dim names = File.ReadAllLines(filePath)`. – jmcilhinney Apr 10 '20 at 16:38
  • Even if your I/O code worked, you're still trying to set elements in an array that has no elements. You start out creating an empty array, i.e. an array with ho elements: `Dim name() As String = {}`. You then try to set elements in that array by index: `name(i) = LineInput(i)`. Array elements don't just appear on their own. If you want to be able to just add items as required then use a collection rather than an array. In this case, that would be a `List(Of String)`. – jmcilhinney Apr 10 '20 at 16:41
  • Thank you very much, this worked, I didn't know that VB6 and VB.NET were different things, I just thought they were the same language, I had been told to avoid StreamReader by my teacher, but I guess that VB.NET only works with it. – MrCasual Apr 10 '20 at 16:51
  • Oops! You forgot to give it the full path to the file. – Andrew Morton Apr 10 '20 at 16:51
  • VB6 was the last version of the original, COM-based VB language. It was released over two decades ago. Some developers haven't moved on for one reason or another. If you're being taught VB.NET and being told to avoid using the `StreamReader` class then, I'm sorry to say, your teacher doesn't know much about VB.NET. They probably learned to code in VB6 and are only using VB.NET because the school makes them, without making any real effort to learn how to use it properly themselves. I strongly recommend using other sources to learn VB.NET properly. – jmcilhinney Apr 10 '20 at 17:04
  • VB.NET was initially released in 2002. It was followed by VB.NET 2003 and then VB 2005. At that point, Microsoft dropped the ".NET" suffix because they wanted .NET to be considered the default for development. Subsequent versions were released in 2008, 2010, 2012, 2013, 2015, 2017 and 2019. As you can see, things have moved on from VB6, which was released in 1996. Some people still like it and it has its good points, but writing VB.NET code as though it was VB6 is completely unjustified in this day and age. – jmcilhinney Apr 10 '20 at 17:13

1 Answers1

0

The specific issue here is that you specify a file number of 1 when you open the file:

FileOpen(1, "example1.txt", OpenMode.Input)

but then you use different file numbers when you read the lines:

name(i) = LineInput(i)

You're not telling LineInput to read a specific line. You're telling it to read the next line from a specific file. That should be:

name(i) = LineInput(1)

This is an example of why you should not use magic numbers in your code. It's too easy to mess them up. If you want to use the same value for the same reason in multiple places, assign it to a variable or even a constant and then use that each time:

Dim fileNumber = 1

FileOpen(fileNumber, "example1.txt", OpenMode.Input)

While Not EOF(fileNumber)
    name(i) = LineInput(fileNumber)

EDIT:

To achieve equivalent functionality with good VB.NET code, you would do something like this:

Imports System.IO

Module Module1

    Sub Main()
        Dim names As New List(Of String)

        Using inputFile As New StreamReader("example1.txt")
            While Not inputFile.EndOfStream
                Dim name = inputFile.ReadLine()

                names.Add(name)
                Console.WriteLine(name)
            End While
        End Using

        Console.ReadLine()
    End Sub

End Module

or this:

Imports System.IO

Module Module1

    Sub Main()
        Dim names As New List(Of String)

        For Each name In File.ReadLines("example1.txt")
            names.Add(name)
            Console.WriteLine(name)
        Next

        Console.ReadLine()
    End Sub

End Module

or this:

Imports System.IO

Module Module1

    Sub Main()
        Dim names = File.ReadAllLines("example1.txt")

        For Each name In names
            Console.WriteLine(name)
        Next

        Console.ReadLine()
    End Sub

End Module

Note that the last example is slightly different because names is an array rather than a collection and the entire file is read first, before each name is output to the console. It would appear the same from the user's perspective though. Once they are populated, you can pretty much use an array and a collection in exactly the same way.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • 1
    @NOVADeathstar If you are not familiar with the term: [What is a magic number, and why is it bad?](https://stackoverflow.com/q/47882/1115360) – Andrew Morton Apr 10 '20 at 16:54
  • I seem to remember something about `Dim fileNum = FreeFile()` to get a file handle that is not being used but that was a long time ago. – Mary Apr 10 '20 at 18:00
  • I bet the teacher stayed away from StreamReader because of the `Using...End Using`, and `.Dispose`. Can't teach everything at once. Your last example using the File class shouldn't upset the teacher. – Mary Apr 10 '20 at 18:06
  • 1
    @Mary, I'm not sure that that would be the case because `FileOpen` requires `FileClose`, so calling `Close` on a `StreamReader` is not really any different. You could even call `File.OpenText` to create the `StreamReader` if you don't want to use a constructor. You could argue that the VB6-style code is simpler than the alternatives but the difference is so small that there just can't be a justification for teaching something that no self-respecting .NET developer would use. – jmcilhinney Apr 10 '20 at 18:09
  • 1
    @Mary re `FreeFile` your memory is correct, that was IMO the best practice in VBA to get a file handle and ensure that you weren't stomping on anything. – Craig Apr 13 '20 at 13:59