Main Site Documentation

Visual Basic 2012 - reading SD card on Fez Hydra


#1
Hi

I have tried converting the C# help files on the SDCard module from the GHI resources, I have got a fair way through but I can seem to figure out the very last couple of steps.  This is my program:

Imports GT = Gadgeteer
Imports GTM = Gadgeteer.Modules
Imports System
Imports System.IO
Imports System.Text



Namespace reading_SD_mark

    Partial Public Class Program
        Dim font As Font
        Dim dave As String
        Dim volume As Byte
        Dim rootdirectory As String
        Dim fileopen As FileStream
        Dim data As Long
        Dim textda As String
        ' This is run when the mainboard is powered up or reset. 
        Public Sub ProgramStarted()
            font = Resources.GetFont(Resources.FontResources.small)
            sdCard.MountSDCard()
           
            '*******************************************************************************************/

            ' Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started")
            
        End Sub

            Private Sub button_ButtonPressed(sender As Gadgeteer.Modules.GHIElectronics.Button, state As Gadgeteer.Modules.GHIElectronics.Button.ButtonState) Handles button.ButtonPressed
            rootdirectory = sdCard.GetStorageDevice().RootDirectory
            fileopen = New FileStream(rootdirectory & "dave1.txt", FileMode.Open)
            data = fileopen.Length
            [b]fileopen.Read(data, 0, data)
            textda = New String(Encoding.UTF8.GetChars(data))[/b]
            Debug.Print(textda)
           

        End Sub
    End Class

End Namespace

_______________________________________

I have been able to convert everything until the bold part, fileopen.Read(data, 0, data).

Any help would be greatly appreciated.

Thanks

#2

fileopen.Read first argument should be a byte array.


#3

Thanks taylorza but how or where do I get the byte array from?


#4

You need to create the array so that the data can be read into it.



Dim bytes(data-1) as Byte
fileopen.Read(bytes, 0, data)
...

Now bytes will have the data you read from the file. I am sure that the sample actually would have data as the byte array, it would help if you provided thoriginal C# code so we can see where you might have gone wrong.


#5

Hi Taylorza

Thanks for the reply, I have tried to make the changes suggested by yourself and I am still getting an error, here is my code:

Imports GT = Gadgeteer
Imports GTM = Gadgeteer.Modules
Imports System
Imports System.IO
Imports System.Text

Namespace reading_SD_mark

Partial Public Class Program
    Dim font As Font
    Dim rootdirectory As String
    Dim filestream As FileStream
    'Dim data As Integer
    Dim textda As String


    ' This is run when the mainboard is powered up or reset. 
    Public Sub ProgramStarted()
        'FileStream FileStream = New FileStream(rootdirectory + "dave.csv", FileMode.Open)
        'byte[] data = New byte[fileStream.length]
        font = Resources.GetFont(Resources.FontResources.small)
        sdCard.MountSDCard()
        '*******************************************************************************************
  
        Debug.Print("Program Started")
        
    End Sub

    Private Sub button_ButtonPressed(sender As Gadgeteer.Modules.GHIElectronics.Button, state As Gadgeteer.Modules.GHIElectronics.Button.ButtonState) Handles button.ButtonPressed
        ' If button.IsPressed Then
        rootdirectory = sdCard.GetStorageDevice().RootDirectory
        filestream = New FileStream(rootdirectory & "dave1.txt", FileMode.Open)
        Dim data As Byte
        [b]data = filestream.Length[/b]
        Dim bytes(data - 1) As Byte
        filestream.Read(bytes, 0, data)
        filestream.Close()
        textda = New String(Encoding.UTF8.GetChars(bytes))
        Debug.Print(textda)
        oledDisplay.SimpleGraphics.DisplayText(rootdirectory, font, GT.Color.Red, 50, 50)
        ' End If
    End Sub
End Class

End Namespace

The part in bold ‘data = filestream.Length’ is giving the error "implicit conversion from ‘long’ to ‘byte’. When I run the program I get the following error:

A first chance exception of type ‘System.IO.IOException’ occurred in System.IO.dll
Error invoking method “Gadgeteer.Interfaces.InterruptInput” (check arguments to Program.BeginInvoke are correct)

I have tried to convert this to VB from C# on the GHI site, their code is:

//Use FileStream to read a text file
FileStream fileStream = new FileStream(rootDirectory + @ “\hello.txt”, FileMode.Open);.
//load the data from the stream
byte[] data = new byte[fileStream.Length];
fileStream.Read(data, 0, data.Length);.
fileStream.Close();
string text = new string(Encoding.UTF8.GetChars(data));

Debug.Print(text);

Thanks David


#6

I’m not sure if this will help, but here is some code I used to read from the storage device used in my code share article

Private Function ReadTextFile(path As String) As String
	Dim storageDev As GT.StorageDevice
	storageDev = sdCard.GetStorageDevice
	Dim result As String = ""
	Try
		Dim rawBytes() As Byte = storageDev.ReadFile(path)
		Dim rawChars() As Char = System.Text.UTF8Encoding.UTF8.GetChars(rawBytes)
		result = New String(rawChars)
	Catch ex As Exception
		FatalError(ex.Message, "ReadTextFile")
	End Try
	Return result
End Function

This was done on the spider main board.


#7

