The process cannot access file due to opened already - c#

The code running on wince 5.0 / .net framework compact 2.0
Always get a exception says:
the process cannot access the file because it is being used by another process.
Really confused as i already encolse the stream in the using statement,so the filestream should be closed automaticly once leave the using block .
//read text
using (StreamReader sr = File.OpenText(fname))
{
string line;
while ((line = sr.ReadLine()) != null)
{
// append into stringbuilder
sb.Append(line);
sb.Append("\n");
}
}
//write text, below code raise the exception.
//if i comment it and re-run the code,exception disappear
using (StreamWriter sw = File.CreateText(fname))
{
sw.Write(sb.ToString());
}
addition:i just want to update the file, read and write. any better way?

sorry guys, the issue is in my code and i confused you here as i dont share that code.
actually because i wrote this in the very beginning of the program
// f is the fileinfo which point to fname as well
string text = f.OpenText().ReadToEnd();
this created a streamreader, not being assigned to any varible, but it's in the heap.so i ignored.
thanks people helpping here. BTW changed code to this then issue gone
using (StreamReader sr = f.OpenText())
{
string text = sr.ReadToEnd();
}

I tested this code on my computer. There is no problem.
Better way. For read and write full file, you can use File.ReadAllText(fname) and File.WriteAllText(fname). And instead of using \n use Environment.NewLine

Related

Using StreamReader / StreamWriter to grab logs causes program to cease responding

