For some reason my previous question was considered too vague. So let me be more specific.
I have a 2 dimensional array of type single.
I want to serialize it to save in an Access database.
The suggestion was to save it as a Memo field which is fine.
I want to later read the Memo field and deserialize it to retrieve the original array.
I have searched extensively on the web and here and can not find the answer. I believe I am serializing the array correctly but do not know how to deserialize it.
This code appears to work for serializing but I can not figure out how to deserialize:
Dim f As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim ms As New MemoryStream
f.Serialize(ms, arLHS)
Dim byArr As Byte() = ms.ToArray
I then save byArr to the Memo field.
Please provide sample code.
You can deserialize it via base64 converter:
Dim str_b64 As String = Convert.ToBase64String(byArr)
Dim ms2 As New MemoryStream(Convert.FromBase64String(str_b64))
Dim intArr2(,) As Int32 = f.Deserialize(ms2)
This may look somewhat awkward, but it works - tested in a console app in VS 2010.
Credit goes here. Through this link, you can also find the full version of the code to play with.
I changed the data type of the Access field from Memo to OLE Object and that seems to work. When I look at the data in Access it tells me the field is "Long binary data" and I was able to use the following code after reading the record from Access:
Dim f As New System.Runtime.Serialization.Formatters.BinaryFormatter
Dim byArr As Byte()
byArr = DirectCast(dtLHS.Rows(0).Item("LHS"), Byte())
Dim theArrayAsString As String = Convert.ToBase64String(byArr)
Dim ms2 As New MemoryStream(Convert.FromBase64String(theArrayAsString))
Dim newLHS(,) as single = f.Deserialize(ms2)
Is this correct?
Related
I'm trying to save a local document stored in SQL db using UiPath.
From the execute query activity it returns a DataTable value with one column(“Data”).
If I'm not wrong somehow I need to transform the DataTable.rows(0)(“Data”) (studio is interpreting it as object) to an array of bytes.
I used invoke code but the file is broken:
Dim _MemoryStream As New System.IO.MemoryStream()
Dim _BinaryFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
_BinaryFormatter.Serialize(_MemoryStream, inputObj)
_MemoryStream.ToArray()
File.WriteAllBytes(“C:\Users\Desktop\test.tiff”, _MemoryStream.ToArray())
Unless you serialised an object when saving, which I doubt, there's no reason to try to deserialise an object when retrieving. Every field from a DataRow is returned as an Object reference, because it must support any type of object, but that object still has its own type. If you saved binary data then that type will be Byte(), i.e. a Byte array. Kinda looks like File.WriteAllBytes takes a Byte array:
File.WriteAllBytes(“C:\Users\Desktop\test.tiff”, DirectCast(inputObj, Byte()))
That is what I would expect that you need to do. It does depend on how you saved the data in the first place but if you used File.ReadAllBytes or Image.Save then this should do the job. If not, show us how you sabed the data in the first place.
I try to download files from gridview .. I save files in database and then I display in grid-view I try this
I save files in database table not in folder so I try to download files
when i do this document is download but there is problem when i debug the code and check then in this line
Dim row = db_stu.dResult.Tables(0).Rows(i)
dResult shows
docid document docname docextension
1014 System.Byte[] Book2.xlsx .xlsx
and then when i further proceed docname shows "1912218726836.xlsx" this and also file download as a corrupt
These two lines together are wrong:
Dim binary() As Byte = TryCast(structDb.dstResult.Tables(0).Rows(i).Item("document"), Byte())
Dim ms As MemoryStream = New MemoryStream(binary)
The reason to use TryCast is that the object that you're trying to cast may not be the type you're trying to cast it as. In that case, TryCast will return Nothing. Use of TryCast should ALWAYS be followed by a test for Nothing, which you haven't done. You're using the result as though you're sure that there will be an object of that type. If you know that then you should be using DirectCast rather than TryCast.
Even if you do know that the reference will not be to an object of a different type and you use DirectCast though, if you cast a null reference, i.e. Nothing, then you're still going to get Nothing back. So, you first need to determine whether structDb.dstResult.Tables(0).Rows(i).Item("document") can refer to an object of a type other than Byte(). If it can't then use DirectCast rather than TryCast. Either way, it appears that that expression can produce Nothing so you need to check for Nothing either way, e.g.
Dim binary() As Byte = TryCast(structDb.dstResult.Tables(0).Rows(i).Item("document"), Byte())
If binary IsNot Nothing Then
Dim ms As MemoryStream = New MemoryStream(binary)
'...
End If
EDIT: If the column is nullable then you need to first test whether the row contains null and then only use the data if there is some:
Dim row = structDb.dstResult.Tables(0).Rows(i)
If Not row.IsNull("document") Then
'There is data so go ahead and use it.
Dim binary = DirectCast(row("document"), Byte())
'...
I've Googled the underlying question of how to store an image in the database and found many examples. However, all of the answers I'm seeing (for example this), seem to use a SQLCommand as the solution whether they are using the older "image" type, text, or suggesting VARCHAR(MAX). I am using SQL 2008 and SQL 2012
I'm having trouble incorporating this into my app since I have a legacy dll which will do some other work, and then store my image. I want to wrap this into a SQL transaction. The challenge is that the DLL is essentially a black-box to me since I cannot change the source code. The Dll exposes a parameter for an optional SQL statement it can run as part of its transaction.
The structure of the DLL is something like this:
Public Class MyClass
Public Property ExtraSQL as string
Public Function DoWork
Dim sMainSQL as String
'Start A transaction
Execute(sMainSQL)
If ExtraSQL <> "" Then
Execute(ExtraSQL)
End If
If OK Then Commit Transaction
End Function
End Class
My goal is to feed a SQL string into property ExtraSQL, but I'm not sure how to do this as all the examples are indicating something SqlCommand.Parameters(#Image).Value = byteArray(). I'm getting the image data from a web service. Over its life cycle, it's formatted as an Image, a base64 Encoded string, a memorystream and a byte array, so converting between the types is not the problem. I'm just unclear on the cleanest syntax for doing this. Is it best to just take my original base64 string and do something like:
INSERT INTO tblImage (ImageData) Values ('Base64 blah blah')
and then whenever I read the image back out do this:
Public Function Base64ToImage(ByVal base64String As String) As System.Drawing.Image
Dim img As System.Drawing.Image = Nothing
Try
'Convert Base64 string to byte array
Dim btImage As Byte() = Convert.FromBase64String(base64String)
Dim ms As New IO.MemoryStream(btImage, 0, btImage.Length)
ms.Write(btImage, 0, btImage.Length)
img = System.Drawing.Image.FromStream(ms, True)
Catch ex As Exception
End Try
Return img
End Function
I would appreciate any supporting links, examples, and advice. Thank you in advance.
Well, considering you clearly can't send in parameterized SQL, yes that's the best approach. I sure don't like it because it's wide open to SQL injection. I would consider decompiling the assembly you're using and making it my own source code in the future.
I'm making a registration form with a picture in VB.Net using an Access database. Utilizing the following code, I am getting an error.
Me.Student_instructorTableAdapter.Insert(txtname,txtpass, ***PictureBox1.Image***)
Me.Student_instructorTableAdapter.Fill(Me.DatabaseDataSet4.student_instructor)
MsgBox("Successfully added", MsgBoxStyle.Information)
The PictureBox1.Image is saving into an Access Database ("picture") which throws an error:
"System.Drawing.Image" cannot be converted to '1-dimensional array"
What should I use instead of PictureBox1.Image when I call Insert in order to avoid the exception?
(Should be a comment but I need to post code)
We need the full exception message to know exactly what it's expecting (1-dimensional array of what?) Most likely it's a Byte array.
If so, you can convert an image to a Byte array like this...
Public Function ImageToByteArray(imageIn As System.Drawing.Image) As Byte()
Dim ms As New MemoryStream()
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
Return ms.ToArray()
End Function
You can convert a Byte array back to an image like this...
Public Function byteArrayToImage(byteArrayIn As Byte()) As Image
Dim ms As New MemoryStream(byteArrayIn)
Dim returnImage As Image = Image.FromStream(ms)
Return returnImage
End Function
See here for more information
I'm not familiar with access data types so it may support images directly. If so, you need to make sure that you've got the right data type selected for that column/field.
Incidentally, if you don't have to, don't use Access (or at least the storage engine/JET) for new projects - it's slow, unreliable with more than 10 users and has serious security issues. If you don't want a full-up SQL Server database, consider SQL Compact Edition (CE) or SQL Express.
I need your help, guys! :|
I've got myself a CSV file with the following contents:
1,The Compact,1.8GHz,1024MB,160GB,440
2,The Medium,2.4GHz,1024MB,180GB,500
3,The Workhorse,2.4GHz,2048MB,220GB,650
It's a list of computer systems, basically, that the user can purchase.
I need to read this file, line-by-line, into an array. Let's call this array csvline().
The first line of the text file would stored in csvline(0). Line two would be stored in csvline(1). And so on. (I've started with zero because that's where VB starts its arrays). A drop-down list would then enable the user to select 1, 2 or 3 (or however many lines/systems are stored in the file). Upon selecting a number - say, 1 - csvline(0) would be displayed inside a textbox (textbox1, let's say). If 2 was selected, csvline(1) would be displayed, and so on.
It's not the formatting I need help with, though; that's the easy part. I just need someone to help teach me how to read a CSV file line-by-line, putting each line into a string array - csvlines(count) - then increment count by one so that the next line is read into another slot.
So far, I've been able to paste the numbers of each system into an combobox:
Using csvfileparser As New Microsoft.VisualBasic.FileIO.TextFieldParser _
("F:\folder\programname\programname\bin\Debug\systems.csv")
Dim csvalue As String()
csvfileparser.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
csvfileparser.Delimiters = New String() {","}
While Not csvfileparser.EndOfData
csvalue = csvfileparser.ReadFields()
combobox1.Items.Add(String.Format("{1}{0}", _
Environment.NewLine, _
csvalue(0)))
End While
End Using
But this only selects individual values. I need to figure out how selecting one of these numbers in the combobox can trigger textbox1 to be appended with just that line (I can handle the formatting, using the string.format stuff). If I try to do this using csvalue = csvtranslator.ReadLine , I get the following error message:
"Error 1 Value of type 'String' cannot be converted to '1-dimensional array of String'."
If I then put it as an array, ie: csvalue() = csvtranslator.ReadLine , I then get a different error message:
"Error 1 Number of indices is less than the number of dimensions of the indexed array."
What's the knack, guys? I've spent hours trying to figure this out.
Please go easy on me - and keep any responses ultra-simple for my newbie brain - I'm very new to all this programming malarkey and just starting out! :)
Structure systemstructure
Dim number As Byte
Dim name As String
Dim procspeed As String
Dim ram As String
Dim harddrive As String
Dim price As Integer
End Structure
Private Sub csvmanagement()
Dim systemspecs As New systemstructure
Using csvparser As New FileIO.TextFieldParser _
("F:\folder\programname\programname\bin\Debug\systems.csv")
Dim csvalue As String()
csvparser.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
csvparser.Delimiters = New String() {","}
csvalue = csvparser.ReadFields()
systemspecs.number = csvalue(0)
systemspecs.name = csvalue(1)
systemspecs.procspeed = csvalue(2)
systemspecs.ram = csvalue(3)
systemspecs.harddrive = csvalue(4)
systemspecs.optical = csvalue(5)
systemspecs.graphics = csvalue(6)
systemspecs.audio = csvalue(7)
systemspecs.monitor = csvalue(8)
systemspecs.software = csvalue(9)
systemspecs.price = csvalue(10)
While Not csvparser.EndOfData
csvalue = csvparser.ReadFields()
systemlist.Items.Add(systemspecs)
End While
End Using
End Sub
Edit:
Thanks for your help guys, I've managed to solve the problem now.
It was merely a matter calling loops at the right point in time.
I would recommend using FileHelpers to do the reading.
The binding shouldn't be an issue after that.
Here is the Quickstart for Delimited Records:
Dim engine As New FileHelperEngine(GetType( Customer))
// To Read Use:
Dim res As Customer() = DirectCast(engine.ReadFile("FileIn.txt"), Customer())
// To Write Use:
engine.WriteFile("FileOut.txt", res)
When you get the file read, put it into a normal class and just bind to the class or use the list of items you have to do custom stuff with the combobox. Basically, get it out of the file and into a real class asap, then things will be easier.
At least take a look at the library. After using it, we use a lot more simple flat files since it is so easy, and we haven't written a file access routine since (for that kinda stuff).
http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser.aspx
I think your main problem is understanding how arrays work (hence the error message).
You can use split and join functions to convert strings into and out of arrays
dim s() as string = split("1,2,3",",") gives and array of strings with 3 elements
dim ss as string = join(s,",") gives you the string back
Firstly, it's actually really good that you are using the TextFieldParser for reading CSV files - most don't but you won't have to worry about extra commas and quoted text etc...
The Readline method only gives you the raw string, hence the "Error 1 Value of type 'String' cannot be converted to '1-dimensional array of String'."
What you may find easier with combo boxes etc is to use an object (e.g. 'systemspecs') rather than strings. Assign the CSV data to the objects and override the "ToString" method of the 'systemspecs' class to display in the combo box how you want with formatting etc. That way when you handle the SelectedIndexChanged event (or similar) you get the "SelectedItem" from the combo box (which can be Nothing so check) and cast it as the 'systemspecs' to use it. The advantage is that you are not restricted to display the exact data in the combo etc.
' in "systemspecs"...
Public Overrides Function ToString() As String
Return Name ' or whatever...
End Function ' ToString
e.g.
dim item as new systemspecs
item.ID = csvalue(1)
item.Name = csvalue(2)
' etc...
combobox1.Items.Add(item)
Let me know if that makes sense!
PK :-)