In C# while creating a file second time will throw an exception - c#

I am creating a file using file stream, but before that i am applying if condition to see if the file exist or not. When i click on button and if supppose file is there it deletes the file. Its ok, and again if i press the button the file gets created. At first time it works well.
Now the file is created, again if I press the button and it should delete but it is trhowing an exception saying that*The process cannot access the file 'C:\Hello1' because it is being used by another process.*
Below is my code
private void button2_Click(object sender, EventArgs e)
{
string fileName = #"C:\Hello1";
if
(File.Exists(fileName))
{
File.Delete(fileName);
MessageBox.Show("File is deleted");
}
else
{
FileInfo createFile = new FileInfo(fileName);
FileStream create = createFile.Create();
MessageBox.Show("Created");
}
}
So why I am not able to delete second time, My text file is not open also but still it is showing the exception.

You're never closing your stream that created the file. Put your FileStream in a using statement, which will automatically clean up the open file handle.
using(FileStream create = createFile.Create())
{
//code here
}

The file stream is still opened when you're trying second time, try this:
private void button2_Click(object sender, EventArgs e)
{
string fileName = #"C:\Hello1";
if
(File.Exists(fileName))
{
File.Delete(fileName);
MessageBox.Show("File is deleted");
}
else
{
FileInfo createFile = new FileInfo(fileName);
using(FileStream create = createFile.Create())
{
MessageBox.Show("Created");
}
}
}

Oh yes i got the answer,
I need to use
private void button2_Click(object sender, EventArgs e)
{
string fileName = #"C:\Hello1";
if
(File.Exists(fileName))
{
File.Delete(fileName);
MessageBox.Show("File is deleted");
}
else
{
FileInfo createFile = new FileInfo(fileName);
FileStream create = createFile.Create();
MessageBox.Show("Created");
create.Close();
}
}
We need to use create.Close();

Here is an example I used to write a local log:
StreamWriter log;
string fpath = string.Format(#"{0}\{1}.txt",GetDirectory(),DateTime.Now.ToString("yyy-MM-dd"));
if (!File.Exists(fpath))
{
log = new StreamWriter(fpath);
}
else
{
log = File.AppendText(fpath);
}
log.WriteLine(string.Format("{0} ==> {1}",DateTime.Now.ToString("MM/dd/yyy HH:mm:ss"), Message));
log.Dispose();
log = null;

Related

Avoid "file in use by another process" IO exception

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.

C# WPF FileSaving Exception encountered

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();
}
}

Creating a text file with user entered name using c#

hi i have a webform where i am trying to create a txt file in a particular directory but i want to the name of the txt file to be entered by the user but I am not getting it how to do it please help
the code below creates a text file with name NameBox.Text.ToString I dont want that please help and thanks.
protected void Page_Load(object sender, EventArgs e)
{
NameLabel.Visible = false;
NameBox.Visible = false;
submit.Visible = false;
}
protected void Button1_Click(object sender, EventArgs e)
{
NameLabel.Visible = true;
NameBox.Visible = true;
submit.Visible = true;
}
protected void submit_Click(object sender, EventArgs e)
{
// string fname = NameBox.Text;
string path = #"D:\NameBox.Text.ToString.txt";
try
{
// Delete the file if it exists.
if (File.Exists(path))
{
// Note that no lock is put on the
// file and the possibility exists
// that another process could do
// something with it between
// the calls to Exists and Delete.
File.Delete(path);
}
// Create the file.
using (FileStream fs = File.Create(path))
{
Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
// Open the stream and read it back.
using (StreamReader sr = File.OpenText(path))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
}
catch (Exception Ex)
{
Console.WriteLine(Ex.ToString());
}
}
}
First, keep in mind that your IIS will not allow you to access your local file System as you expcect in a "console" application, maybe running with local admin rights.
Second, be sware of illegal characters for file names, you need to check or replace it.
And third, what if two users decide to use the same filename?
As Dejan Dakic already mentioned, step back and reconsider, maybe about using a database, like SQLite or something else.
string path = #"D:\NameBox.Text.ToString.txt";
That won't work. if your textfield is called "NameBox" you need to access the value of its text which is not possible within a String.
Try this:
String path = #"D:\" + NameBox.Text + ".txt";
If you're new to programming, I'd suggest to go get a book or some tutorials and get started that way! :)

IO exception is generated when i try to copy from 1 file to other file

I create an empty file and try to copy the contents from an existing to the newly created file. When i do that i am getting an IOexception
private void button1_Click(object sender, EventArgs e)
{
String test = textBox1.Text.ToString();
if (string.IsNullOrEmpty(textBox1.Text))
{
MessageBox.Show("Enter the filename");
}
else
{
StreamWriter File = new StreamWriter(test);
MessageBox.Show(test + " Has been created");
}
}
private void button2_Click(object sender, EventArgs e)
{
String test = textBox1.Text.ToString();
try
{
File.Copy(#"D:\\Study this.txt", test);
}
catch (IOException)
{
MessageBox.Show("IO error occured");
}
}
You will need to close the Stream so in the else statement add File.Close(); that will release the newly created file. That section of the code will now look like this:
StreamWriter File = new StreamWriter(test);
File.Close();
MessageBox.Show(test + " Has been created");
replace line StreamWriter File = new StreamWriter(test); with below
using (File.Create(test)) ;
or with
using (StreamWriter writer = new StreamWriter(test)){}
reason for above change is you need to propery close the opend stream object before the copy.
using block will handle that for you.

How to handle Word close event from WinForms application?

I have a WinForms application and I am looking for a way to do the following:
Click link to create a Word document from a BLOB in the database and open it.
Block the WinForms application until Word is closed.
Handle when Word is closed, check if the document was changed, and persist changes to the database.
The problem I am having is not creating the Word document and opening it, but it is hooking to the Word process to know when Word has closed. Is there some libraries to look at for doing this or any tutorials that would show how to accomplish this task?
Please see accepted solution, but here is the code I used to complete my task:
protected static string FilePath { get; set; }
public static void DisplayDocument(byte[] documentBytes, string filePath)
{
FilePath = filePath;
if (documentBytes == null) return;
if (!Directory.Exists(TEMP_FILE_DIRECTORY))
Directory.CreateDirectory(TEMP_FILE_DIRECTORY);
if (File.Exists(FilePath)) File.Delete(FilePath);
try
{
FileStream fs = new FileStream(FilePath, FileMode.Create);
fs.Write(documentBytes, 0, Convert.ToInt32(documentBytes.Length));
fs.Seek(0, SeekOrigin.Begin);
fs.Close();
ProcessStartInfo psi = new ProcessStartInfo(FilePath);
Process process = Process.Start(psi);
process.EnableRaisingEvents = true;
process.Exited += process_Exited;
process.WaitForExit();
}
catch (Exception e)
{
MessageHandler.Show(e.Message, Strings.ErrorOpeningFile);
}
}
private static void process_Exited(object sender, EventArgs e)
{
FileInfo fileInfo = new FileInfo(FilePath);
if(fileInfo.CreationTime.CompareTo(fileInfo.LastWriteTime) < 0)
Debug.WriteLine("File updated, perform database upload here.");
}
You can wait for a process to close using the following code:
process.WaitForExit();
when word will close, you can check if the file is modified and store it in database.

Categories

Resources