Search code examples
vb.netbinaryfiles

I cant write data to a binary file in a loop


All of my data (name/rollnumber/class) is of a fixed length (14 bytes), I want the program to keep taking a random name from the array, then make a random rollnumber and keep writing it into a file until I press "A".

After i finish running the program, the first 14 bytes are always empty and then my data is in the next 14 bytes. Nothing more nothing less. I don't know why it only wrote one data record.

This is my code:

    Dim randomvalue As Integer

    'Making this array so that each data entry has 14 bytes to it

    Dim array1(91) As Integer

    array1(1) = 14
    For x = 2 To 91
        array1(x) = array1(x) + 14
    Next

    Dim n1, n2, n3, n4 As Integer

    'Array with names of fixed lenght, I want to take a name from only these 9:

    Dim array2(9) As String
    array2(1) = "aleen"
    array2(2) = "talha"
    array2(3) = "waddi"
    array2(4) = "hasna"
    array2(5) = "hassa"
    array2(6) = "zainn"
    array2(7) = "faqeh"
    array2(8) = "furru"
    array2(9) = "ibrah"

  'There is a structure above submain with studentname/rollnumber/class all declared as string 

    Dim newstudent As student
    Dim studentstream As New FileStream("C:\Users\Students\Desktop\A2Filing.dat", FileMode.OpenOrCreate)
    Dim bw As New BinaryWriter(studentstream)

    While Console.ReadLine <> "A"
        Console.WriteLine("Press any key other than 'A' if you want to make another entry into the file")


        'CInt(Math.Floor((upperlimit - lowerlimit + 1) * Rnd())) + lowerlimit
        'Randomize a number b/w 1-9 to get a studentname from the array

        randomvalue = CInt(Math.Floor((9 - 1 + 1) * Rnd())) + 1
        newstudent.studentname = array2(randomvalue)

        n1 = Rnd() + (Rnd() * 50)
        n2 = Rnd() * 10
        n3 = Rnd() * 255
        n4 = Rnd() * Rnd()
        newstudent.rollnumber = Convert.ToString(Left(n1, 1) + Left(n2, 1) + Left(n3, 1) + Left(n4, 1))

        newstudent.studentclass = "A2"

        'Randomize a number between 91 and 1 to place the data in

        Dim randomvalue2 As Integer
        randomvalue2 = CInt(Math.Floor((91 - 1 + 1) * Rnd())) + 1
        studentstream.Position = array1(randomvalue2)


        bw.Write(newstudent.studentname)
        bw.Write(newstudent.rollnumber)
        bw.Write(newstudent.studentclass)
    End While

Solution

  • There are some notes here:

    • the array1 items as you init will all be 14, you have to change it to following, but as i'll say later it is not required to define such array!

      For x = 2 To 91
        array1(x) = array1(x - 1) + 14   'modified to array1(x - 1)
      Next
      
    • before bw.Write, you have this: studentstream.Position = array1(randomvalue2) which will override the file position! also all items in array1 are equal to 14. this is why you get always a small file size (nothing more nothing less). you don't need to set position this way. Just remove that line from your code to append data one after one.

    • According to documentations, if you use a BinaryWriter to write strings, it will be prefixed by string-length! see this question.

      Dim bw As New BinaryWriter(studentstream, System.Text.Encoding.ASCII)
      
      bw.Write("A")  'writes: 1 A  => where 1 is length of string "A"
      bw.Write("BC") 'writes: 2 B  => where 2 is length of string "BC" 
      
      'note that for Unicode Encoding, it will be 2 bytes per char
      Dim bw As New BinaryWriter(studentstream, System.Text.Encoding.Unicode)
      bw.Write("A")  '2 A 0        where 2 is length of unicde string [A 0]
      bw.Write("BC") '4 B 0 C 0    where 4 is length of unicde string [B 0 C 0]
      
    • If you want to write strings without length prefix, you can use System.Text.Encoding.ASCII.GetBytes(str) to convert it to byte array:

      bw.Write(System.Text.Encoding.ASCII.GetBytes(newstudent.studentname))
      
    • Another option will also be to use StreamWriter instead of BinaryWriter as it seems you don't need it. see this link

    • note that its better to open files with Using block. otherwise, do not forget to call Close method (studentstream.Close()) when you finished. if you don't do this, you may lose last chunk or whole of your data!

      Using studentstream As New FileStream("C:\...\Desktop\A2Filing.dat", FileMode.Create)
      
    • use FileMode.Create to override the file if it already exists