SharpZipLib - ZipException "System.ArgumentOutOfRangeException" - Why am I getting this exception? - c#

I'm using SharpZipLib to unzip files. My code has been working nicely for all zipfiles except the zip file what i am extracting now...
Got this exception:
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: length
The exception is being thrown at size = s.Read(data, 0, data.Length);
Hereb is my code...
public static void UnzipFile(string sourcePath, string targetDirectory)
{
try
{
using (ZipInputStream s = new ZipInputStream(File.OpenRead(sourcePath)))
{
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
//string directoryName = Path.GetDirectoryName(theEntry.Name);
string fileName = Path.GetFileName(theEntry.Name);
if (targetDirectory.Length > 0)
{
Directory.CreateDirectory(targetDirectory);
}
if (fileName != String.Empty)
{
using (FileStream streamWriter = File.Create(targetDirectory + fileName))
{
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
}
}
}
}
}
catch (Exception ex)
{
throw new Exception("Error unzipping file \"" + sourcePath + "\"", ex);
}
}

Looks like a bug to me. Fortunately, you have access to the code, so you should be able to see exactly where it's going wrong. I suggest you build a debug version of SharpZipLib, break on the line which is throwing the exception, and have a look at what it's actually testing.
It should be fine to read into a 2K buffer even if there's not 2K of data left.
(I wouldn't actually write the code quite how you have, but that's a different matter. I'd also move it into its own utility method - the act of copying all the data from one stream to another is pretty common. There's no need to tie it to zip.)

Looking at the code, you are reading the same set of bytes again (and advancing the position).
size = s.Read(data, 0, data.Length);
An example from here shows that the 2nd argument should be a moving position & not a fixed number.

Change your code int size = 2048; to int size = data.Length;. You won't take OutOfRange exception.
using (FileStream streamWriter = File.Create(targetDirectory + fileName))
{
int size = data.Length;
byte[] data = new byte[size];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
}

Related

How to do a string compare with the incoming message

