Using C# File class to edit file, but throwing exception - c#

I am using the File class to edit an HTML file. I need to delete a line of code from it. The way I am doing it is:
if (selectedFileType.Equals("html"))
{
string contentsOfHtml = File.ReadAllText(paramExportFilePath);
//delete part that I don't want
string deletedElement = "string I need to delete";
contentsOfHtml.Replace(deletedElement, "");
File.WriteAllText(paramExportFilePath, contentsOfHtml);
}
However it is throwing the exception: The process cannot access the file 'path\to\file.html' because it is being used by another process.
I am worried that this is happening because either the File.ReadAllText or File.WriteAllText methods are running on the file, even though in the documentation it specifies that they do close the file. So does anyone know what could be causing this?

If this is a file on a live site then there's a good chance that the web server has a lock on it.
Assuming your working in Windows, try using Process Explorer to see what has a lock on the file.

Whenever you are dealing with Stream based objects, you are always better off wrapping in using statements:
String s1;
using (StreamReader r = new StreamReader(paramExportFilePath, Encoding.ASCII))
{
s1 = r.ReadToEnd();
}
String s2 = s1.Replace("string to delete", "replacement string");
using (StreamWriter w = new StreamWriter(paramExportFilePath, false, Encoding.ASCII))
{
w.Write(s2);
}
The using statements ensure that objects are properly closed and, more importantly, disposed.
Note: replace Encoding.ASCII with whatever you like (perhaps UTF8 if it's HTML code).

Related

Input from any file in WPF Application is very Slow

I have a WPF Application which takes an input file path from user and then at the backend open the text file and try to read single character from the file.
fs = File.OpenRead(fileName);
var sr = new StreamReader(fs);
int c;
while ((c = sr.Read()) != -1)
{
Console.Write((char)c); //to check character read from file
try
{
frequencyMap.Add((char)c, 1);
}
catch
{
frequencyMap[(char)c] += 1;
}
}
Here frequencyMap is the dictionary in which character and it's frequency is stored.
This is one method no matter whatever i do the reading from file is always slow even if i try to read the whole text. On output window i see
Area selected is the part of input from the file.
Files upto 2KBs are fine but reading from files like 20KB really gives a hard time.
Now I read that using threads can solve this problem i just don't know how.
My Question is how can i read data from files fastly? if using threads is the solution then how to implement it?
i am new to this so kindly help me.
Thanks
Don't read it by character, read it for example by line, and process each string in a loop. Also Exception is not a way to check if the key exists in the Dictionary.
using (var sr = new StreamReader(fileName))
{
while (!sr.EndOfStream)
{
string s = sr.ReadLine();
Debug.WriteLine(s); //to check string read from file
foreach (char c in s)
{
if (frequencyMap.ContainsKey(c))
frequencyMap[c]++;
else
frequencyMap.Add(c, 1);
}
}
}
Firstly I hope the Console.WrieLine is purely test code. Writing to the console for every character will slow down your processing considerably.
Secondly, it appears from the screen shot you shared that your application is throwing a lot of exceptions. Throwing exceptions is not cheap either in a tight loop.
Thirdly I would recommend you profile your application (visual studio provides a profiler) to help you pin point where exactly your application is spending it’s time.

IO Exception in C#

In my c# application which developed with c# in visual studio 2012 I created a file by this command :
System.IO.File.Create("config.conf");
after that in the next line I want to use the file by this command :
System.IO.StreamReader rd = new System.IO.StreamReader("config.conf");
But I get This exception :
"The process cannot access the file '\config.far' because it is being used by >another process."
I used thread.sleep(2000) to make application wait but still it doesn't answer.
I will appropriate any help.
File.Create creates the file and returns a FileStream holding the file open.
You can do this:
System.IO.File.Create("config.conf").Dispose();
by disposing of the returned stream object, you close the file.
Or you can do this:
using (var stream = File.Create("config.conf"))
using (var rd = new StreamReader(stream))
{
.... rest of your code here
Additionally, since disposing of the StreamReader will also dispose of the underlying stream, you can reduce this to just:
using (var rd = new StreamReader(File.Create("config.conf")))
{
.... rest of your code here
Final question: Why are you opening a newly created stream for reading? It will contain nothing, so there's nothing to read.
using(var conf = System.IO.File.Create("config.conf"))
{
using (var rd = new System.IO.StreamReader(conf))
{
// Do whatever you want to do with the file here
}
}
The problem is that File.Create returns a stream to the file. That is: The file is already opened for you!
You could do this:
using (System.IO.StreamReader rd = new System.IO.StreamReader(System.IO.File.Create("config.conf")))
{
...
}
By the way, this does not really make sense. What do you expect an empty, newly created file to contain?
When working with files, it is always a good idea to dispose of the file once you are done.
This can be done by two different techniques, the most popular one is using a "using" statement:
using (FileStream fileStream = File.Create(fileNamePath))
{
// insert logic here, for example:
fileStream.SetLength(fileSize);
}
The other one, is calling the .Dispose method.
Close the file if it is opened in notepad or something similar.

Is it necessary to close a file after calling ReadAllText?

I am doing the following:
if (File.Exists(filePath))
{
string base64 = File.ReadAllText(filePath);
return new ImageContentDTO
{
ImageContentGuid = imageContentGuid,
Base64Data = base64
};
}
This works perfectly fine. What I want to ask is if I need to Close the file or anything similar after I am done reading from it. And if so, how?
No, you don't have to explicitly close the file, File.ReadAllText takes care of that for you.
The documentation contains this information very explicitly:
This method opens a file, reads each line of the file, and then adds each line as an element of a string. It then closes the file.
[...]
The file handle is guaranteed to be closed by this method, even if exceptions are raised.
You don't need to close anything when using File.ReadAllText since the underling stream reader is closed implicitely.
MSDN: File.ReadAllText
Opens a text file, reads all lines of the file, and then closes the
file.
Here's the implementation in .NET 4 (ILSpy):
string result;
using (StreamReader streamReader = new StreamReader(path, encoding))
{
result = streamReader.ReadToEnd();
}
return result;
The using statement disposes the StreamReader (even on error), that also closes it.
I know this question has been answered and this is almost a year now but for those who search and read this question, I would like to suggest you close a file when done with it, or at least do an investigation like my answer shows.
I am no programming expert but I have come across this situation recently.
I created a WinForms c# program and used File.ReadAllText to copy text to a string. Afterwards I tried to delete the file, directly from the folder not through the program, but I got an error that the file was still open in another program. I then stopped running the program and was able to delete the file.
That's my experience in Visual Studio 2012 Ultimate. It might be supposed to do something different, but that's what it did for me.
When I used StreamReader.ReadToEnd then StreamReader.Close on the same file, I had no problem deleting the file while running the program.
You have to close IDisposable instances only, usually by means of using, e.g.:
// StreamReader is IDisposable and should be Closed/Disposed
// either explicitly or by using
using (StreamReader sr = new StreamReader(filePath)) {
String base64 = sr.ReadToEnd();
...
}
since you don't have an IDisposable instance in your code (File.ReadAllText
returns String which is not IDisposable) you have nothing to Close/Dispose
StreamWriter outputFile = new StreamWriter(#"C:\Users\Marc\Desktop\_App\files\Data" + dat1 + ".txt");
outputFile.WriteLine(sb.ToString());
outputFile.Close();
StreamWriter outputFileex = new StreamWriter(#"C:\Users\Marc\Desktop\_App\files\DataEx" + dat1 + ".txt");
outputFileex.WriteLine(sbex.ToString());
outputFileex.Close();
Here's a working example I just did with a stringbuilder: "sb". If I remove one of those closes' the file gets generated but the file shows up blank with no data. I had to add in a close to get it to work properly.

Debug file used by another process

Using Visual Studio 2010 and im getting "File is used by another process" almost randomly when trying to read a file. Im reading about 10 xml files into memory with the same procedure
The code that breaks is
private static TextReader CreateTextReader(IsolatedStorageFile isolatedStorageFolder, string path)
{
TextReader textReader = null;
if (isolatedStorageFolder == null)
textReader = new StreamReader(path);
else
textReader = new StreamReader(new IsolatedStorageFileStream(path, FileMode.Open, isolatedStorageFolder));
return textReader;
}
The code breaks 10 percent of the time on
textReader = new StreamReader(path);
I personally think its some kind of garbage collection problem, anyone has any tips on how to debug this kind of problem.
Be sure to call .Dispose or .Close on all steam reader operations that could lock the file. That might be your problem as that code works for me as a flat program.
You need to dispose of the TextReader. Use the using statement like
using (TextReader r = CreateTextReader(...))
{
}
Otherwise the file will remain open when you close your application.
EDIT
You're saying in your comments to the question that you're actually already using using - could it be that the file you're trying to read is actually opened by another application? Sometimes antivir solutions lock files while scanning them or stuff like that - will it work after a short while or do you have to reboot or something like that?

Exists, Read and Write in just one step

I'm trying to find out if a file exists, if it does, verify if the css style already exists, if not, write them at the end of the file ...
I'm doing all this already but in 3 steps:
Does the file exist?
FileInfo fi= new FileInfo(Path.Combine(rootPath, "DefaultStyles.css");
If it does, I use TextReader to get the contents
using (TextReader tr = new StreamReader(file))
{
r = tr.ReadToEnd().Contains(".onebyonecard");
tr.Close();
}
Then I write into it if style was not found
using (TextWriter tw = new StreamWriter(file))
{
tw.Write(cssStyle);
tw.Close();
}
Is there a way to do this in one easy open / close, instead needed to open the file over and over?
Well you can open a single stream for read and write - but given that you're reading the whole file, I would personally just open it twice. Note that your current code will overwrite the file, not append to it.
I would personally use the static methods in the File class:
// Elide this into the "if" condition if you want. I've separated it out here,
// but obviously it makes no difference.
bool present = File.Exists(path) &&
File.ReadAllText(path).Contains(".onebyonecard);
if (!present)
{
File.AppendAllText(path, cssStyle);
}
This is simpler than having a read/write stream and creating both a TextReader and a TextWriter over it.
A couple of notes:
By separating the file access, there is a slight risk of a race condition. We could open the file, read the contents, then it could be updated while we decide what to do next. Likewise the file could exist when we perform the check, but then be deleted before it's read. In most applications this risk is so slight as to be irrelevant - only you can say for sure.
The code above could still throw an exception, if the file exists but can't be read/written by the relevant user, or is in use by another process. Normal exception handling style applies - decide to what extent you think you can actually recover from such situations, and act appropriately.
Well, since you are using ReadToEnd() you might as well use:
if (!File.Exists(file) || !File.ReadAllText(file).Contains(".onebyonecard"))
File.AppendAllText(file, cssStyle);
but this still opens it twice. There are APIs that would allow it to be opened once only, but those are binary APIs (Stream etc) - which will work, but are probably overkill for your scenario.
try
{
TextReader tr = new StreamReader(file);
r = tr.ReadToEnd().Contains(".onebyonecard");
tr.Close();
tr.Dispose ();
}
catch { //File is not exists or is used by another application
}

Categories

Resources