I'm attempting to use StreamReader and StreamWriter to grab a temporary output log (.txt format) from another application.
The output log is always open and constantly written to.
Unhelpfully if the application closes or crashes, the log file ends up deleted - hence the need for a tool that can grab the information from this log and save it.
What my program currently does is:
Create a new .txt file, and stores the path of that file as the
string "destinationFile".
Finds the .txt log file to read, and stores the path of that file as
the string "sourceFile"
It then passes those two strings to the method below.
Essentially I'm trying to read the sourceFile one line at a time.
Each time one line is read, it is appended to destinationFile.
This keeps looping until the sourceFile no longer exists (i.e. the application has closed or crashed and deleted its log).
In addition, the sourceFile can get quite big (sometimes 100Mb+), and this program may be handling more than one log at a time.
Reading the whole log rather than line by line will most likely start consuming a fair bit of memory.
private void logCopier(string sourceFile, string destinationFile)
{
while (File.Exists(sourceFile))
{
string textLine;
using (var readerStream = File.Open(sourceFile,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
using (var reader = new StreamReader(readerStream))
{
while ((textLine = reader.ReadLine()) != null)
{
using (FileStream writerStream = new FileStream(destinationFile,
FileMode.Append,
FileAccess.Write))
using (StreamWriter writer = new StreamWriter(writerStream))
{
writer.WriteLine(textLine);
}
}
}
}
}
The problem is that my WPF application locks up and ceases to respond when it reaches this code.
To track down where, I put a MessageBox just before the writerStream line of the code to output what the reader was picking up.
It was certainly reading the log file just fine, but there appears to be a problem with writing it to the file.
As soon as it reaches the using (FileStream writerStream = new FileStream part of the code, it stops responding.
Is using the StreamWriter in this manner not valid, or have I just gone and dome something silly in the code?
Am also open to a better solution than what I'm trying to do here.
Simply what I understand is you need to copy a file from source to destination which may be deleted at any time.
I'll suggest you to use FileSystemWatcher to watch for source file changed event, then just simply copy the whole file from source to destination using File.Copy.
I've just solved the problem, and the issue was indeed something silly!
When creating the text file for the StreamWriter, I had forgotten to use .Dispose();. I had File.Create(filename); instead of File.Create(filename).Dispose(); This meant the text file was already open, and the StreamWriter was attempting to write to a file that was locked / in use.
The UI still locks up (as expected), as I've yet to implement this on a new thread as SteenT mentioned. However the program no longer crashes and the code correctly reads the log and outputs to a text file.
Also after a bit of refinement, my log reader/writer code now looks like this:
private void logCopier(string sourceFile, string destinationFile)
{
int num = 1;
string textLine = String.Empty;
long offset = 0L;
while (num == 1)
{
if (File.Exists(sourceFile))
{
FileStream stream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (new StreamReader(stream))
{
stream.Seek(offset, SeekOrigin.Begin);
TextReader reader2 = new StreamReader(stream);
while ((textLine = reader2.ReadLine()) != null)
{
Thread.Sleep(1);
StreamWriter writer = new StreamWriter(destinationFile, true);
writer.WriteLine(textLine);
writer.Flush();
writer.Close();
offset = stream.Position;
}
continue;
}
}
else
{
num = 0;
}
}
}
Just putting this code up here in case anyone else is looking for something like this. :)

How do I read from a file?

I'm trying to get my program to read code from a .txt and then read it back to me, but for some reason, it crashes the program when I compile. Could someone let me know what I'm doing wrong? Thanks! :)
using System;
using System.IO;
public class Hello1
{
public static void Main()
{
string winDir=System.Environment.GetEnvironmentVariable("windir");
StreamReader reader=new StreamReader(winDir + "\\Name.txt");
try {
do {
Console.WriteLine(reader.ReadLine());
}
while(reader.Peek() != -1);
}
catch
{
Console.WriteLine("File is empty");
}
finally
{
reader.Close();
}
Console.ReadLine();
}
}
I don't like your solution for two simple reasons:
1)I don't like gotta Cath 'em all(try catch). For avoing check if the file exist using System.IO.File.Exist("YourPath")
2)Using this code you haven't dispose the streamreader. For avoing this is better use the using constructor like this: using(StreamReader sr=new StreamReader(path)){ //Your code}
Usage example:
string path="filePath";
if (System.IO.File.Exists(path))
using (System.IO.StreamReader sr = new System.IO.StreamReader(path))
{
while (sr.Peek() > -1)
Console.WriteLine(sr.ReadLine());
}
else
Console.WriteLine("The file not exist!");
If your file is located in the same folder as the .exe, all you need to do is StreamReader reader = new StreamReader("File.txt");
Otherwise, where File.txt is, put the full path to the file. Personally, I think it's easier if they are in the same location.
From there, it's as simple as Console.WriteLine(reader.ReadLine());
If you want to read all lines and display all at once, you could do a for loop:
for (int i = 0; i < lineAmount; i++)
{
Console.WriteLine(reader.ReadLine());
}
Use the code below if you want the result as a string instead of an array.
File.ReadAllText(Path.Combine(winDir, "Name.txt"));
Why not use System.IO.File.ReadAllLines(winDir + "\Name.txt")
If all you're trying to do is display this as output in the console, you could do that pretty compactly:
private static string winDir = Environment.GetEnvironmentVariable("windir");
static void Main(string[] args)
{
Console.Write(File.ReadAllText(Path.Combine(winDir, "Name.txt")));
Console.Read();
}
using(var fs = new FileStream(winDir + "\\Name.txt", FileMode.Open, FileAccess.Read))
{
using(var reader = new StreamReader(fs))
{
// your code
}
}
The .NET framework has a variety of ways to read a text file. Each have pros and cons... lets go through two.
The first, is one that many of the other answers are recommending:
String allTxt = File.ReadAllText(Path.Combine(winDir, "Name.txt"));
This will read the entire file into a single String. It will be quick and painless. It comes with a risk though... If the file is large enough, you may run out of memory. Even if you can store the entire thing into memory, it may be large enough that you will have paging, and will make your software run quite slowly. The next option addresses this.
The second solution allows you to work with one line at a time and not load the entire file into memory:
foreach(String line in File.ReadLines(Path.Combine(winDir, "Name.txt")))
// Do Work with the single line.
Console.WriteLine(line);
This solution may take a little longer for files because it's going to do work MORE OFTEN with the contents of the file... however, it will prevent awkward memory errors.
I tend to go with the second solution, but only because I'm paranoid about loading huge Strings into memory.

Streamwriter.Writeline and File.WriteAllText writing text out of order

