the process cannot access the file, using filewriter - c#

Trying to check if the file is empty or not, and then write something like "the text is empty" into the document.
But whenever I do get the
the process cannot access the file because it is being used by another process
even though I'm closing the file after the write.
What am I missing here?
StreamWriter myWriter1 = new StreamWriter(resultpath);
List<string> a = File.ReadAllLines(path).ToList();
List<string> b = File.ReadAllLines(newPath).ToList();
foreach (string s in a)
{
Console.WriteLine(s);
if (!b.Contains(s))
{
myWriter1.WriteLine(s);
myWriter1.Close();
}
else
{
continue;
}
}
string[] resultfile = File.ReadAllLines(resultpath);
if (resultfile == null || resultfile.Length == 0)
{
myWriter1.WriteLine("Der er ikke nogen udmeldinger idag", true);
}
myWriter1.Close();

You can close & dispose file writer after writing to it in the loop and re-create it when you neet to write to the same file again.
Also note it is better to wrap it into using statement to ensure it wil be closed and set free unmanaged resources automatically (so you don't need to close it in the loop again and again).
List<string> a = File.ReadAllLines(path).ToList();
List<string> b = File.ReadAllLines(newPath).ToList();
using (var myWriter1 = new StreamWriter(resultpath, false))
{
foreach (string s in a)
{
Console.WriteLine(s);
if (!b.Contains(s))
myWriter1.WriteLine(s);
}
}
string[] resultfile = File.ReadAllLines(resultpath);
if (resultfile == null || resultfile.Length == 0)
{
using (var myWriter1 = new StreamWriter(resultpath, true))
{
myWriter1.WriteLine("Der er ikke nogen udmeldinger idag", true);
}
}

Try this code. You were closing the StreamWriter on each line that is in the 2 analized files,but if there is no coincidence, you never close it.
using (var myWriter1 = new StreamWriter(resultpath, true))
{
List<string> a = File.ReadAllLines(path).ToList();
List<string> b = File.ReadAllLines(newPath).ToList();
int coincidences=0;
foreach (string s in a)
{
Console.WriteLine(s);
if (!b.Contains(s))
{
myWriter1.WriteLine(s);
coincidences++;
}
}
if (coincidences == 0)
{
myWriter1.WriteLine("Der er ikke nogen udmeldinger idag", true);
}
}
Also,note that for IDisposable objects it's better to enclose it in a using clause,as it disposes all the resources when finished.

Related

Anonymous Pipe not ending stream?

Hello I am having a strange error with using pipes to communicate between two process. In short everything is working fine with the program except that the client side never closes the stream, meaning the server's streamReader.readLine never returns null, causing the sever process to never terminate. I'm convinced this is a simple issue but I and struggling to find a answer. Here is some relevant code:
Server Side:
using (StreamReader sr = new StreamReader(clientServer))
{
// Display the read text to the console
string temp;
int count = 0;
while ((temp = sr.ReadLine()) != null)
{
if (count == 0)
{
Console.WriteLine("==========Parent Process found text:like==========");
}
Console.WriteLine(temp);
count++;
}
Console.WriteLine("out of while loop");
}
Client Project:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
class PipeClient
{
static void Main(string[] args)
{
try
{
if (args.Length < 3)
{
Console.WriteLine("Invalid number of commandline arguments");
}
else
{
List<string> inputList = new List<string>();
List<string> foundMatchList = new List<string>();
using (PipeStream pipeClientIn =
new AnonymousPipeClientStream(PipeDirection.In, args[0]))
{
using (StreamReader sr = new StreamReader(pipeClientIn))
{
// Display the read text to the console
string temp;
int count = 0;
while ((temp = sr.ReadLine()) != null)
{
if (count == 0)
{
Console.WriteLine("==========Client Process Read Text:==========");
}
Console.WriteLine(temp);
inputList.Add(temp);
count++;
}
foreach (var curtString in inputList)
{
if (curtString.Contains(args[2]))
{
foundMatchList.Add(curtString);
}
}
}
//Console.WriteLine("released sr");
}
// Console.WriteLine("released pipeClientIn");
using (PipeStream pipeClientOut =
new AnonymousPipeClientStream(PipeDirection.Out, args[1]))
{
using (StreamWriter sw = new StreamWriter(pipeClientOut))
{
sw.AutoFlush = true;
foreach (var match in foundMatchList)
{
sw.WriteLine(match);
}
}
}
//Console.WriteLine("released pipeClientOut");
}
}
catch (Exception e)
{
/* if (args.Length == 0)
Console.WriteLine("no arguments");
foreach(String s in args)
{
Console.Write("{0} ", s);
}*/
Console.WriteLine(e.Message);
}
}
}
I've tested and can confirm that the client process terminates.
I attempted to manually flush and close the Client StreamWriter but this did not work.
My overall question is: Why am I never seeing the the "out of while loop" message? And how can fix my client so that it will end the stream?
Did you call clientServer.DisposeLocalCopyOfClientHandle()?
from msdn
The DisposeLocalCopyOfClientHandle method should be called after the
client handle has been passed to the client. If this method is not
called, the AnonymousPipeServerStream object will not receive notice
when the client disposes of its PipeStream object.
hope this helps

The process cannot access the file because it is being used by another process. XML

I am calling below method in a loop with same xmlRequestPath and xmlResponsePath files. Two loop counts it executes fine in the 3rd iteration I am getting exception "The process cannot access the file because it is being used by another process.".
public static void UpdateBatchID(String xmlRequestPath, String xmlResponsePath)
{
String batchId = "";
XDocument requestDoc = null;
XDocument responseDoc = null;
lock (locker)
{
using (var sr = new StreamReader(xmlRequestPath))
{
requestDoc = XDocument.Load(sr);
var element = requestDoc.Root;
batchId = element.Attribute("BatchID").Value;
if (batchId.Length >= 16)
{
batchId = batchId.Remove(0, 16).Insert(0, DateTime.Now.ToString("yyyyMMddHHmmssff"));
}
else if (batchId != "") { batchId = DateTime.Now.ToString("yyyyMMddHHmmssff"); }
element.SetAttributeValue("BatchID", batchId);
}
using (var sw = new StreamWriter(xmlRequestPath))
{
requestDoc.Save(sw);
}
using (var sr = new StreamReader(xmlResponsePath))
{
responseDoc = XDocument.Load(sr);
var elementResponse = responseDoc.Root;
elementResponse.SetAttributeValue("BatchID", batchId);
}
using (var sw = new StreamWriter(xmlResponsePath))
{
responseDoc.Save(sw);
}
}
Thread.Sleep(500);
requestDoc = null;
responseDoc = null;
}
Exception is occurring at using (var sw = new StreamWriter(xmlResponsePath)) in above code.
Exception:
The process cannot access the file 'D:\Projects\ESELServer20130902\trunk\Testing\ESL Server Testing\ESLServerTesting\ESLServerTesting\TestData\Assign\Expected Response\Assign5kMACResponse.xml' because it is being used by another process.
Maybe at the third loop the stream is still being closed, so it tells you that it is non accessible. Try waiting a bit before calling it again in the loop, for example:
while (...)
{
UpdateBatchID(xmlRequestPath, xmlResponsePath);
System.Threading.Thread.Sleep(500);
}
Or, close explicitly the stream instead of leaving the work to the garbage collector:
var sr = new StreamReader(xmlResponsePath);
responseDoc = XDocument.Load(sr);
....
sr.Close();
Instead of using two streams, a Write and a Read stream, try using only a FileStream, since the problem might be that after loading the file the stream remains opened until the garbadge collector actives.
using (FileSteam f = new FileStream(xmlResponsePath))
{
responseDoc = XDocument.Load(sr);
var elementResponse = responseDoc.Root;
elementResponse.SetAttributeValue("BatchID", batchId);
responseDoc.Save(sw);
}

Writing to file using values from an object in C#

My objective with this code is to use the foreach loop to go through each object and write the current string value to a txt file.
I'm using "Woof" and "Bull" as a test. Bull is the string variable in my AverageValues class.
Unfortunately, it currently will not write the value of bull to the file, however, it will create the file.
I think this is something easy to fix, I'm just can't seem to find it right now.
All help would be appreciated!
public void doStuff()
{
AverageValues AVS = new AverageValues();
AVS.Bull = "Woof";
string path = "C:\\users\\kjenks11\\Averages.txt";
FileStream NewFile = File.Create(path);
StreamWriter writeIt = new StreamWriter(NewFile);
List<AverageValues> AV = new List<AverageValues>();
AV.Add(AVS);
foreach (var value in AV)
{
writeIt.Write(value.Bull);
}
NewFile.Close();
}
You need to flush to write the data to the file. You also might consider adding using statements to your writer to free the resources when you're done.
public void doStuff()
{
AverageValues AVS = new AverageValues();
AVS.Bull = "Woof";
string path = "C:\\users\\kjenks11\\Averages.txt";
using (var NewFile = File.Create(path))
{
using (var writeIt = new StreamWriter(NewFile))
{
List<AverageValues> AV = new List<AverageValues> {AVS};
foreach (var value in AV)
{
writeIt.Write(value.Bull);
}
}
}
}
Flush or close the stream before closing the file itself:
foreach (var value in AV)
{
writeIt.WriteLine(value.Bull);
}
writeIt.Flush();
writeIt.Close();
Note on style - when creating a Stream (of any kind), or rather, any object that implements IDisposable, create it with a using statement:
using(var writeIt = new StreamWriter(NewFile))
{
// use writeIt here - it will dispose properly
}
If you use using around your stream, there's no need to call flush and close explicitly. As soon as you leave the using block' scope the stream will be closed and disposed. The close will call flush for you.
public void doStuff()
{
AverageValues AVS = new AverageValues();
AVS.Bull = "Woof";
string path = "C:\\users\\kjenks11\\Averages.txt";
FileStream NewFile = File.Create(path);
List<AverageValues> AV = new List<AverageValues>();
AV.Add(AVS);
using(StreamWriter writeIt = new StreamWriter(NewFile))
{
foreach (var value in AV)
{
writeIt.Write(value.Bull);
}
}
NewFile.Close();
}

How do i use threading in this program?

I've written this console application to search for a particular string from a file and see if its present or not.. But i want to open only the file in the main program. And include 10different threads to find 10 different words simultaneously.. I tried using the thread but i didnt get it right.. How do i do it? could someone help me with the code? This is my program..
class Program
{
static void Main(string[] args)
{
Thread T = new Thread(Finding);
T.Start();
using (System.IO.StreamReader Reader = new System.IO.StreamReader("C://myfile2.txt"))
{
StringBuilder Sb = new StringBuilder();
string fileContent = Reader.ReadToEnd();
if (fileContent.Contains("and"))
{
Console.WriteLine("It is Present");
}
else
{
Console.WriteLine("It is not Present");
}
Console.ReadLine();
}
}
static void Finding()
{
if (fileContent.Contains("hello"))
{
Console.WriteLine("It is Present");
}
else
{
Console.WriteLine("It is not Present");
}
}
}
var text = File.ReadAllText("somePath");
foreach (var word in new[]{"word1", "word2", "word3"})
{
var w = word;
new Thread(() => Console.WriteLine("{0}: {1}",
w,
text.Contains(w) ? "Yes" : "No")).Start();
}
You should know that string can't contain infinite characters, so if the content is too big for a string, you could use File.ReadAllLines("path") into "lines" instead of File.ReadAllText("path") into "text" and replace
text.Contains(w)
with
lines.Any(l => l.Contains(w))
You could also do something sophisticated using File.ReadLines() to avoid reading all lines when not necessary, if you believe that all words are likely to be found.

How to avoid using foreach loop to get the filelist for different reason

Here what am trying to do:
I have a remote server (e.g:svr01,svr02,svr03). Using GetFileList to read the directory get all the files and match with the file name I have then copy to my local drive.
If any files matched then am adding them to an XML file also.
I was trying to do like below
class Program
{
static void Main(string[] args)
{
var getfiles = new fileshare.Program();
string realname = "*main*";
string Location = "SVR01";
bool anymatch = false;
foreach (var file in getfiles.GetFileList(realname,Location))
{anymatch=true;}
if (anymatch == true)
{ baseMeta(); }
foreach (var file in getfiles.GetFileList(realname,Location))
{getfiles.copytolocal(file.FullName); }
}
private FileInfo[] GetFileList(string pattern,string Location)
{
try
{
switch (Location)
{
case "SVR01":
{
var di = new DirectoryInfo(#"\\SVR01\Dev");
return di.GetFiles(pattern);
}
case "SVR02":
{
var di = new DirectoryInfo(#"\\SVR02\Dev");
return di.GetFiles(pattern);
}
case "SVR03":
{
var di = new DirectoryInfo(#"\\SVR03\Prod");
return di.GetFiles(pattern);
}
default: throw new ArgumentOutOfRangeException();
}
}
catch(Exception ex)
{ Console.Write(ex.ToString());
return null;
}
}
private void copytolocal(string filename)
{
string nameonly = Path.GetFileName(filename);
File.Copy(filename,Path.Combine(#"c:\",nameonly),true);
}
private void baseMeta()
{
XmlWriter xmlWrite = XmlWriter.Create(#"c:\basexml");
xmlWrite.WriteStartElement("job");
xmlWrite.WriteElementString("Name", "test");
xmlWrite.WriteElementString("time", DateTime);
xmlWrite.Close();
}
}
but this piece of code worries me because am doing the same process two times, any one please guide me how to avoid this.
foreach (var file in getfiles.GetFileList(realname,Location))
{
anymatch=true;}
if (anymatch == true)
{
baseMeta();
}
foreach (var file in getfiles.GetFileList(realname,Location))
{
getfiles.copytolocal(file.FullName);
}
}
Even am trying to find out if it match anyfile then i quit the first foreach loop generate the basemeta() then goes to next foreach loop to do the rest of the process.
Using LINQ you should be able to easily change your posted code into:
var getfiles = new fileshare.Program();
string realname = "*main*";
string Location = "SVR01";
var fileList = getFiles.GetFileList(realname, Location);
var anymatch = fileList.Any();
if (anymatch) // Or possibly `if (fileList.Any())` if anymatch isn't
// really used anywhere else
baseMeta();
foreach (var file in getfiles.GetFileList(realname,Location))
getfiles.copytolocal(file.FullName);
You'll get the greatest benefit by replacing your GetFileList method with:
private IEnumerable<FileInfo> GetFileList(string pattern,string Location)
{
string directory = string.Empty;
switch (Location)
{
case "SVR01":
directory = #"\\SVR01\Dev";
break;
case "SVR02":
directory = #"\\SVR02\Dev";
break;
case "SVR03":
directory = #"\\SVR03\Prod");
break;
default:
throw new ArgumentOutOfRangeException();
}
DirectoryInfo di = null;
try
{
di = new DirectoryInfo(directory);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
yield break;
}
foreach(var fi in di.EnumerateFiles(pattern))
yield return fi;
}
Use this
var files = getfiles.GetFileList(realname, Location);
if (files.Length > 0)
{
baseMeta();
foreach(var file in files)
{
getfiles.copytolocal(file.FullName);
}
}
Try this:
Create method to check the file existence and do all in single loop.
your statement is not much clear that when you will copy or not.. use
your condition on which you want to copy or create xml entry..
What is your AnyMatch?? If you want to check that Is there any file then use
var fileList = getfiles.GetFileList(realname,Location);
if( fileList.Count() > 0)
{
baseMeta();
}
foreach (var file in fileList)
{
// copy the file if match does not exist..
getfiles.copytolocal(file.FullName);
}
But Foreach loop through collection if it have any item. so you need not to care about the count of the files..
If you want to do entry on every copy as per your code then why you need to check anyMatch etc. It will create entry on every file copy.
foreach (var file in getfiles.GetFileList(realname,Location))
{
baseMeta();
// copy the file
getfiles.copytolocal(file.FullName);
}

Categories

Resources