Unzip a zip file in silverlight - silverlight

I am trying to develop code to unzip file from the zip file in Silverlight 5. The files are in a directory within the zip file.
I translated this code I found elsewhere from c# to VB since we are a VB shop. It is failing on the fourth line "Object reference not set to an instance of an object.".
I realize now that the problem is that the third line is expecting a relative uri and I am passing it a file, but I don't know how to fix this.
Can you tell me what is wrong with this code. I will also welcome other ideas.
Thanks.
Public Shared Function GetZipContents(ByVal filename As String) As String()
Try
Dim zipStream As System.IO.Stream = New System.IO.MemoryStream()
Dim zipInfo As New StreamResourceInfo(zipStream, Nothing)
Dim streamInfo As StreamResourceInfo = Application.GetResourceStream(zipInfo, New Uri(filename, UriKind.Relative))
Dim fileStream As Stream = streamInfo.Stream
Dim names As New List(Of String)()
Dim reader As New BinaryReader(fileStream)
Do While reader.ReadUInt32() = &H4034B50
' Skip the portions of the header we don't care about
reader.BaseStream.Seek(14, SeekOrigin.Current)
Dim compressedSize As UInteger = reader.ReadUInt32()
Dim uncompressedSize As UInteger = reader.ReadUInt32()
Dim nameLength As Integer = reader.ReadUInt16()
Dim extraLength As Integer = reader.ReadUInt16()
Dim nameBytes() As Byte = reader.ReadBytes(nameLength)
names.Add(Encoding.UTF8.GetString(nameBytes, 0, nameLength))
reader.BaseStream.Seek(extraLength + compressedSize, SeekOrigin.Current)
Loop
' Move the stream back to the begining
fileStream.Seek(0, SeekOrigin.Begin)
Return names.ToArray()
Catch ex As Exception
MessageBox.Show(ex.Message)
Return Nothing
End Try
End Function

There is quick and dirty way to unzip in Silverlight.
Use Application.GetResourceStream Method.
http://msdn.microsoft.com/en-us/library/cc190632(v=vs.95).aspx

Check out my blogpost on this: http://www.sharpgis.net/post/2010/08/25/REALLY-small-unzip-utility-for-Silverlight-e28093-Part-2.aspx