I'm having an issue where I'm writing the contents of several xml files to one file. When I run the program, the output is in the proper format, but the words are out of order. An example of this:
My string is "<s:AttributeType name=\"Shift\" number=\"34\" nullable=\"true\" writeunknown=\"true\">"
So it should print <s:AttributeType name="Shift" number="34" nullable="true" writeunknown="true">
But instead <s:AttributeType name="Shift" writeunknown="true" number="34" nullable="true">
is returned.
Some of the file is written in using File.WriteAllText(#"C:\Users\status.xml", xsh);
Where 'xsh' is a variable containing a string.
The rest is written in using this loop:
foreach (var i in Numbers.GetWSnumber())
{
string contents = "";
string curFile = #"\\production\public\Staus\TStatus\WS" + i.SetId + ".xml";
if (File.Exists(curFile))
{
System.IO.StreamReader file = new System.IO.StreamReader(curFile);
while ((contents = file.ReadLine()) != null)
{
using (StreamWriter sw = File.AppendText(#"C:\Users\status.xml"))
{
sw.WriteLine(contents);
}
}
file.Close();
}
}
Any help is appreciated
The order of XML attributes is not important so I wouldn't worry about it. However, if it's really bugging you I would suggest moving your using statement.
using (StreamWriter sw = File.AppendText(#"C:\Users\status.xml"))
{
sw.WriteLine(contents);
}
Although this is probably optimized so that it works the same as if it were better written, the way you currently have this a new StreamWriter is being allocated and then disposed of with every iteration.
Your using statement should wrap the while loop and not the other way around. This could possibly solve the problem (though I think it's unlikely) as I don't know how the compiler is handling this line. Either way, it's worth changing.

Creating a file (.htm) in C#

I would like to know the best way to create a simple html file using c#.
Is it using something like System.IO.File.Create?
Something like -
using (FileStream fs = new FileStream("test.htm", FileMode.Create))
{
using (StreamWriter w = new StreamWriter(fs, Encoding.UTF8))
{
w.WriteLine("<H1>Hello</H1>");
}
}
I'll say that File.WriteAllText is a stupid-proof way to write a text file for C# >= 3.5.
File.WriteAllText("myfile.htm", #"<html><body>Hello World</body></html>");
I'll even say that File.WriteAllLines is stupid-proof enough to write bigger html without fighting too much with string composition. But the "good" version is only for C# 4.0 (a little worse version is C# >= 2.0)
List<string> lines = new List<string>();
lines.Add("<html>");
lines.Add("<body>");
lines.Add("Hello World");
lines.Add("</body>");
lines.Add("</html>");
File.WriteAllLines("myfile.htm", lines);
// With C# 3.5
File.WriteAllLines("myfile.htm", lines.ToArray());
I would go with File.Create and then open a StreamWriter to that file if you dont have all the data when you create the file.
This is a example from MS that may help you
class Test
{
public static void Main()
{
string path = #"c:\temp\MyTest.txt";
// Create the file.
using (FileStream fs = File.Create(path, 1024))
{
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);
}
}
}
}
Have a look at the HtmlTextWriter class. For an example how to use this class, for example look at http://www.dotnetperls.com/htmltextwriter.
Reading and writing text files and MSDN info. HTML is just a simple text file with *.HTML extension ;)
Simply opening a file for writing (using File.OpenWrite() for example) will create the file if it does not yet exist.
If you have a look at http://msdn.microsoft.com/en-us/library/d62kzs03.aspx you can find an example of creating a file.
But how do you want to create the html file content? If that's just static then you can just write it to a file.. if you have to create the html on the fly you could use an ASPX file with the correct markup and use a Server.Execute to get the HTML as a string.
Yep, System.IO.File.Create(Path) will create your file just fine.
You can also use a filestream and write to it. Seems more handy to write a htm file

How to open a large text file in C#

I have a text file that contains about 100000 articles.
The structure of file is:
.Document ID 42944-YEAR:5
.Date 03\08\11
.Cat political
Article Content 1
.Document ID 42945-YEAR:5
.Date 03\08\11
.Cat political
Article Content 2
I want to open this file in c# for processing it line by line.
I tried this code:
String[] FileLines = File.ReadAllText(
TB_SourceFile.Text).Split(Environment.NewLine.ToCharArray());
But it says:
Exception of type
'System.OutOfMemoryException' was
thrown.
The question is How can I open this file and read it line by line.
File Size: 564 MB (591,886,626 bytes)
File Encoding: UTF-8
File contains Unicode characters.
You can open the file and read it as a stream rather than loading everything into memory all at once.
From MSDN:
using System;
using System.IO;
class Test
{
public static void Main()
{
try
{
// Create an instance of StreamReader to read from a file.
// The using statement also closes the StreamReader.
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
String line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
catch (Exception e)
{
// Let the user know what went wrong.
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
}
Your file is too large to be read into memory in one go, as File.ReadAllText is trying to do. You should instead read the file line by line.
Adapted from MSDN:
string line;
// Read the file and display it line by line.
using (StreamReader file = new StreamReader(#"c:\yourfile.txt"))
{
while ((line = file.ReadLine()) != null)
{
Console.WriteLine(line);
// do your processing on each line here
}
}
In this way, no more than a single line of the file is in memory at any one time.
If you are using .NET Framework 4, there is a new static method on System.IO.File called ReadLines that returns an IEnumerable of string. I believe it was added to the framework for this exact scenario; however, I have yet to use it myself.
MSDN Documentation - File.ReadLines Method (String)
Related Stack Overflow Question - Bug in the File.ReadLines(..) method of the .net framework 4.0
Something like this:
using (var fileStream = File.OpenText(#"path to file"))
{
do
{
var fileLine = fileStream.ReadLine();
// process fileLine here
} while (!fileStream.EndOfStream);
}

Categories