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
Related
The code that I have included below successfully writes to a CSV file. But if the CSV file that I am writing to happens to be open in Excel, I get a System.IO.Exception that indicates that "the file is being used by another process."
How can I change my code so that the program will continuing running and wait until the CSV is no longer open in Excel?
private void timer1_Tick(object sender, EventArgs e)
{
int actmonth, actyear, actsecond;
System.DateTime fecha = System.DateTime.Now;
actmonth = fecha.Month;
actyear = fecha.Year;
if (actmonth <= 9)
{
valorfechaact = System.Convert.ToString(actyear) + "00" + System.Convert.ToString(actmonth);
}
else
{
valorfechaact = System.Convert.ToString(actyear) + "0" + System.Convert.ToString(actmonth);
}
actsecond = fecha.Second;
string label;
label = label1.Text;
string at = "#";
string filename = valorfechaact + ".csv";
string ruta3 = System.IO.Path.Combine(at, label, filename);
if (Directory.Exists(label1.Text))
{
StreamWriter wr = new StreamWriter(ruta3, true);
wr.WriteLine("1asd" + actsecond);
wr.Close();
wr.Dispose();
}
else
{
System.Console.WriteLine("no se puede escribir en el archivo");
timer1.Stop();
}
}
You can write a Methode which try to open the File with a FileStream and return a boolean Flag
A possible Solution is
public static class FileInfoExtension
{
public static bool IsLocked(this FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
return true;
}
finally
{
stream?.Close();
}
return false;
}
}
Then you can use it
var fileInfo = new FileInfo(ruta3);
if (!fileInfo.IsLocked())
{
// do code
}
A very simple (and bad) Solution to wait is
while (file.IsLocked())
{
Thread.Sleep(100);
}
General is your Code unclear and difficult to read.
You have much redudant code and few variable are bad named.
Maybe this Guidline can help you https://github.com/dennisdoomen/CSharpGuidelines
Maybe a little bit clearer solution is
private void timer1_Tick(object sender, EventArgs e)
{
var directory = label1.Text;
if (!Directory.Exists(directory))
{
Console.WriteLine("no se puede escribir en el archivo");
timer1.Stop();
return;
}
var now = DateTime.Now;
_valorfechaact = now.Month <= 9 ? $"{now.Year}00{now.Month}" : $"{now.Year}0{now.Month}";
var fullname = Path.Combine("#", directory, $"{_valorfechaact}.csv");
var fileInfo = new FileInfo(fullname);
if (fileInfo.IsLocked())
{
Console.WriteLine($"The File {fullname} is locked!");
return;
}
using (var wr = new StreamWriter(fullname, true))
{
wr.WriteLine("1asd" + now.Second);
}
}
You could take a look at this question:
Checking if an Excel Workbook is open
One of the approaches that are discussed is to simply attempt to access the file. If that throws an exception, you can wait and try again.
If you really want to wait until the workbook is writable you can do that, e.g. by using a while loop (probably you'll want to add a time out, or if relevant alert the user that he/she needs to close the file in Excel).
In code it could be something like:
int someLargeNumberOfIterations = 100000000;
while(FileIsLocked(filepath) && elapsedMs < timeoutMs) {
Thread.SpinWait(someLargeNumberOfIterations);
// Set elapsed
}
// Write the file
where FileIsLocked is a function you write based on the aforementioned post and timeoutMs is some appropriate timeout.
My issue is that I keep seeing a recurring theme with trying to allow my Notepad clone to save a file. Whenever I try to save a file, regardless of the location on the hard disk, the UnauthorizedAccess Exception continues to be thrown. Below is my sample code for what I've done, and I have tried researching this since last night to no avail. Any help would be greatly appreciated.
//located at base class level
private const string fileFilter = "Text Files|*.txt|All Files|*.*";
private string currentPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
private void MenuFileSaveAs_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.DefaultExt = "*.txt";
sfd.Filter = fileFilter;
sfd.AddExtension = true;
sfd.InitialDirectory = currentPath;
sfd.RestoreDirectory = true;
sfd.OverwritePrompt = true;
sfd.ShowDialog();
try
{
System.IO.File.WriteAllText(currentPath,TxtBox.Text,Encoding.UTF8);
}
catch (ArgumentException)
{
// Do nothing
}
catch(UnauthorizedAccessException)
{
MessageBox.Show("Access Denied");
}
}
Change the following lines.
...
if (sfd.ShowDialog() != true)
return;
try
{
using (var stream = sfd.OpenFile())
using (var writer = new StreamWriter(stream, Encoding.UTF8))
{
writer.Write(TxtBox.Text);
}
}
...
I hope it helps you.
You need to get the correct path context and file object from the dialog box once the user has hit 'ok'. Namely verify the user actually hit ok and then use the OpenFile property to see what their file selection is:
if (sfd.ShowDialog.HasValue && sfd.ShowDialog)
{
if (sfd.OpenFile() != null)
{
// convert your text to byte and .write()
sfd.OpenFile.Close();
}
}
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();
}
}
}
}
I have to store the contents of a control between sessions. This is what I do:
private void Window_Closing(object sender, CancelEventArgs e)
{
IsolatedStorageFile f = IsolatedStorageFile.GetUserStoreForAssembly();
using(IsolatedStorageFileStream stream = new IsolatedStorageFileStream("somefilename", FileMode.Create, f))
using(StreamWriter writer = new StreamWriter(stream))
{
foreach(string path in searchFoldersListView.Items)
{
writer.WriteLine(path);
}
}
}
This is attached to the Closing event of the window. When debugging, the control goes through all the items, but when I run the program again, the control is empty. It turns out that when I navigate to the file, it's empty. When I change the code to save to a regular file by putting a File.AppendAllText() in the foreach loop, that file is saved just fine. Why is that?
EDIT: reading event handler:
private void Window_Initialized(object sender, EventArgs e)
{
IsolatedStorageFile f = IsolatedStorageFile.GetUserStoreForAssembly();
using(IsolatedStorageFileStream stream = new IsolatedStorageFileStream("somefilename", FileMode.OpenOrCreate, f))
using(StreamReader reader = new StreamReader(stream))
{
string line = reader.ReadLine();
while(line != null)
{
searchFoldersListView.Items.Add(line);
}
}
}
There is a bug in your method that reads from the file. You only read the first line which is probably null. Try the following:
using(StreamReader reader = new StreamReader(stream))
{
string line = reader.ReadLine();
while(line != null)
{
searchFoldersListView.Items.Add(line);
line = reader.ReadLine();
}
}
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.