@ Linkin1977 - You also changed the ‘data’ variable to be define as a byte whee it was previously a long.

I am on the iPad at the moment, but as soon as I get to a decent keyboard I will give you the line by line convention of the C# code.


#8

@ Linkin1977 - Here is the exact line by line converstion to from C# to VB.NET, excuse any typos, I did not do this in an IDE.

The following C#


//Use FileStream to read a text file
FileStream fileStream = new FileStream(rootDirectory + @ "\hello.txt", FileMode.Open);.
//load the data from the stream
byte[] data = new byte[fileStream.Length];
fileStream.Read(data, 0, data.Length);.
fileStream.Close();
string text = new string(Encoding.UTF8.GetChars(data));

Debug.Print(text);

Translates to this VB.NET code


' Use FileStream to read a text file
Dim fileStream as New FileStream(rootDirectory & "\hello.txt", FileMode.Open)
'load the data from the stream
Dim data(fileStream.Length - 1) As Byte
fileStream.Read(data, 0, data.Length)
fileStream.Close()
Dim text As New String(Encoding.UTF8.GetChars(data))

Debug.Print(text);

Here are a few guidelines for you

Declaring simple variables
C#


byte age;     // Declares a variable called age which of type byte 
int counter;  // Declares a variable called counter which is of type int (32 bit numeric value)

VB.NET


Dim age as Byte             ' Declares a variable called age which of type byte 
Dim counter as Integer      ' Declares a variable called counter which is of type Integer (32 bit numeric value)

Declaring array variables
C#


byte[] data = new byte[10];      // Declares a variable called data which is an array of 10 bytes
string[] names = new string[10]; // Declares a variable called names which is an array of  10 strings

VB.NET


Dim data(9) as Byte    ' Declares a variable called data which is an array of 10 bytes
Dim names(9) As String ' Declares a variable called names which is an array of  10 strings


#9

Thanks everyone for the help. I do appreciate all the guidance. I will try this when I get in. Cheers


#10

Hello Taylorza

I have done this EXACTLY as you have laid out, thank you so much. I am still getting one error in this line: Dim data(filestream.Length - 1) As Byte - it is saying implicit conversion from ‘Long’ to ‘Integer’

Do you know how I can rectify this? Thanks again!


#11

@ Linkin1977 - That is because the bounds of an array should be an integer and fileStream.Length is probably returning a Long. Try this


Dim data(CInt(fileStream.Length - 1)) as Byte

This performs a type cast from the Long (64 bit integer value) to an Integer (32 bit integer value).

The reason the compiler does not perform this conversion automatically is because there is a risk of data loss since you are going from a data type that can hold larger numbers down to a data type which can hold smaller numbers so if you want to do that you have to be explicit about it so that you are telling the compiler ‘Hey, don’t worry I know what I am doing’… Famous last words :slight_smile:

This is not an issue, because .NETMF would not allow you to allocate an array larger than +/- 700KB anyway so that will be an issue long before the datatype values bite you.


#12

The code is now perfect!!! You star, I however think I have made a mistake now :frowning:

When I push the button I get:

Exception System.IO.IOException - CLR_E_VOLUME_NOT_FOUND (1)

#### Message: 
#### System.IO.Path::NormalizePath [IP: 0070] ####
#### System.IO.Path::GetFullPath [IP: 001a] ####
#### System.IO.FileStream::.ctor [IP: 0009] ####
#### System.IO.FileStream::.ctor [IP: 0010] ####
#### reading_SD_mark.reading_SD_mark.Program::button_ButtonPressed [IP: 002d] ####
#### Gadgeteer.Modules.GHIElectronics.Button::OnButtonEvent [IP: 0058] ####
#### Gadgeteer.Modules.GHIElectronics.Button::_input_Interrupt [IP: 0068] ####
#### Gadgeteer.Interfaces.InterruptInput::OnInterruptEvent [IP: 0055] ####
#### System.Reflection.MethodBase::Invoke [IP: 0000] ####
#### Gadgeteer.Program::DoOperation [IP: 001a] ####
#### Microsoft.SPOT.Dispatcher::PushFrameImpl [IP: 0054] ####
#### Microsoft.SPOT.Dispatcher::PushFrame [IP: 001a] ####
#### Microsoft.SPOT.Dispatcher::Run [IP: 0006] ####
#### Gadgeteer.Program::Run [IP: 0020] ####

A first chance exception of type ‘System.IO.IOException’ occurred in System.IO.dll
Error invoking method “Gadgeteer.Interfaces.InterruptInput” (check arguments to Program.BeginInvoke are correct)

These are the parts I am loading at the start:

Imports GT = Gadgeteer
Imports GTM = Gadgeteer.Modules
Imports System
Imports System.IO
Imports System.Text

Sorry for ANOTHER question!


#13

I think that the error should give you the pointer that you need. CLR_E_VOLUME_NOT_FOUND means your VOLUME wasn’t located. That could simply be that you haven’t defined the volume portion of the path correctly, can you show us how you do that?

If you’re using the code from your previous attempts,

rootdirectory = sdCard.GetStorageDevice().RootDirectory

may not be correct. Can you examine that object (or perhaps that’s where the exception is thrown?).


#14

Thanks again, entirely my fault, I forgot the \ before the file name! School boy error!

Thanks for everyones help.