I thought this would be an easy task but I seem to have gotten lost in a rabbit hole.
I am trying to convert a class to XML and then a byte array in order to send it as the content of a HTTPWebRequest for a WCF Restful webservice. My code will return the class as XML in the Byte Array but the format is incorrect. The XML looks like this:
<?xml version="1.0" encoding="utf-8"?><Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><FirstName>Richard</FirstName><LastName>Cranium</LastName></Person>
I was attempting to use the OmitXmlDeclaration method thinking this would eliminate the extra declarations but it does not work with the xmltextwriter object and when I use the xmlwriterobject I can't determine how convert the outcome to a Byte array.
Here is my code:
Private Shared Function GenerateXMLPersonAsByte(strFirstName As String, strLastName As String) As Byte()
' This should serialize this to a byte array
Dim p As New Person()
p.FirstName = strFirstName
p.LastName = strLastName
' Want to use this with the xmlTextWriter but it does not support the property it is to be used with the XMLWriter instead
'Dim settings As XmlWriterSettings = New XmlWriterSettings()
'settings.OmitXmlDeclaration = True
'settings.ConformanceLevel = ConformanceLevel.Fragment
'settings.CloseOutput = False
' Create the XmlWriter object and write some content.
Dim mStream As New MemoryStream()
Dim ser As New XmlSerializer(GetType(Person))
Dim xmlTW As New XmlTextWriter(mStream, Encoding.UTF8)
ser.Serialize(xmlTW, p)
mStream = DirectCast(xmlTW.BaseStream, MemoryStream)
mStream.Close()
Return mStream.ToArray()
End Function
What must I do in order to get the XML with the correct opening tag?
or
How do I get the output from the XmlTextWriter object to a byte array?
I can't answer the whole question, but convert to string first
Dim myXmlString As String
Dim myStringWriter As New StringWriter()
Dim myXmlTextWriter As XmlTextWriter = New XmlTextWriter(myStringWriter)
'Write XML, and then flush the writer...
myXmlTextWriter.Flush()
'Return text from string writer...
myXmlString = myStringWriter.ToString()
'Close the Objects...
myStringWriter.Close()
myXmlTextWriter.Close()
then convert to byte using (sorry, C#, but you get the .NET call)
byte[] data = ASCIIEncoding.UTF8.GetBytes(myXmlString);
Related
I am creating a project where a zip file is base 64 encoded and then the file is decoded and saved, but when I unzip the file it gives a corrupted file error.
Dim zip As New Xs_UnZipFilesCompat
''Encode()
Dim base64encoded As String
Using r As StreamReader = New StreamReader(File.OpenRead("E:\zip_test.zip"))
Dim data As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(r.ReadToEnd())
base64encoded = System.Convert.ToBase64String(data)
r.Dispose()
End Using
'decode --> write back
Using w As StreamWriter = New StreamWriter(File.Create("e:\stcRepositorio\Entrena_To_Art\Enviar\testDEco.zip"))
Dim data As Byte() = System.Convert.FromBase64String(base64encoded)
w.Write(System.Text.ASCIIEncoding.ASCII.GetString(data))
w.Dispose()
End Using
I can't find the solution
The encode is not correct. Specifically, this line:
Dim data As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(r.ReadToEnd())
You definitely don't want to read a file with a *.zip extension as if it were made of ASCII characters. Replace it with this:
Dim data As Byte() = System.IO.File.ReadAllBytes(fileName)
Which means you also no longer need the StreamReader, so we end up with this:
Public Function Encode(fileName As String) As String
Return Convert.ToBase64String(IO.File.ReadAllBytes(fileName))
End Function
Then the Decode would look like this:
Public Sub Decode(fileName As String, base64Data As String)
IO.File.WriteAllBytes(fileName, Convert.FromBase64String(base64Data))
End Sub
And you could call them like this:
Dim base64encoded As String = Encode("E:\zip_test.zip")
Decode("e:\stcRepositorio\Entrena_To_Art\Enviar\testDEco.zip", base64encoded)
Or we can write it without the methods like this:
Dim base64encoded As String = Convert.ToBase64String(IO.File.ReadAllBytes("E:\zip_test.zip"))
IO.File.WriteAllBytes("e:\stcRepositorio\Entrena_To_Art\Enviar\testDEco.zip", Convert.FromBase64String(base64encoded))
But it seems like that all reduces down to this:
IO.File.Copy("E:\zip_test.zip", "e:\stcRepositorio\Entrena_To_Art\Enviar\testDEco.zip")
I am able to write to the file perfectly... however I am having trouble reading from file and inserting read data into a listbox.
Public myData As New MySettings
Public saveFile As String = ("mysettings.ini")
'SAVE INFO TO SETTINGS FILE
Dim fs As Stream = New FileStream(saveFile, FileMode.Create)
Dim bf As BinaryFormatter = New BinaryFormatter()
For l_index As Integer = 0 To ListBox1.Items.Count - 1
Dim l_text As String = CStr(ListBox1.Items(l_index))
bf.Serialize(fs, l_text)
Next
fs.Close()
Return
This is the part where I am having trouble...
'LOAD INFO FROM SETTINGS FILE
Dim fs As Stream = New FileStream(saveFile, FileMode.Open)
Dim bf As BinaryFormatter = New BinaryFormatter()
For l_index As Integer = 0 To saveFile.Count - 1
Dim l_text As String = CStr(saveFile(l_index))
'myData = CType(bf.Deserialize(fs), CType(myData))
ListBox1.Items.Add(myData)
Next
fs.Close()
Return
Any help at all would be appreciated, even a point in the right direction.
Thanks in advance!!
The ListBox ObjectCollection (Items) is not marked as serializable, so you cant serialize the entire thing at once. You may have encountered this and used the loop to serialize each item. The loop does appear to serialize each item, but I don't know how you can deserialize in a loop - you wont know how many items there are, nor will the Serializer.
Rather than one item at a time, you could copy the ListBox items to an array and serialize the entire thing:
Dim ary(lb.Items.Count - 1) As Object
lb.Items.CopyTo(ary, 0)
' OpenOrCreate!
Using fs As New FileStream("C:\Temp\lbitems.bin", FileMode.OpenOrCreate)
Dim bf As New BinaryFormatter
bf.Serialize(fs, ary)
End Using ' close and dispose of stream
Deserialization is just the reverse:
Using fs As New FileStream("C:\Temp\lbitems.bin", FileMode.Open)
Dim bf As New BinaryFormatter
Dim myAry = bf.Deserialize(fs)
lb.Items.Clear()
lb.Items.Add(myAry)
End Using
You can make it a bit simpler using a List(of String) and assign it as the DataSource.
Private myLBItems As New List(Of String)
...
' fake items to add
myLBItems.Add("Foo")
myLBItems.Add("Bar")
myLBItems.Add("Option")
myLBItems.Add("Strict")
lb.DataSource = myLBItems
Using the List as the DataSource, you dont have to copy items from here to there - whatever is in the List will appear in the ListBox. Serialization is simple too:
bf.Serialize(fs, myLBItems)
Since Deserializing returns an Object, you need to cast it (Option Strict):
myLBItems = CType(bf.Deserialize(fs), List(Of String))
Note: This may not be doing what you want at all. Your code is serializing what is in the ListBox after converting it to String. Later, it looks like you want to Deserialize to a MySettings Type.
If MySettings is something like a Name and Value pair (or collection of them), probably half the data and all the Type information will have been lost.
I have a web service,which return data in byte array.Now i want to read that data in my console project.How can i do that,i already add the desire references to access that web service.I am using vb.net VS2012.Thanks.My web service method is as follow.
Public Function GetFile() As Byte()
Dim response As Byte()
Dim filePath As String = "D:\file.txt"
response = File.ReadAllBytes(filePath)
Return response
End Function
Something like,
Dim result As String
Using (Dim data As New MemoryStream(response))
Using (Dim reader As New StreamReader(data))
result = reader.ReadToEnd()
End Using
End Using
if you knew the encoding, lets say it was UTF-8 you could do,
Dim result = System.Text.UTF8Encoding.GetString(response)
Following on from your comments, I think you are asserting this.
Dim response As Byte() 'Is the bytes of a Base64 encoded string.
So, we know all the bytes will be valid ASCII (because its Base64,) so the string encoding is interchangable.
Dim base64Encoded As String = System.Text.UTF8Encoding.GetString(response)
Now, base64Encoded is the string Base64 representation of some binary.
Dim decodedBinary As Byte() = Convert.FromBase64String(base64Encoded)
So, we've changed the encoded base64 into the binary it represents. Now, because I can see that in your example, you are reading a file called "D:/file.txt" I'm going to make the assumption that the contents of the file is a character encoded string, but I don't know the encoding of the string. The StreamReader class has some logic in the constructor that can make an educated guess at character encoding.
Dim result As String
Using (Dim data As New MemoryStream(decodedBinary))
Using (Dim reader As New StreamReader(data))
result = reader.ReadToEnd()
End Using
End Using
Hopefully, now result contains the context of the text file.
I'm trying to set the user agent for a request with XmlRead. I googled a lot about this and couldn't find the answer. Here is my chunk of code:
Dim RssData As DataSet
Dim Title As String
Dim Url As String
Dim Stream As String
Dim buffer As Integer
RssData = New DataSet()
RssData.ReadXml("http://localhost/user_agent.php")
buffer = 0
For Each RssRow As DataRow In RssData.Tables("entry").Rows
Title = Microsoft.VisualBasic.Left(RssRow.Item("title").ToString, 30)
Stream += Title & vbCrLf
Next
LinkLabel3.Text = Stream
For Each RssRow As DataRow In RssData.Tables("entry").Rows
Title = Microsoft.VisualBasic.Left(RssRow.Item("title").ToString, 30)
Url = RssRow.Item("url").ToString
LinkLabel3.Links.Add(buffer, Title.Length, Url)
buffer = buffer + Title.Length + 2
Next
The part of the code that actually performs the web request is buried pretty deep so you'd have to inherit a bunch of code to do what you asked for. Instead, let me suggest a different path, download the XML on your own with code that's easy to set that header, and then load that into the dataset. The WebClient class lets you set arbitrary headers and has a simple DownloadString method. Once you've got that you can wrap it in a MemoryStream and pass that into ReadXml(). (I couldn't find a way to read the XML as a string, that's why I was forced to read it as Stream.)
''//Will hold our downloaded XML
Dim MyXml As String
''//Create a webclient to download our XML
Using WC As New System.Net.WebClient()
''//Manually set the user agent header
WC.Headers.Add("user-agent", "your user agent here")
''//Download the XML
MyXml = WC.DownloadString("http://localhost/user_agent.php")
End Using
''//Create our dataset object
Dim RssData As New DataSet()
''//There is no direct method to load XML as a string (at least that I could find) so we will
''// convert it to a byte array and load it into a memory stream
Dim Bytes As Byte() = System.Text.Encoding.UTF8.GetBytes(MyXml)
Using MS As New System.IO.MemoryStream(Bytes)
''//Load the stream into the reader
RssData.ReadXml(MS)
End Using
''//Your code continues normally here
I am generating this XML using the serializer in VB.net as shown below
Dim string_writer As New StringWriter()
Dim serializer As New XmlSerializer(GetType(MyClass))
serializer.Serialize(string_writer, addr)
txttest.Text = string_writer.ToString()
though it is returning XML, I see xmlns="http://tempuri.org/ in all the elements, is there anyway I hide this one.
Sure - just pass the default namespace you want to use to the constructor of your XmlSerializer:
Dim string_writer As New StringWriter()
Dim serializer As New XmlSerializer(GetType(MyClass), "")
serializer.Serialize(string_writer, addr)
txttest.Text = string_writer.ToString()
That should do the trick.