Sorry I would have time to explore the suggestions. I did find a way to accomplish my goal on my own. See the code below. I would be using this code either because the Technical Leader here prefers I do it a different way using a WCF service. Warning I was not able to test this code 100% since I am not planning to use it, but it is close to being right.
Imports ICSharpCode.SharpZipLib.Zip
Public Shared Sub UnZip(ByVal SrcFile As String, ByVal DstFile As String, ByVal BufferSize As Integer)
Try
Dim _FileName As String
Dim _ZipEntry As ZipEntry
Dim _FileStreamOut As FileStream = Nothing
Dim _Done As Boolean = False
Dim _FileStreamIn As New FileStream(SrcFile, FileMode.Open, FileAccess.Read)
Dim _ZipInStream As New ZipInputStream(_FileStreamIn)
Do Until _Done = True
_ZipEntry = _ZipInStream.GetNextEntry()
If IsNothing(_ZipEntry) Then
_Done = True
Exit Do
End If
_FileName = DstFile & "\" & _ZipEntry.Name
_FileName = _FileName.Replace("/", "\")
If Right(_FileName, 1) = "\" Then
If Directory.Exists(_FileName) = False Then
Directory.CreateDirectory(_FileName)
End If
Else
_FileStreamOut = New FileStream(_FileName, FileMode.Create, FileAccess.Write)
Dim size As Integer
Dim buffer(BufferSize - 1) As Byte
Do
size = _ZipInStream.Read(buffer, 0, buffer.Length)
_FileStreamOut.Write(buffer, 0, size)
Loop While size > 0
End If
Loop
_ZipInStream.Close()
_FileStreamOut.Close()
_FileStreamIn.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub

Related

ReadFields() in TextFieldParser throwing exception

I have a bunch of csv files in a folder. Here is a sample:
Item Value
Row1 Val1
Row2 Val2
Row3 Val3
Row4 Val4"
Row5 Val5
I had written a code to plot a chart based on the information available in all the csv file in that folder. Here is my button click event:
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles generatePlot.Click
Dim dirs As FileInfo() = GetFilesInDirectory("*.csv", True) 'Get all the csv file from result folder in descending order (creation date)
Dim diNext As FileInfo
Try
For Each diNext In dirs.Reverse
Using MyReader As New FileIO.TextFieldParser(diNext.FullName)
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(",")
Dim currentRow As String()
While Not MyReader.EndOfData
currentRow = MyReader.ReadFields()
processRow(diNext, currentRow)
End While
End Using
Next
Catch ex As Exception
MessageBox.Show(ErrorToString)
End Try
'Save chart as an image
Chart1.SaveImage(imageSave, System.Drawing.Imaging.ImageFormat.Bmp)
End Sub
If you look at my sample csv, Row4 has a value of Val4". Note the double quote in it. And, I am getting an exception in my code at currentRow = MyReader.ReadFields() which says Line 5 cannot be parsed using the current delimiter. I know that the reason is because of the presence of double quote. Since this is a string array, I thought that I need to create a function to process each item in the array and trim out the double quote. But, I can't do it as the exception is thrown even before I can process the string array.
Any idea on how to solve this?
Hari
A StreamReader can be used to read text files, just look at the example below to achieve your needs:
Note that the MemoryStream and the Writer are not needed for you, just the Reader.
Public Sub ReadTest()
Using MemoryStream As New IO.MemoryStream()
Dim Writer As New IO.StreamWriter(MemoryStream) 'Writing on a memory stream to emulate a File
Writer.WriteLine("Item,Value")
Writer.WriteLine("Row1,Val1")
Writer.WriteLine("Row2,Val2")
Writer.WriteLine("Row3,Val3")
Writer.WriteLine("Row4,Val4""")
Writer.WriteLine("Row5,Val5")
Writer.Flush()
MemoryStream.Position = 0 'Reseting the MemoryStream to Begin Reading
Dim Reader As New IO.StreamReader(MemoryStream) 'Reading from the Memory but can be changed into the File Path
While Not Reader.EndOfStream
Dim Line As String = Reader.ReadLine
Dim Values() = Line.Split(",")
'Values(0) will contain the First Item
'Values(1) will contain the second Item
Values(1).Replace("""", "") 'Remove the quote from the value string
End While
End Using
End Sub
Thanks to the suggestion given by #jmcilhinney and #AugustoQ.
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles generatePlot.Click
Dim dirs As FileInfo() = GetFilesInDirectory("*.csv", True) 'Get all the csv file from result folder in descending order (creation date)
Dim diNext As FileInfo
Dim currentRow As String()
Try
For Each diNext In dirs.Reverse
For Each rawRows As String In File.ReadLines(diNext.FullName)
currentRow = processRawRow(rawRows)
processRow(diNext, currentRow)
Next
Next
Catch ex As Exception
MessageBox.Show(ErrorToString)
End Try
'Save chart as an image
Chart1.SaveImage(imageSave, System.Drawing.Imaging.ImageFormat.Bmp)
End Sub
I had replaced the TextFieldParser completely and used this function:
Private Function processRawRow(ByVal rawRows As String) As String()
rawRows = rawRows.Replace("""", "").Trim()
Dim processedList = rawRows.Split(",")
Return processedList
End Function
And it works perfectly. Thanks everyone...
Hari

Loading file into array using streamreader

I'm trying to get a file and iterate through it using StreamReader and load each line into an array. I know the file is coming in correctly and it is a text file of data coming in lines.
Dim req As WebRequest = WebRequest.Create("http://www.blahahahaha.com/data/myfile.csv")
Dim res As WebResponse = req.GetResponse()
Dim stream As Stream = res.GetResponseStream()
Dim lines2 As String()
Using r As StreamReader = New StreamReader(stream, Encoding.ASCII)
Dim line As String
line = r.ReadLine
Do While (Not line Is Nothing)
lines2(lineCount2) = r.ReadLine
lineCount2 += 1
Loop
End Using
But the resulting array is empty. What am I doing wrong and how do I fix it?
This line:
Dim lines2 As String()
Just declares that lines2 will be a string array. The array itself is not intialized:
Dim lines2(9) As String ' THIS one has elements
But since you likely do not know how many lines there will be, use a List:
Dim Lines As New List(Of String)
Using r As StreamReader = New StreamReader(Stream, Encoding.ASCII)
Dim line As String
line = r.ReadLine
Do Until String.IsNullOrEmpty(line)
Lines.Add(line)
line = r.ReadLine
Loop
End Using
If the calling code really needs an array:
Return Lines.ToArray()
This will return 6 lines as a string array, first line is column names
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim csvAddress As String =
"https://download.microsoft.com/download/4/C/8/4C830C0C-101F-4BF2-8FCB-32D9A8BA906A/Import_User_Sample_en.csv"
Dim Lines As String() = GetCsvData(csvAddress)
For Each line As String In Lines
Console.WriteLine(line)
Next
End Sub
Public Function GetCsvData(ByVal csvAddress As String) As String()
Dim request As WebRequest = WebRequest.Create(csvAddress)
request.Credentials = CredentialCache.DefaultCredentials
Dim response As WebResponse = request.GetResponse()
Dim dataStream As Stream = response.GetResponseStream()
Dim LineList As New List(Of String)
Using r As StreamReader = New StreamReader(dataStream, Encoding.ASCII)
Dim currentLine As String = r.ReadLine
Do While (Not String.IsNullOrWhiteSpace(currentLine))
LineList.Add(currentLine)
currentLine = r.ReadLine
Loop
End Using
Return LineList.ToArray
End Function

ProcessWindowStyle.Hidden in string array

In my VB.net project, I am trying to call up multiple programs using an array to help clean up my code.
Currently, I have this code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles StartServer.Click
Dim proc As New ProcessStartInfo()
Dim prochide As New ProcessStartInfo()
prochide.WindowStyle = ProcessWindowStyle.Hidden
If CheckBox1.CheckState = 1 Then
proc.WorkingDirectory = TextBox1.Text
proc.FileName = "xserver.exe"
Process.Start(proc)
proc.FileName = "yserver.exe"
Process.Start(proc)
proc.FileName = "zserver.exe"
Process.Start(proc)
Else
prochide.WorkingDirectory = TextBox1.Text
prochide.FileName = "xserver.exe"
Process.Start(prochide)
prochide.FileName = "yserver.exe"
Process.Start(prochide)
prochide.FileName = "zserver.exe"
Process.Start(prochide)
End If
End Sub
What this does is allows me to hide the windows so they show up in task manager but the windows don't actually show up.
However, I would prefer to switch with this code or something similar to clean it up:
Dim servers(0 To 2) As String
servers(0) = "xserver.exe"
servers(1) = "yserver.exe"
servers(2) = "zserver.exe"
Then I can simplify the code:
Dim directory As String = TextBox1.Text
For Each fileName As String In servers
Next
However, I cannot figure out how to hide the windows in an array, since the .WindowStyle = ProcessWindowStyle.Hidden does not seem to work with array strings. Is there another way I can do this?Changing the method is fine, I just want to try to clean up the code since it seems a bit bulky right now.
Okay so I've finally checked this out, and this works for me:
Public Class Form1
Dim servers() As String = New String() {"cmd.exe|1", "cmd.exe|1", "cmd.exe|1"}
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim directory As String = TextBox1.Text
Dim prochide As New ProcessStartInfo()
prochide.WorkingDirectory = directory
For Each fileName As String In servers
Dim FileOptions() As String = Split(fileName, "|")
prochide.FileName = FileOptions(0)
prochide.WindowStyle = CType(FileOptions(1), ProcessWindowStyle)
Process.Start(prochide)
Next
End Sub
End Class
When using New String() you cannot declare the array with a limit. So that was our problem. :)
So instead of Dim servers(3)... or Dim servers(0 To 2)... you have to use Dim servers()...

iTextSharp generating corrupted PDF in WPF

I am new to programming with iTextSharp. i have an application that writes in PDF file. File is written in word and than saved in PDF (there are 2 pages). My problem is, that when I want to write on PDF I see the data that was written on but the output PDF is corrupted. I don't understand why PDF gets corrupted?
Public Sub WriteForm(TemplateFilePath As String, NewFilePath As String, data As FormData)
'input output files
Dim oldFile As String = TemplateFilePath
Dim newFile As String = NewFilePath
'if file already exists then delete it
If System.IO.File.Exists(newFile) Then
System.IO.File.Delete(newFile)
End If
' open the reader
Dim reader As New PdfReader(oldFile)
Dim size As Rectangle = reader.GetPageSizeWithRotation(1)
Dim document As New Document(size)
' open the writer
Dim fs As New FileStream(newFile, FileMode.Create, FileAccess.Write)
Dim writer As PdfWriter = PdfWriter.GetInstance(document, fs)
document.Open()
'write data to first page
Me.WriteData(reader, writer, data)
'write second page
Me.AppendCopiedPage(document, writer, reader, 2)
' close the streams
document.Close()
fs.Close()
writer.Close()
reader.Close()
End Sub
'code for WriteData
Private Sub WriteData(reader As PdfReader, writer As PdfWriter, data As FormData)`
Dim cb As PdfContentByte = writer.DirectContent
Dim bf As BaseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1250, BaseFont.EMBEDDED)
cb.SetColorFill(BaseColor.BLACK)
cb.SetFontAndSize(bf, 10)
' create the first page and add it to the pdf
Dim page1 As PdfImportedPage = writer.GetImportedPage(reader, 1)
cb.AddTemplate(page1, 0, 0)
Me.WriteText(cb, data.SID, 110, 653)
...
End Sub

Upload Progressbar with FtpWebRequest

I have a program that uploads files to our server when they are dropped over the form, to make it easy for our customers to get large files to us.
I have it mostly working, but I want to have a progress bar so that the user knows it's working, instead of having it just sit there for 5 minutes while the files upload quietly in the background.
I would be happy to just have the progress bar pulse so it looks the program is working, and not frozen. If I can show actual status then that would be better.
My code:
Private Sub Grid1_Drop(sender As System.Object, e As System.Windows.DragEventArgs) Handles Grid1.Drop
Dim sFileInfo As System.IO.FileInfo
Dim sStatus As String = ""
If e.Data.GetDataPresent("FileDrop") Then
Try
Dim theFiles() As String = CType(e.Data.GetData("FileDrop", True), String())
For Each file As String In theFiles
sFileInfo = New System.IO.FileInfo(file)
If UploadFile(txtUsername.Text, sFileInfo) Then
lstFileList.Items.Add(file & " - Uploaded")
Else
lstFileList.Items.Add(file & " - Upload Failed")
End If
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End Sub
Public Function UploadFile(ByVal User As String, ByVal oFile As FileInfo) As Boolean
Dim ftpRequest As FtpWebRequest
Dim ftpResponse As FtpWebResponse
Try
ftpRequest = CType(FtpWebRequest.Create(Base + User + "/" + oFile.Name), FtpWebRequest)
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile
ftpRequest.Proxy = Nothing
ftpRequest.UseBinary = True
ftpRequest.Credentials = Cred
ftpRequest.KeepAlive = KeepAlive
ftpRequest.EnableSsl = UseSSL
If UseSSL Then ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
Dim fileContents(oFile.Length) As Byte
Using fr As FileStream = oFile.OpenRead
fr.Read(fileContents, 0, Convert.ToInt32(oFile.Length))
End Using
Using writer As Stream = ftpRequest.GetRequestStream
writer.Write(fileContents, 0, fileContents.Length)
End Using
ftpResponse = CType(ftpRequest.GetResponse, FtpWebResponse)
ftpResponse.Close()
ftpRequest = Nothing
Return True
Catch ex As WebException
Return False
End Try
End Function
Have a look at the background worker class. http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx which will free up your ui so you can add in a progress bar control and have it animate while your files are being uploaded

Resources