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
fileopen.Read first argument should be a byte array.
Thanks taylorza but how or where do I get the byte array from?
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.
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
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.
@ 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.
@ 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)
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
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
Thanks everyone for the help. I do appreciate all the guidance. I will try this when I get in. Cheers
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!
@ 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
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.
The code is now perfect!!! You star, I however think I have made a mistake now
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!
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?).
Thanks again, entirely my fault, I forgot the \ before the file name! School boy error!
Thanks for everyones help.