I know it sounds simple but I got some trouble with it. I am trying to make a system with a pic Microcontroller (MCU) and an xamarin android app. The sending part from app to the pic MCU is solved but when I want to send data from the MCU to the app it won't go as flaweless. I am using a HC-06 as a bluetooth device for receiving and sending messages.
The code for receiving from the MCU to the app is:
public void beginListenForData()
{
try
{
inStream = btSocket.InputStream;
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
Task.Factory.StartNew(() => {
byte[] buffer = new byte[1024];
int bytes;
while (true)
{
try
{
Array.Reverse(buffer, 0, buffer.Length);
bytes = inStream.Read(buffer, 0, buffer.Length);
if (bytes > 0)
{
string valor = Encoding.ASCII.GetString(buffer);
System.Diagnostics.Debug.WriteLine(buffer);
System.Diagnostics.Debug.WriteLine(bytes);
System.Diagnostics.Debug.WriteLine(valor);
if (valor == "D0O")
{
System.Diagnostics.Debug.WriteLine("Vergelijking gelukt!");
break;
}
//Result.Text = Result.Text + "\n" + valor;
}
}
catch (Java.IO.IOException)
{
//Result.Text = string.Empty;
break;
}
}
});
}
As you perhaps could geuss the message I try to sent from the MCU is D0O (valor) when the comparison worked with the incoming message I want to debug write that is was successful with:
System.Diagnostics.Debug.WriteLine("Vergelijking gelukt!");
The next part is for checking what for data is coming in:
System.Diagnostics.Debug.WriteLine(buffer);
System.Diagnostics.Debug.WriteLine(bytes);
System.Diagnostics.Debug.WriteLine(valor);
What I noticed is the strange output (see image):
As you can see the message is cut into 2 parts every time. Does anyone has any idea why and how to solve it?
I did change the array order with:
Array.Reverse(buffer, 0, buffer.Length);
Because I did notice it entered in the wrong order. This did work to put it in the right order.
Little update:
I changed some line of code and it works more "flaweless"
while ((count = inStream.Read(buffer, 0, buffer.Length)) > 0)
But what is strange that the first bit gets sepparated from the rest of the receiving string. I am not sure what causes this problem if anyone has a idea?
Thanks in advance.
I found a solution for the problem I was facing. So I will share my answer and thought process so perhaps other people can use the same.
So what I thought was there is a receiving buffer that saves the incoming char's. If the buffer is read with streamReader.Read it returns an integer of the readed char's. So I made second buffer of the datatype string[].
If the string[0] is empty I would place in my first Char that was read by the streamReader.Read. If the string[0] is NOT empty it means that the first char is already been read so I put the incoming char into string[1]. This means that the message that was split up is now into string[0] and string[1]. So what if I could combine it and save it into a string variable. This was done by: string eindtekst = string.Join("", buf); and this gives me the string in one piece so I can compare it. It is importent to clear the both array's as you're done with the comparing otherwise there would be new data added. And as you perhaps can tell string[0] == null would never be true. So only string[1] get's overridden al the time and that means you're losing out on data.
public void beginListenForData()
{
try
{
inStream = btSocket.InputStream;
streamReader = new StreamReader(inStream);
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
char[] buffer = new char[256];
string[] buf = new string[2];
int bytes;
while (1)
{
try
{
if ((bytes = streamReader.Read(buffer, 0, buffer.Length)) > 0)
{
string tekst = new string(buffer, 0, bytes);
if(buf[0] == null)
{
buf[0] = tekst;
}
else
{
buf[1] = tekst;
}
string eindtekst = string.Join("", buf);
if (eindtekst == "D0O")
{
System.Diagnostics.Debug.WriteLine("Vergelijking gelukt!");
System.Diagnostics.Debug.WriteLine(eindtekst);
Array.Clear(buffer, 0, buffer.Length);
Array.Clear(buf, 0, buf.Length);
writeData("D2O");
}
streamReader.DiscardBufferedData();
}
}
catch (Java.IO.IOException)
{
break;
}
}
}
Thanks for all the help

C# Cyclic redundancy check Exception when reading the stream of a CD

I want to read a CD to write it's content to a file, but I get an IOException (Data error Cyclic Redundancy Check) after a few read/write to my output file.
I'm trying to make an ISO creator program and the disk I read is 500 Mo game CD, and the exception arise after reading about at 1,9 Mo of data. The CD is not broken and perfectly usable.
I don't know if they are limitations with chunk size or buffer size (using 4096 bytes).
I'm very interested by any idea or experience to fix that problem.
EDIT
I get this error with every CD, not only this one. And it's not broken, as I used it just before starting to make the program to install the game it contains.
I use this code to read the CD :
const int BUFFER_SIZE = 4096;
private void MakeISO()
{
_HDEV = NativeMethods.CreateFileR(DRIVE_NAME);
string targetFile = TARGET + "\\" + NAME;
try
{
_FSR = new FileStream(_HDEV, FileAccess.Read, BUFFER_SIZE);
_FSW = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, BUFFER_SIZE);
byte[] buffer = new byte[BUFFER_SIZE];
int length;
while ((length = _FSR.Read(buffer, 0, buffer.Length)) > 0)
{
_FSW.Write(buffer, 0, buffer.Length);
}
// Don't work either
//do
//{
// _FSR.Read(buffer, 0, BUFFER_SIZE);
// _FSW.Write(buffer, 0, BUFFER_SIZE);
//}
//while (_fsw.Position == _fsr.Position);
}
catch (Exception ex)
{
//
}
finally
{
CloseAll();
}
}

Download not working once the size less than buffer length c#

today while doing a logic for downloading large size files, i am facing an error. For downloading what my logic is am spltting the file into 10KB chunks and then integrating it and is downloading.While downloading what happening is like each time am reducing the total size by 10KB , but once the remaining length is less than 10KB my download is getting interuppted. Please find the below code of mine and let me know if any change needed in my logic.
protected void btnDownload_Click(object sender, EventArgs e)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
System.IO.Stream iStream = null;
// Buffer to read 10K bytes in chunk:
byte[] buffer = new Byte[10000];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
// Identify the file to download including its path.
string filepath = "C:\\Users\\GZT00000000000001020\\Desktop\\123.zip";
// Identify the file name.
string filename = System.IO.Path.GetFileName(filepath);
try
{
iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
dataToRead = iStream.Length;
Page.Response.ContentType = "application/octet-stream";
Page.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (Page.Response.IsClientConnected)
{
if( (dataToRead < 10000) && (dataToRead!=-1))
{
length = (int)dataToRead;
buffer = new Byte[length];
dataToRead = -1;
}
else
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 10000);
}
// Write the data to the current output stream.
Page.Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
Page.Response.Flush();
if (dataToRead > 10000)
{
buffer = new Byte[10000];
dataToRead = dataToRead - length;
}
else if(dataToRead!=-1)
{
length =(int)dataToRead ;
buffer = new Byte[length];
}
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
Page.Response.Write("Error : " + ex.Message);
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
}
Page.Response.Close();
}
});
}
You don't call iStream.Read in the branch where dataToRead < 10000

WP7 IsolatedFileStorageStream - Wrong Byte size

