I direct the standard output/error of a process and store it in a string which I log to a file.
I have noticed that not all of the standard output is stored in the text file so I must be hitting the size limit of the string.
Does anyone know of an alternative which would help satisfy this issue?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace Logging
{
class Logger
{
private FileStream file = null;
private StreamWriter writer = null;
public Logger(string _path)
{
if (!File.Exists(_path)) File.Create(_path).Dispose();
file = new FileStream(_path, FileMode.Append, FileAccess.Write, FileShare.Write);
writer = new StreamWriter(file);
}
public void Log(string _text)
{
Console.WriteLine(_text);
using (file)
{
writer.WriteLine("[" + DateTime.Now + "] : " + _text);
}
}
}
}
using (file)
You just disposed your file. You can't write to it anymore.
The string type has a limit of 2GB.
Your handling of the file creation and disposal is causing you some difficulty.
Try this for a little cleaner logging code:
const string log = #"logfile path";
public void Log(string _text)
{
try
{
using (TextWriter tw = new StreamWriter(_path, true))
{
tw.WriteLine("[" + DateTime.Now + "] : " + _text);
}
}
catch (Exception)
{
throw;
}
}
Related
I have created a class in C# in .Net 5 with a single function to perform the following:
find emails that are unread in a specific folder.
save the email in text format to a folder in disk.
set the flag on the email message and save the email.
This class works fine. I now want to make this an async method, so that it doesn't freeze my wpf view. That is where I'm having a problem. I have posted the class code below that isn't working.
Any help is appreciated.
'''
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Interop.Outlook;
namespace ASR.WPF.Outlook
{
public class EmailApp
{
public Task<int> FetchMail()
{
Application oApp = new Microsoft.Office.Interop.Outlook.Application();
NameSpace oNS = oApp.GetNamespace("MAPI");
MAPIFolder oFolder = oNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox)
.Folders["_ArcServe"]
.Folders.GetFirst();
int _processCount = 0;
string _folderName = #"c:\work\arcserve\process\";
try
{
foreach (MailItem msg in oFolder.Items)
{
if (msg.UnRead == true)
{
string detail = msg.Body;
string fileTag = String.Format("{0:yyyyMMdd}", msg.ReceivedTime);
string fileName = _folderName + "digest_" + fileTag + ".txt";
// delete existing file if it exists
if (File.Exists(fileName))
{
File.Delete(fileName);
}
// write the new file
File.WriteAllText(fileName, detail);
//msg.UnRead = false;
msg.Save();
_processCount++;
}
}
}
catch (System.Exception ex)
{
}
finally
{
oFolder = null;
oNS = null;
oApp = null;
}
return _processCount;
}
}
}
'''
Your method is not decorated with async, so the compiler wants you to return Task<int> instead of int. Your signature should be public async Task<int> FetchMail(). After changing it you should find in the method all the places where you could await some method. It basically means you should find methods that have Asnyc overloads. You could, for example, use FileStream which has such overloads instead of static File which has not.
E.g.
var buffer = Encoding.UTF8.GetBytes(detail);
using (var fs = new FileStream(fileName, FileMode.OpenOrCreate,
FileAccess.Write, FileShare.None, buffer.Length, true))
{
await fs.WriteAsync(buffer, 0, buffer.Length);
}
However, if it turns out that there is no Async overload for the method that causes most of that freeze, then I suggest you keep this method sync, I mean without Task and async and call it from the WPF using Task.Run or BackgroundWorker.
Is there any way to create a text file using a name that comes from data entered in a form?
string path = #"E:\AppServ\**Example**.txt";
if (!File.Exists(path))
{
File.Create(path);
}
**Example** being the part taken from user inputted data.
Similar to this Console.Writeline("{0}", userData);
Here is an example of how to store files to the logged in users My Documents folder on windows.
You can modify the AppendUserFile function to support other file modes. This version will open the file for Appending if it exists, or create it if it doesn't exist.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
AppendUserFile("example.txt", tw =>
{
tw.WriteLine("I am some new text!");
});
Console.ReadKey(true);
}
private static bool AppendUserFile(string fileName, Action<TextWriter> writer)
{
string path = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
string filePath = Path.Combine(path, fileName);
FileStream fs = null;
if (File.Exists(filePath))
fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read);
else
fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read);
using (fs)
{
try
{
TextWriter tw = (TextWriter)new StreamWriter(fs);
writer(tw);
tw.Flush();
return true;
}
catch
{
return false;
}
}
}
}
}
I'm playing around with C# and I encountered a problem.
When I try to make a new file, the program breaks and says that the file is being used by another process. It's probably something stupid that I overlooked, but I cant figure it out!
Here is my code:
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace myNameSpace
{
public partial class MainWindow : Form
{
public static string folderPath = #"fullpath";
public MainWindow()
{
InitializeComponent();
StoredTb.Text = folderPath;
String[] files = Directory.GetFiles(folderPath);
foreach (string file in files)
myDropDown.Items.Add(Path.GetFileNameWithoutExtension(file));
}
private void myDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
this.BeginInvoke(new MethodInvoker(myDropDown_invokedMethod));
}
private void myDropDown_invokedMethod()
{
string fullpath = MainWindow.folderPath + myDropDown.SelectedText + ".txt";
StreamReader sr = new StreamReader(fullpath);
NameTb.Text = myDropDown.SelectedText;
DescriptionTb.Text = sr.ReadToEnd();
sr.Close();
}
private void SaveBtn_Click(object sender, EventArgs e)
{
File.Create(NameTb.Text + ".txt");
TextWriter tw = new StreamWriter(NameTb.Text + ".txt"); /* this is where the problem occurs */
tw.WriteLine("The very first line!");
tw.Close();
}
}
}
Sorry for the long code snippet, but since I'm not sure where the problem originates from I had to include pretty much everything.
Your problem is that File.Create will open a stream allowing you to do what you like to the file:
http://msdn.microsoft.com/en-us/library/d62kzs03.aspx
A FileStream that provides read/write access to the file specified in path.
Therefore, technically, it is in use already.
Just remove the File.Create altogether. The StreamWriter will handle creating the file if it doesn't exist.
Also, invest in using constructs to properly dispose of your file connections too. Will help avoid this in the future.
As per MSDN the File.Create Method (String) uses a FileStream which in your case is not being closed. Use something like this:
FileStream fs = new FileStream(NameTb.Text + ".txt");
File.Create(fs);
fs.Close();
or #Muctadir Dinar
var fileStream = File.Create(NameTb.Text + ".txt");
//... do all the writing using fileStream
fileStream.Close();
Use
myDropDown_invokedMethod();
instead of
this.BeginInvoke(new MethodInvoker(myDropDown_invokedMethod));
File.Create returns a FileStream object which holds your file. You should use this object for further task.
var fileStream = File.Create(NameTb.Text + ".txt");
//... do all the writing using fileStream
fileStream.Close();
or you could do just
var fs = File.Create(NameTb.Text + ".txt");
fs.Close();
TextWriter tw = new StreamWriter(NameTb.Text + ".txt");
tw.WriteLine("The very first line!");
tw.Close();
Your problem seems to be in SaveBtn_Click event, you are using your destination file twice for writing:
File.Create(NameTb.Text + ".txt");
TextWriter tw = new StreamWriter(NameTb.Text + ".txt");
Remove this line:
File.Create(NameTb.Text + ".txt");
Thats because the File.Create(NameTb.Text + ".txt"); keeps the file open:
try use this instead:
private void SaveBtn_Click(object sender, EventArgs e)
{
using(Stream stream = File.Create(NameTb.Text + ".txt"))
{
TextWriter tw = new StreamWriter(stream); /* this is where the problem was */
tw.WriteLine("The very first line!");
tw.Close();
}
}
This wil force the File.Create to be Disposed when the method has exits. The dispose will close the filehandle (win32 unmanaged handle). Otherwise the file will be closed by the garbage collector, but you never know when.
I see 2 ways:
1)use System.IO.File.WriteAllText http://msdn.microsoft.com/en-us/library/vstudio/8bh11f1k.aspx
2)read about disposing http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
I hope someone can help me. I am a beginner at c# and programming in general and I'm trying to complete this program. Basically it looks in an XML file, grabs all of the occurrences of a specific tag and is supposed to write the File Names plus whatever is between any instances of these two tags. So far I've tried TextWriter, StreamWriter, FileStream and some others and nothing doing what I want. I realise this may be a stupid question but I'm a super noob and need help for my particular case. My code is as follows.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var files = from file in Directory.GetFiles("W:\\SRC\\hDefMl\\1.0\\Instrument_Files")
orderby file
ascending
select file;
StringBuilder sb_report = new StringBuilder();
string delimiter = ",";
sb_report.AppendLine(string.Join(delimiter, "Module", "Generator(s)"));
foreach (var file in files)
{
string filename = Path.GetFileNameWithoutExtension(file);
Console.WriteLine("The HDefML file for {0} contains these EEPROM Generators:", filename);
XDocument hdefml = XDocument.Load(file);
var GeneratorNames = from b in hdefml.Descendants("Generators")
select new
{
name = (string)b.Element("GeneratorName")
};
string description;
foreach (var generator in GeneratorNames)
{
Console.WriteLine(" GeneratorName is: {0}", generator.name);
sb_report.AppendLine(string.Join(delimiter, filename,
generator.name));
}
}
}
You should be able to just do something like this, if the string you have built with your string builder is formatted correctly.
static void WriteToCSV(string str, string path)
{
using (Stream stream = File.Create(path))
using (StreamWriter writer = new StreamWriter(stream))
{
writer.WriteLine(str);
}
}
try{
FileStream FS;
StreamWriter SW;
using (FS = new FileStream("HardCodedFileName.csv", FileMode.Append))
{
using (SW = new StreamWriter(FS))
{
foreach (var generator in GeneratorNames)
{
SW.WriteLine(string.Join(delimiter, filename,
generator.name));
}
}
}
}
catch (Exception e){
Console.Writeline(e.ToString());
}
I have a file path that might exist or might not exist.
I want to create / override the file, and i have this code:
string filePath = GetFilePath();
using (FileStream file = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
xDoc.Save(file);
}
When i call using (FileStream file ...) and the file doesn't exist, it throws an Could not find a part of the path... error.
I am doing something wrong? shouldn't it create the file if doesn't exist?
FileStream can't create intermediate directories that don't exist. This question should help you.
FileMode.OpenOrCreate creates a file if it doesn't exist. If you also need to create the directory:
bool dirExists = System.IO.Directory.Exists(dir);
if(!dirExists)
System.IO.Directory.CreateDirectory(dir);
using(var fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
{
}
OpenOrCreate
Specifies that the operating system should open a file if it exists;
otherwise, a new file should be created.
try this:
void OpenOrCreateFile()
{
try
{
string filePath = GetFilePath();
EnsureFolder(filePath); //if directory not exist create it
using(var fs = new FileStream(filePath, FileMode.OpenOrCreate))
{
//your code
}
}
catch(Exception ex)
{
//handle exception
}
}
void EnsureFolder(string path)
{
string directoryName = Path.GetDirectoryName(path);
if ((directoryName.Length > 0) && (!Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
}
You can use StreamWriter has a boolean parameter append to overwrite the file it contents exits
http://msdn.microsoft.com/en-IN/library/36b035cb.aspx
public StreamWriter(
string path,
bool append
)
You can use the below given code
using System;
using System.IO;
using System.Text;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
string fileName = "test.txt";
string textToAdd = "Example text in file";
using (StreamWriter writer = new StreamWriter(fileName, false))
{
writer.Write(textToAdd);
}
}
}
}