I am trying to write text to my txt file. After the first write the application crash with error
Cannot write to a closed TextWriter
My list contains links that the browser opens and I want to save all of them in txt file (like a log).
My code:
FileStream fs = new FileStream(
"c:\\linksLog.txt", FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
for (int i = 0; i < linksList.Count; i++)
{
try
{
System.Diagnostics.Process.Start(browserType, linksList[i]);
}
catch (Exception) { }
using (sw)
{
sw.WriteLine(linksList[i]);
sw.Close();
}
Thread.Sleep((int)delayTime);
if (!cbNewtab.Checked)
{
try
{
foreach (Process process in Process.GetProcesses())
{
if (process.ProcessName == getProcesses)
{
process.Kill();
}
}
}
catch (Exception) { }
}
}
You're in a for loop, but you close and dispose of your StreamWriter on the first iteration:
using (sw)
{
sw.WriteLine(linksList[i]);
sw.Close();
}
Instead, remove that block, and wrap everything in one using block:
using (var sw = new StreamWriter(#"C:\linksLog.txt", true)) {
foreach (var link in linksList) {
try {
Process.Start(browserType, list);
} catch (Exception) {}
sw.WriteLine(link);
Thread.Sleep((int)delayTime);
if (!cbNewtab.Checked) {
var processes = Process.GetProcessesByName(getProcesses);
foreach (var process in processes) {
try {
process.Kill();
} catch (Exception) {}
}
}
}
}
The line
using (sw)
closes/disposes your StreamWriter.
Since you are looping, you dispose an already disposed StreamWriter.
Better to close the StreamWriter outside the loop, after all write operations are finished.
In addition, catching exceptions and ignoring the caught exception is almost always a bad idea. If you can't handle an exception, do not catch it.
The problem is that you are closing you Stream in the loop, should done only after...
FileStream fs = new FileStream("c:\\linksLog.txt", FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
for (int i = 0; i < linksList.Count; i++)
{
try
{
System.Diagnostics.Process.Start(browserType, linksList[i]);
}
catch (Exception)
{
}
// Removed the using blocks that closes the stream and placed at the end of loop
sw.WriteLine(linksList[i]);
Thread.Sleep((int)delayTime);
if (!cbNewtab.Checked)
{
try
{
foreach (Process process in Process.GetProcesses())
{
if (process.ProcessName == getProcesses)
{
process.Kill();
}
}
}
catch (Exception)
{ }
}
}
sw.Close();
That's because you are, indeed, closing your stream in the middle of the loop. You have the using (sw) block in the middle, which will work fine in the first run through the for loop, and then crash. To fix it, just drop the sw.Close() call, and move the using to be outside the for loop:
Dont write the sw.Close() in your code because if the file is closed the code cannot read the file.
Related
I'm having an issue at the moment which I am trying to fix.
Trying to concatenate the values(Free space left in my SSD+ time of execution)after each scan I do (the scans are scheduled)and will be saved in a csv file.
using System;
using System.IO;
namespace SSD
{
public class Program
{
static void Main(string[] args)
{
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
if (d.IsReady == true)
{
var t = d.AvailableFreeSpace;
var AvailableFree = (t / Math.Pow(10, 9)) - 10;
var timeOnly = DateTime.Now;
FileStream ostrm;
StreamWriter writer;
TextWriter oldOut = Console.Out;
try
{
ostrm = new FileStream(#"path.csv", FileMode.OpenOrCreate, FileAccess.Write);
writer = new StreamWriter(ostrm);
writer.Write(AvailableFree +","+ timeOnly);
}
catch (Exception e)
{
Console.WriteLine("Cannot open file.csv for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(writer);
Console.SetOut(oldOut);
writer.Close();
ostrm.Close();
Console.WriteLine("Done");
while (true) { }
}
}
}
}
}
}
May anyone tell me what I am doing wrong?
Kind regards
I'm trying to delete the files in a directory, but I get errors when attempting to remove the files which are currently in use. Is there a way to skip the files that are currently in use and delete the rest of them? Thanks.
foreach(var file in Directory.GetFiles(tempPath))
{
File.Delete(file);
}
That's the code I have so far, not sure how to go about this.
you can check by try catch
private bool IsLocked(string filePath)
{
FileInfo f = new FileInfo(filePath);
FileStream stream = null;
try
{
stream = f.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException ex)
{
return true;
}
finally
{
if (stream != null)
stream.Close();
}
return false;
}
public void RemoveFile(string folderPath)
{
foreach (var file in Directory.GetFiles(folderPath))
{
if (!IsLocked(file))
{
File.Delete(file);
}
}
}
I think the easier way is surrounding your code with a try-catch block. Something like this:
foreach(var file in Directory.GetFiles(tempPath))
{
try
{
File.Delete(file);
}
catch (Exception)
{
//Decide what you want to do here, you can either
//ask user to retry if the file is in use
//Or ignore the failure and continue, or...
}
}
Wrap File.Delete in a try { } catch block
I have a windows form project in which I zip a folder. The form freezes for 3-4 seconds and then the operation is done.
private void ZipSafe(string p_FolderName, string p_ArchiveName)
{
try
{
if (File.Exists(p_ArchiveName))
File.Delete(p_ArchiveName);
string[] l_DataSet = Directory.GetFiles(p_FolderName, "*.txt");
using (ZipArchive l_Zip = ZipFile.Open(p_ArchiveName, ZipArchiveMode.Create))
{
foreach (string l_File in l_DataSet)
{
using (FileStream l_Stream = new FileStream(l_File, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite))
{
ZipArchiveEntry l_ZipArchiveEntry = l_Zip.CreateEntry(Path.GetFileName(l_File), CompressionLevel.Optimal);
using (Stream l_Destination = l_ZipArchiveEntry.Open())
{
l_Stream.CopyTo(l_Destination);
}
}
}
l_Zip.Dispose();
}
}
catch (System.Exception e)
{
using (StreamWriter sw = new StreamWriter(#"C:\Users\**\Documents\ErrorZip.txt"))
{
string l = e.ToString();
sw.WriteLine(l);
sw.Close();
}
}
}
I call this function when clicking on a button. I have tried to use the debugger to understand what's going on here. The freeze happens during the second iteration of the for-each loop, for the following line of code:
l_Stream.CopyTo(l_Destination);
I know there has been a lot of post about zipping folders in c#, still I hope my question is relevant. Any help would be great, thank in advance guy.
Have a good day,
vbvx
This happens because you are using the UI thread to carry out the operation. You need to run the operation on another thread to leave the UI thread free (i.e. stopping your application from freezing).
try:
private void ZipSafe(string p_FolderName, string p_ArchiveName)
{
Task.Factory.StartNew(() =>
{
try
{
if (File.Exists(p_ArchiveName))
File.Delete(p_ArchiveName);
string[] l_DataSet = Directory.GetFiles(p_FolderName, "*.txt");
using (ZipArchive l_Zip = ZipFile.Open(p_ArchiveName, ZipArchiveMode.Create))
{
foreach (string l_File in l_DataSet)
{
using (FileStream l_Stream = new FileStream(l_File, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite))
{
ZipArchiveEntry l_ZipArchiveEntry = l_Zip.CreateEntry(Path.GetFileName(l_File), CompressionLevel.Optimal);
using (Stream l_Destination = l_ZipArchiveEntry.Open())
{
l_Stream.CopyTo(l_Destination);
}
}
}
l_Zip.Dispose();
}
}
catch (System.Exception e)
{
using (StreamWriter sw = new StreamWriter(#"C:\Users\**\Documents\ErrorZip.txt"))
{
string l = e.ToString();
sw.WriteLine(l);
sw.Close();
}
}
}
}
Basically I'm writing code that creates a new file in the IsolatedStorage, I'm sure that I'm closing the streams correctly but there must be something that's missing, could you have a look at it to make sure I'm not missing something obvious?
Here's my save function, it's where the error is thrown and is called at the end of a game once the user enters his/her name:
public void SaveHighScores(string NewName, int NewScore)
{
SortHighScores(NewName, NewScore);
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
try
{
using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream("HighScores.txt", FileMode.CreateNew, isoStore))
{
using (StreamWriter writer = new StreamWriter(isoStream))
{
for (int i = 0; i < 5; i++)
{
writer.WriteLine(MyScores[i].Name);
writer.WriteLine(MyScores[i].Score);
}
writer.Close();
}
isoStream.Close();
}
}
catch (IsolatedStorageException e)
{
throw e; // "IsolatedStorageException was unhandled" error now occurs here
}
}
And here is my Read Function, it is called once at the beginning of the game during initialisation:
public void ReadHighScores()
{
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
if (isoStore.FileExists("HighScores.txt"))
{
try
{
using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream("HighScores.txt", FileMode.Open, isoStore))
{
using (StreamReader reader = new StreamReader(isoStream))
{
int i = 0;
while (!reader.EndOfStream)
{
MyScores[i].Name = reader.ReadLine();
string scoreString = reader.ReadLine();
MyScores[i].Score = Convert.ToInt32(scoreString);
i++;
}
reader.Close();
}
isoStream.Close();
}
}
catch (IsolatedStorageException e)
{
throw e;
}
}
else
{
if (!failedRead)
{
failedRead = true;
ReadHighScores();
}
}
}
Can anyone shed some light on this?
[EDIT]
Ok so for some reason this now works the first time I call the save game function on a fresh install of the app, however the next time I play or when I restart the game and play again it crashes when it tries to save, which is odd, is FileMode.CreateNew probably where I'm going wrong?
[EDIT]
Yup, FileMode.CreateNew throws an exeption when a file already exists so I added isoStore.DeleteFile("HighScores.txt") before I create the new file, now works like a dream :)
[SOLVED]
FileMode.CreateNew throws an exception when the file already exists, so you have to call isoStore.DeleteFile(string FileName) before creating the new file or alternatively if you don't absolutely need to use FileMode.CreateNew use FileMode.Create instead
If I am using a try/catch/finally block where and how should I initialize variables? For example say I'm trying to use a FileStream . I want to catch any exceptions thrown while creating or using the stream. Then regardless of whether there were any problems or not I want to ensure any stream created is closed.
So I'd do something like this:
System.IO.FileStream fs;
try
{
fs = new System.IO.FileStream("C:\test.txt", System.IO.FileMode.Open);
//do something with the file stream
}
catch (Exception exp)
{
//handle exceptions
}
finally
{
//ERROR: "unassigned local variable fs"
if (fs != null)
{
fs.Close();
}
}
However this gives me an error in the finally block saying unassigned local variable fs. Yet, if I change the declaration of fs to System.IO.FileStream fs = null it works.
Why do I need to explicitly set fs to null? I've also tried declaring fs in the try block, but then I get the error The name fs does not exsist in the current context in finally block.
BTW: I know I could use a Using block, but the point of my question is to understand the correct usage of a try/catch/finally block.
Assign fs = null;
System.IO.FileStream fs = null;
try
{
fs = new System.IO.FileStream("C:\test.txt", System.IO.FileMode.Open);
//do something with the file stream
}
catch (Exception exp)
{
//handle exceptions
}
finally
{
//ERROR: "unassigned local variable fs"
if (fs != null)
{
fs.Close();
}
}
See section 5.3 of the specification.
http://msdn.microsoft.com/en-us/library/aa691172(VS.71).aspx
At a given location in the executable
code of a function member, a variable
is said to be definitely assigned if
the compiler can prove, by static flow
analysis, that the variable has been
automatically initialized or has been
the target of at least one assignment.
With your try/catch/finally, the assignment of the try block cannot be guaranteed when you attempt to access the object in the finally block. As you have seen, you can meet the requirement by assigning an initial value to the variable (null, in this case).
The C# design team feels that making sure you explicitly initialize things is a good idea. I tend to agree; I've been bitten by bugs from uninitialized variables enough in C++.
Initializing fs to null is the correct usage. The compiler wants to ensure that you are reading only initialized variables, to avoid serious mistakes. And it cannot garantee that the initialization in your try block is ever executed
The purist in me would want to do something like this:
void DoSomethingWithStream()
{
try
{
System.IO.FileStream fs = new System.IO.FileStream(#"C:\test.txt", System.IO.FileMode.Open);
try
{
// do something with the file stream
}
catch (Exception ex)
{
// handle exceptions caused by reading the stream,
// if these need to be handled separately from exceptions caused by opening the stream
}
finally
{
// FileStream.Close might throw an exception, so put FileStream.Dispose in a separate try/finally
fs.Dispose();
}
}
catch (Exception ex)
{
// handle exceptions that were either thrown by opening the filestream, thrown by closing the filestream, or not caught by the inner try/catch
}
}
Taken to the extreme, though, this would be messy:
void DoSomethingWithStream_PartDeux()
{
try
{
System.IO.FileStream fs = new System.IO.FileStream(#"C:\test.txt", System.IO.FileMode.Open);
try
{
try
{
// do something with the file stream
}
catch (Exception ex)
{
// handle exceptions caused by reading the stream,
// if these need to be handled separately from exceptions caused by opening the stream
}
finally
{
fs.Close();
}
}
finally
{
// FileStream.Close might throw an exception, so put FileStream.Dispose in a separate try/finally
fs.Dispose();
}
}
catch (Exception ex)
{
// handle exceptions
}
}
Accessing a database could be even worse:
void DoSomethingWithDatabase()
{
var connection = new System.Data.SqlClient.SqlConnection("Connect to mah database!");
try
{
var command = new System.Data.SqlClient.SqlCommand("Get mah data!", connection);
connection.Open();
try
{
var reader = command.ExecuteReader();
try
{
try
{
// read data from data reader (duh)
}
finally
{
reader.Close();
}
}
finally
{
reader.Dispose();
}
}
finally
{
connection.Close();
}
}
finally
{
connection.Dispose();
}
}
But then, in most cases I don't really see a need to explicitly close your streams / connections / data readers if you are going to dispose of them immediately afterward (unless you're just really paranoid). So, the database code above could just as easily be this:
void DoSomethingWithDatabase_PartDeux()
{
using (var connection = new System.Data.SqlClient.SqlConnection("Connect to mah database!"))
{
var command = new System.Data.SqlClient.SqlCommand("Get mah data!", connection);
connection.Open();
using(var reader = command.ExecuteReader())
{
// read data from data reader (duh)
}
}
}
Maybe I've just been tainted from coding with Dr. Wily's evil API. Using the initialize-variable-to-null trick doesn't work with his framework:
void DoSomethingWithDrWilyEvilBoobyTrap()
{
Dr.Wily.Evil.BoobyTrap trap = null;
try
{
trap = new Dr.Wily.Evil.BoobyTrap(Dr.Wily.Evil.Evilness.Very);
// do something with booby trap
}
catch (Exception ex)
{
// handle exceptions
}
finally
{
if (trap != null) // Exception thrown here!
trap.Dispose(); // Exception thrown here as well!
}
}
Here's a sneak peek at some of the souce code in his API:
public enum Evilness
{
Slight,
Moderate,
Very,
}
class BoobyTrap : IDisposable
{
public Evilness Evil { get; protected set; }
public BoobyTrap(Evilness evil)
{
this.Evil = evil;
}
public void DoEvil()
{
// ... snip (sorry, it's just too evil) ...
}
public static bool IsNull(BoobyTrap instance)
{
throw new Exception("I bet you thought this function would work, didn't you? Well it doesn't! You should know whether or not your variables are null. Quit asking me!");
}
public static bool operator !=(BoobyTrap x, object y)
{
if(y == null)
throw new Exception("You cannot check if an instance of a BoobyTrap is null using the != operator. Mwahahaha!!!");
return x.Equals(y);
}
public static bool operator ==(BoobyTrap x, object y)
{
if (y == null)
throw new Exception("You cannot check if an instance of a BoobyTrap is null using the == operator. Mwahahaha!!!");
return x.Equals(y);
}
#region IDisposable Members
public void Dispose()
{
switch (this.Evil)
{
case Evilness.Moderate:
case Evilness.Very:
throw new Exception("This object is cursed. You may not dispose of it.");
}
}
#endregion
}
You are close. I'd set the declaration to be null.
System.IO.FileStream fs = null;
try
{
fs = new System.IO.FileStream("C:\test.txt", System.IO.FileMode.Open);
//do something with the file stream
}
catch (Exception exp)
{
//handle exceptions
}
finally
{
//ERROR: "unassigned local variable fs"
if (fs != null)
{
fs.Close();
}
}
I think that is very acceptable when you can't use a using statement.