Using c#, I am downloading a file from a url the user enters on the phone. When it is writing the file to the IsolatedStorage, it is writing too many bytes to the file and therefore, the program used to open these files will not open.
When I debug, the bit size is 451,258 bytes, but when the file is exported from IsolatedStorage it is 454,656 bytes. It is filling the remaining space with spaces. Is there anyway to adjust this file size? Trim off the extra space at the end and save?
Forgive my ignorance as I am new at C# and WP7 developoment. I would really appreciate the help.
Here is my code :
public void readCompleteCallback(Object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
try
{
//string fileName = txtUrl.Text.Substring(txtUrl.Text.LastIndexOf("/") + 1).Trim();
string fileName = "DownloadedNZB.nzb";
bool isSpaceAvailable = IsSpaceIsAvailable(e.Result.Length);
if (isSpaceAvailable)
{
// Save mp3 to Isolated Storage
using (var isfs = new IsolatedStorageFileStream(fileName,
FileMode.CreateNew,
IsolatedStorageFile.GetUserStoreForApplication()))
{
long fileLen = e.Result.Length;
byte[] b = new byte[fileLen];
e.Result.Read(b, 0, b.Length);
isfs.Write(b, 0, b.Length);
isfs.Flush();
isfs.Close();
MessageBox.Show("File downloaded successfully");
}
}
else
{
MessageBox.Show("Not enough to save space available to download the file");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else
{
MessageBox.Show(e.Error.Message);
}
}
Replace
e.Result.Read(b, 0, b.Length);
isfs.Write(b, 0, b.Length);
isfs.Flush();
isfs.Close();
with
var numberOfBytesRead = e.Result.Read(b, 0, b.Length);
isfs.Write(b, 0, numberOfBytesRead);
isfs.Flush();
isfs.Close();

how to split a wmv file

im doing a application in which i split a wmv file and transfer it to otherlocation(in 'x' kbs) .after the transfer gets completed the file doesnt play,it gives a message as the format is not supported.is there anyother way to do it.
sory i will explain what im doing now
i wrote an remote application,i want to transfer a .wmv file from one machine to other,i want to split the .wmv and send it to the remote machine and use it there.if i try to send the complete file means it will take lot of memory that seems very bad.so i want to split it and send it.but the file doesnt gets played it raises an exception the format is not supported.
the following is the code im doing i just done it in the local machine itself(not remoting):
try
{
FileStream fswrite = new FileStream("D:\\Movie.wmv", FileMode.Create);
int pointer = 1;
int bufferlength = 12488;
int RemainingLen = 0;
int AppLen = 0;
FileStream fst = new FileStream("E:\\Movie.wmv", FileMode.Open);
int TotalLen = (int)fst.Length;
fst.Close();
while (pointer != 0)
{
byte[] svid = new byte[bufferlength];
using (FileStream fst1 = new FileStream("E:\\Movie.wmv", FileMode.Open))
{
pointer = fst1.Read(svid, AppLen, bufferlength);
fst1.Close();
}
fswrite.Write(svid, 0, pointer);
AppLen += bufferlength;
RemainingLen = TotalLen-AppLen;
if(RemainingLen < bufferlength)
{
byte[] svid1 = new byte[RemainingLen];
using (FileStream fst2 = new FileStream("E:\\Movie.wmv", FileMode.Open))
{
pointer = fst2.Read(svid1, 0, RemainingLen);
fst2.Close();
}
fswrite.Write(svid, 0, pointer);
break;
}
}
fswrite.Close();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
You'll probably find Good way to send a large file over a network in C# helpful.
Im going to make the assumtion your spliting the file when your sending it, and not trying to have the wmv in 3 different files on the remote machine.
When your sending the file what you basicly do is this:
Local machine
1) Read 16k bytes ( Or whatever number you prefere )
2) Send those 16k bytes over the network
3) Repeat above steps untill done
Remote machine
1) Listen for a connection
2) Get 16k bytes
3) Write 16k bytes
4) Repeat untill done.
This method will work, but your kind of inventing the wheel again, i would recommend using either something as simple as File.Copy ( Works fine over the network ) or if that does not meet your needs perhaps using a FTP client / server solution ( Plenty of C# examples on the net that can be hosted inside your application ).
i tried this
private void Splitinthread()
{
int bufferlength = 2048;
int pointer = 1;
int offset = 0;
int length = 0;
byte[] buff = new byte[2048];
FileStream fstwrite = new FileStream("D:\\TEST.wmv", FileMode.Create);
FileStream fst2 = new FileStream("E:\\karthi.wmv", FileMode.Open);
int Tot_Len = (int)fst2.Length;
int Remain_Buff = 0;
//Stream fst = File.OpenRead("E:\\karth.wmv");
while (pointer != 0)
{
try
{
fst2.Read(buff, 0, bufferlength);
fstwrite.Write(buff, 0, bufferlength);
offset += bufferlength;
Remain_Buff = Tot_Len - offset;
Fileprogress.Value = CalculateProgress(offset, Tot_Len);
if (Remain_Buff < bufferlength)
{
byte[] buff1 = new byte[Remain_Buff];
pointer = fst2.Read(buff1, 0, Remain_Buff);
fstwrite.Write(buff1, 0, pointer);
Fileprogress.Value = CalculateProgress(offset, Tot_Len);
fstwrite.Close();
fst2.Close();
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
MessageBox.Show("Completed");
}

Categories