DownloadFileAsync doesn't download file but completed event is fired? - c#

Alright, I'm at a loss here. I am trying to download a jar file and then make a batch file that runs it. I was able to download this file once before with my code, but now the completed event fires (I think, because the code inside it runs. Sorry I'm new-ish to C#.) instantly but no file is downloaded. I added a new button with nothing but the download code, and it the file was there, but it just showed up as 0KB. Nothing even shows up in Fiddler with my current code. I am using the IP address to skip the DNS checking and I set the proxy to null. (I read somewhere that doing this stops it from hanging. I think. It was something about web proxy auto-detection.) I can verify that the download links (which I don't show here, unless you need it) are real and downloads the file by simply opening it up in a web browser. Anyway, here is a snippet of my code:
WebClient wc1 = new WebClient();
wc1.DownloadFileCompleted += new AsyncCompletedEventHandler(wc1_DownloadFileCompleted);
wc1.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc1_DownloadProgressChanged);
if (cmboboxVersion.SelectedText == ...)
{
stsprgsbar.Style = ProgressBarStyle.Continuous;
stslblStaus.Text = "Downloading files...";
wc1.DownloadFileAsync(new Uri(...), #txtboxFolder.Text + "\\jarfile.jar");
FileStream fs = new FileStream(#txtboxFolder.Text + "\\batfile.bat", FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(...);
sw.Close();
fs.Close();
}
else if (cmboboxVersion.SelectedText == ...)
{
stsprgsbar.Style = ProgressBarStyle.Continuous;
stslblStaus.Text = "Downloading files...";
wc1.DownloadFileAsync(new Uri(...), #txtboxFolder.Text + "\\jarfile.jar");
FileStream fs = new FileStream(#txtboxFolder.Text + "\\batfile.bat", FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(...);
sw.Close();
fs.Close();
}
else
{
stsprgsbar.Style = ProgressBarStyle.Continuous;
stslblStaus.Text = "Downloading files...";
wc1.DownloadFileAsync(new Uri(...), #txtboxFolder.Text + "\\jarfile.jar");
FileStream fs = new FileStream(#txtboxFolder.Text + "\\batfile.bat", FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(...);
sw.Close();
fs.Close();
}
}
public void wc1_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
stsprgsbar.Value = e.ProgressPercentage;
}
public void wc1_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
string BatPath = #txtboxFolder.Text + "\\batfile.bat";
stsprgsbar.Style = ProgressBarStyle.Marquee;
stslblStaus.Text = "Generating files...";
ProcessStartInfo pro = new ProcessStartInfo(BatPath);
//pro.CreateNoWindow = true;
Process.Start(pro);
}

wc1.DownloadFileAsync(new Uri(...), #txtboxFolder.Text + "\\jarfile.jar", #"c:\jarfile.jar"););

Related

Read and write to a file in the same stream

I'm trying to read and write to the same file in a way such that no other program can access the file in between:
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
StreamReader sr = new StreamReader(fs);
StreamWriter sw = new StreamWriter(fs);
newString = sr.ReadToEnd() + "somethingNew";
sw.Write(newString);
fs.Close();
The file is never written to. If I debug I can see that the reader manages to fetch the contents of the file, but the writer does not seem to be able to write to the file. Nothing happens.
I've been looking at this question which seems to be the same as mine. However I'm not able to get it to work.
Just Flush your changes to file, Have sw.Flush(); before closing the stream. like:
string filePath = "test.txt";
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
StreamReader sr = new StreamReader(fs);
StreamWriter sw = new StreamWriter(fs);
newString = sr.ReadToEnd() + "somethingNew";
sw.Write(newString);
sw.Flush(); //HERE
fs.Close();
You may see this post simultaneous read-write a file in C# (open multiple streams for reading and writing)
As mentioned above - just add the Flush() to force the data held in the stream to be written to the file. In a comment you mentioned that you had previously used a 'using' statement but this hadn't worked.
Briefly here's why:
A using statement automatically calls Flush() so you don't have
to.
When you dispose of a StreamReader (or StreamWriter) - like by using a 'using' statement - the inner stream object is also disposed and you lose the handle to the stream.
#EJS a simple static method that you can use to create a new file if it does not exist as well as write to the same file if it does exist
Simple usage
string path = #"C:\SomePath\Name.txt";
if (!System.IO.File.Exists(path))
{
WriteAndOrAppendText(path, "File Created");
}
else if (System.IO.File.Exists(path))
{
WriteAndOrAppendText(path, "New Boot.");
}
private static void WriteAndOrAppendText(string path, string strText)
{
if (!File.Exists(path))
{
using (StreamWriter fileStream = new StreamWriter(path, true))
{
fileStream.WriteLine(strText);
fileStream.Flush();
fileStream.Close();
}
}
else
{
using (StreamWriter fileStream2 = new StreamWriter(path, true))
{
fileStream2.WriteLine(strText);
fileStream2.Flush();
fileStream2.Close();
}
}
}
For being able to create a file, append to it, and read the data in it while still allowing an application to write to it, as I believe you are trying to do, here's a set up I created:
string path = #"C:\SomePath\MyLogFile.txt";
public static string Log(string Message)
{
try
{
if (File.Exists(path) == false)
File.Create(path).Close(); // need this .Close()!!!
logCounter++;
string logString = logCounter + " " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + ": " + Message + Environment.NewLine;
using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.Write(logString);
}
}
return logString; // only necessary so we can return an error in the Exception block
}
catch (Exception ex)
{
return "Logger: Cannot log data. " + ex.ToString();
}
}
It's actually required to use FileAccess.Write if you do FileMode.Append - instead of being able to use FileAccess.ReadWrite - but I found that didn't matter because whatever had been written would have been closed and flushed to the file, and I could still open the file and read it (it wouldn't be locked & blank) using these. I have sw.Write() because I have Environment.NewLine that I added into my logString, but I could've done sw.WriteLine() and removed that, if I had wanted to.
One caveat: File.Exists() has issues if the path is long - can't remember the limit, but just know that there is one, so don't put your file you're writing to several layers deep. Less is always better.

System.IO.MemoryStream cannot access a closed file

I'm new to Streams and in the program i'm developing requires reading data from a hex file.
File=level.dat
The code im using:
FileStream fs;
private void Form1_Load(object sender, EventArgs e)
{
Main("PCWorld\\level.dat");
NbtTree nbtTree = new NbtTree();
Stream s = fs;
Stream destStream = new MemoryStream();
nbtTree.ReadFrom(s);
nbtTree.WriteTo(destStream);
}
void Main():
void Main(string filename)
{
// From MSDN Forums, slightly modified by me
try
{
string fileName = filename;
// Create random data to write to the file.
byte[] dataArray = new byte[100000];
new Random().NextBytes(dataArray);
using (FileStream
fileStream = new FileStream(fileName, FileMode.Create))
{
// Write the data to the file, byte by byte.
for (int i = 0; i < dataArray.Length; i++)
{
fileStream.WriteByte(dataArray[i]);
}
// Set the stream position to the beginning of the file.
fileStream.Seek(0, SeekOrigin.Begin);
// Read and verify the data.
for (int i = 0; i < fileStream.Length; i++)
{
if (dataArray[i] != fileStream.ReadByte())
{
MessageBox.Show("Failed to load " + fileName + " (MCPC.dll)\n\nReason: Failed to read bytes\nResult: Close();\nSoloution: Try again and/or tell DMP9 Software", "Error");
Close();
return;
}
fs = fileStream;
}
}
}
catch (OutOfMemoryException ex)
{
MessageBox.Show("Failed to load NBT++.PC.exe\n\nReason: Out of memory (System.OutOfMemoryException: " + ex.Message + ")\nResult: Close();\nSoloution: Your PC Does not have enough RAM to run NBT++", "Error");
Close();
}
}
My program has a reference of Substrate (https://code.google.com/p/substrate-minecraft/downloads/list) and that does most of the work, but its my code giving
the "Cannot access a closed file"
Any help?
Thanks...
Your problem is in:
Stream s = fs;
The fs filestream is closed in your Main method (using statement disposes the filestream). To fix this you should open a new filestream to read from the file:
Stream s = new FileStream("PCWorld\\level.dat", FileMode.Read);
When using
using (FileStream fileStream = new FileStream(fileName, FileMode.Create))
{...}
you are closing this filestream when you go out scope. So you have to re-open file to read
http://msdn.microsoft.com/en-us/library/yh598w02.aspx

FileMode and FileAccess and IOException: The process cannot access the file 'filename' because it is being used by another process

I have an application A that generates a text file for tracing.
While, an application B needs read the same text file and attach in a mailmessage.
But I get the following error, when application B try read the text file:
IOException: The process cannot access the file 'filename' because it
is being used by another process
Any suggestions ? Maybe better use for FileMode and FileAccess?
Application A
if (File.Exists(nFile2)) File.Delete(nFile2);
traceFile2 = File.Open(nFile2, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
if (traceFile2 != null)
{
var twt2 = new TextWriterTraceListener(traceFile2);
// http://www.helixoft.com/blog/archives/20
try
{
if (twt2.Writer is StreamWriter)
{
(twt2.Writer as StreamWriter).AutoFlush = true;
}
}
catch { }
var indiceTraceFile2 = Trace.Listeners.Add(twt2);
System.Diagnostics.Trace.WriteLine("INICIO: " + DateTime.Now.ToString());
Application B
using (FileStream fileStream = File.Open(f, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
{
var messageAttachment = new Attachment(fileStream, Path.GetFileName(f));
msgMail.Attachments.Add(messageAttachment);
}
You need to make sure that both the service and the reader open the log file non-exclusively. Notice line 2 of App A and Line 1 of App B
Application A:
if (File.Exists(nFile2))
File.Delete(nFile2);
traceFile2 = new FileStream(nFile2, FileMode.Open, FileAccess.Write, FileShare.ReadWrite);
if (traceFile2 != null)
{
var twt2 = new TextWriterTraceListener(traceFile2);
// http://www.helixoft.com/blog/archives/20
try
{
if (twt2.Writer is StreamWriter)
{
(twt2.Writer as StreamWriter).AutoFlush = true;
}
}
catch { }
var indiceTraceFile2 = Trace.Listeners.Add(twt2);
System.Diagnostics.Trace.WriteLine("INICIO: " + DateTime.Now.ToString());
and Application B:
using (FileStream fileStream = new FileStream(f, FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
var messageAttachment = new Attachment(fileStream, Path.GetFileName(f));
msgMail.Attachments.Add(messageAttachment);
}
Of course you can read and write from/to the same file at the same time (by different threads/processes).
Here is a sample code. Just see how FileStream is created.
string fname = "a.txt";
//WRITER
Task.Factory.StartNew(() =>
{
var f = new FileStream(fname, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
var s = new StreamWriter(f);
long l = 0;
while (true)
{
s.WriteLine(l++);
s.Flush();
Task.Delay(1000).Wait();
}
});
//READER
Task.Factory.StartNew(() =>
{
Task.Delay(1000).Wait();
var f = new FileStream(fname, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var s = new StreamReader(f);
while (true)
{
var line = s.ReadLine();
if (line == null) { Task.Delay(100).Wait(); continue; };
Console.WriteLine("> " + line + " <");
}
});
It seems that you are not using the Dispose() and Close() methods of StreamWriter class to release the file.
You need to release control of the file from Program A. Try closing or disposing the streamwriter when you finish.
Or you might attempt using as is described in the answer to this question: Releasing access to files

FileStream.WriteLine() is not writing to file

I am trying to make a simple software which stores data in a TXT log file.
This is my code
FileStream fs = null;
StreamWriter fw = null;
try
{
fs= new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"/textme.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
fw = new StreamWriter(fs);
fw.Write("sadadasdsadsadsadas");
for (int i = 0; i < AnimalShelter.AnimalList.Count; i++)
{
fw.WriteLine("<chipNr>" + AnimalShelter.AnimalList[i].ChipRegistrationNumber + "<chipNr>");
Console.WriteLine("<chipNr>" + AnimalShelter.AnimalList[i].ChipRegistrationNumber + "<chipNr>");
}
}
catch(IOException)
{
MessageBox.Show("ERROR THROWN");
}
finally
{
if (fs!= null) fs.Close();
// if (fw != null) fw.Close();
}
What I achieved is: the file gets created, but nothing gets written in it.
I checked a lot of posts but I could not find any particular help.
Adding a call to Flush the stream works. This is because you are wrapping the FileStream. StreamWriter will write to the FileStream, but you need to indicate when to send the Stream to the actual file. Also, you can exchange your try finally with a using:
try
{
using (var fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"/textme.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var fw = new StreamWriter(fs))
{
fw.Write("sadadasdsadsadsadas");
for (int i = 0; i < AnimalShelter.AnimalList.Count; i++)
{
fw.WriteLine("<chipNr>" + AnimalShelter.AnimalList[i].ChipRegistrationNumber + "<chipNr>");
Console.WriteLine("<chipNr>" + AnimalShelter.AnimalList[i].ChipRegistrationNumber + "<chipNr>");
}
fw.Flush(); // Added
}
}
}
catch(IOException)
{
MessageBox.Show("ERROR THROWN");
}
Enclose your StreamWriter in an using block to be sure that everything is correctly closed at the end of the file usage, also I don't think you need to create a FileStream for this to work.
try
{
string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "textme.txt")
using(fw = new StreamWriter(fileName, true))
{
......
}
}
catch(IOException)
{
MessageBox.Show("ERROR THROWN");
}
Note that the StreamWriter has a constructor that accepts two parameters, the name of the file to create/open and a flag to indicate that the file should be opened in append mode or overwritten
See StreamWriter docs
Always use using (as mentioned already) and you won't run into problems (or have to think about it)...
using (FileStream fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/textme.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
using (StreamWriter fw = new StreamWriter(fs))
{
fw2.Write("sadadasdsadsadsadas");
}
(also you could have closed the writer instead of filestream which should've worked)
The problem is as I far as I can tell...
FileStream.Close is actually Stream.Close - and that calls Dispose but it ain't virtual, so does some general cleanup.
FileStream.Dispose which is called implicitly when you use using - does specific Flush and then Close/Dispose - so does proper specific cleanup.
You can avoid any of that via using as that is generally recommended pattern (and frankly never got me into any of these)
Indeed, Flush() is the answer; however, I would use File.WriteAllLines() instead.
try
{
var fileName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"/textme.txt";
var lines = AnimalShelter.AnimalList.Select(o=> "<chipNr>" + o.ChipRegistrationNumber + "</chipNr>");
File.WriteAllLines(fileName, lines);
foreach(var line in lines)
Console.WriteLine(line);
}
catch(IOException)
{
MessageBox.Show("ERROR THROWN");
}
Try using this - just replace the array:
try
{
using (Stream fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/textme.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamWriter sw = new StreamWriter(fs))
{
int[] test = new int[] { 0, 12, 23, 46 };
sw.Write("sadadasdsadsadsadas");
for (int i = 0; i < test.Length; i++)
{
sw.WriteLine("<chipNr>" + test[i] + "<chipNr>");
Console.WriteLine("<chipNr>" + test[i] + "<chipNr>");
}
sw.Close();
}
fs.Close();
}
}
catch (IOException)
{
MessageBox.Show("ERROR THROWN");
}

Writing to isolated storage in windows phone 7

I am trying to read from the isolated storage if the file is exist it will delete the whole file and directories before recreating the file.
Then if the file does not exist it will create the file and directories.
Below is my code: I got a error of opertion not permitted on isolated storage at write file
int indexQues;
string rate;
string[] queSplit;
string[] rateSplit;
private void saveBtn_Click(object sender, RoutedEventArgs e)
{
indexQues = queListPicker.SelectedIndex;
rate = rateListPicker.SelectedItem.ToString();
IsolatedStorageFile myStore = IsolatedStorageFile.GetUserStoreForApplication();
try
{
//For question
StreamReader readFileQue = new StreamReader(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Open, myStore));
//For passing rate
StreamReader readFileRate = new StreamReader(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Open, myStore));
String queText = readFileQue.ReadLine();
queSplit = queText.Split(new char[] { '^' });
String rateText = readFileRate.ReadLine();
rateSplit = rateText.Split(new char[] { '^' });
readFileQue.Close();
readFileRate.Close();
int noOfQueInDB = queSplit.Count();
int noOfRateInDB = rateSplit.Count();
MessageBox.Show(noOfQueInDB.ToString());
//if (noOfQueInDB == 2)
//{
myStore.DeleteFile("SettingFolder\\queSetting.txt");
myStore.DeleteFile("SettingFolder\\rateSetting.txt");
myStore.DeleteDirectory("SettingFolder");
MessageBox.Show("Deleted all");
myStore.CreateDirectory("SettingFolder");
//Retrieve the content of "noOfQues"
//And write it into queSetting.txt
StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Create, myStore));
writeFile.Write(indexQues);
// writeFile.Write("^" + indexQues);
writeFile.Close();
StreamWriter writeFile1 = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\rateSetting.txt", FileMode.Create, myStore));
writeFile1.Write(rate);
writeFile1.Close();
MessageBox.Show("Setting Saved");
MessageBox.Show(indexQues.ToString());
MessageBox.Show(rate);
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
//}
}
catch (Exception)
{
myStore.CreateDirectory("SettingFolder");
//Retrieve the content of "noOfQues"
//And write it into queSetting.txt
// ****
// **** The following line throws an exception
// ****
StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Create, myStore));
writeFile.Write(indexQues);
// writeFile.Write("^" + indexQues);
writeFile.Close();
StreamWriter writeFile1 = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\rateSetting.txt", FileMode.Create, myStore));
writeFile1.Write(rate);
writeFile1.Close();
MessageBox.Show("Setting Saved");
MessageBox.Show(indexQues.ToString());
MessageBox.Show(rate);
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}
}
one point - this seems wrong (you open the same file twice ?):
//For question
StreamReader readFileQue = new StreamReader(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Open, myStore));
//For passing rate
StreamReader readFileRate = new StreamReader(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Open, myStore));
second point - you should use Dispose:
readFileQue.Close(); readFileQue.Dispose(); readFileQue = null;
readFileRate.Close(); readFileRate.Dispose(); readFileRate = null;
third point - user proper FileAccess when creating the files:
StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\rateSetting.txt",
FileMode.Create,
FileAccess.Write,
FileShare.Write,
myStore);
Hope the above helps... if not check whether the Directory is really created...
EDIT:
Are you sure the Exception is thrown from the catch-block ? IF so, then there must have happened some Exception before that - what was that Exception?

Categories

Resources