i want to copy all lines from text a that contain a certain text to file b with a small c# application.
It's already working, but the output file doesn't show special characters like "äöü". I already tried to set the charset to utf-8, but its not working.
Here's my function:
void BtnCnvClick(object sender, EventArgs e)
{
if(File.Exists(txSource.Text)) {
string[] srcFile = File.ReadAllLines(txSource.Text, System.Text.Encoding.UTF8);
StreamWriter w = new StreamWriter(new FileStream(txOut.Text, FileMode.Open, FileAccess.ReadWrite), System.Text.Encoding.UTF8);
for(int i=0; i < srcFile.Length;i++) {
//progressBar1.Value = i/srcFile.Length;
if(i==0&&useHead) {
w.WriteLine(srcFile[i]);
} else {
if(srcFile[i].Contains(txFilter.Text)) {
w.WriteLine(srcFile[i]);
}
}
}
w.Close();
MessageBox.Show("Export successful!");
}
else MessageBox.Show("Please input a valid file name and filter.");
}
// Edit: It's working now, i just had to change it from UTF-8 to Encoding.Default!
Change this:
StreamWriter w = new StreamWriter(new FileStream(txOut.Text, FileMode.Open, FileAccess.ReadWrite), System.Text.Encoding.UTF8);
to this:
StreamWriter w = new StreamWriter(new FileStream(txOut.Text, FileMode.Open, FileAccess.ReadWrite), System.Text.Encoding.Default);
Related
How can I delete text from text file? For example I have some text and every time I would change the text box text in a file will change. This is what I mean:
StreamWriter = sw;
StreamReader = sr;
string path = "file.txt";
string text = txtText.Text;
if(!File.Exists(path))
{
sw = File.CreateText(path)
}
else
{
sw = new StreamWriter(path, true)
}
//here I want to delete previous line
sw.WriteLine(text)
sw.Close()
you have to replace
sw = new StreamWriter(path, true)
with
sw = new StreamWriter(path, false)
since boolean parameter defines append new text or not
and I recommend to use using to dispose the resource after using
if (!File.Exists(path))
{
sw = File.CreateText(path);
}
else
{
sw = new StreamWriter(path, false);
}
using (sw)
{
sw.WriteLine(text);
};
I am trying to create a list using the FileStream/StreamReader method. Everything works fine except the price calculation is reset every time a new line is added.
I believe the issue is with the save method. I am sure it is not caused from functions in my classes, since the price is showing properly. There seems to be an issue when saving the string.
This is my read method:
public static List<Customer> ReadCustomers()
{
// create an empty customer list
List<Customer> customerList = new List<Customer>();
// new Filestream
FileStream fs = null;
// new StreamReader
StreamReader sr = null;
Customer c; // for reading
string line;
string[] fields;
try
{
fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read);
sr = new StreamReader(fs);
while (!sr.EndOfStream)// while there is data
{
line = sr.ReadLine();
fields = line.Split(','); // split sections by commas
c = new Customer(); // initializes customer object
c.AccountNo = Convert.ToInt32(fields[0].Trim());
c.CustomerName = Convert.ToString(fields[1].Trim());
c.CustomerType = Convert.ToChar(fields[2].Trim());
c.CustomerCharge = Convert.ToDecimal(fields[3].Trim());
customerList.Add(c);
}
}
catch (Exception ex)
{
throw ex;
}
finally // always execute
{
if (fs != null) fs.Close(); // close file
}
return customerList;
}
This is where I try to save the string...
public static void SaveCustomers(List<Customer> list)
{
FileStream fs = null;
StreamWriter sw = null;
string line;
try
{
fs = new FileStream(path, FileMode.Create, FileAccess.Write);
sw = new StreamWriter(fs);
foreach (Customer c in list) // for each customer in the list
{
line = c.AccountNo.ToString() + ", " + c.CustomerName.ToString() + ", " +
c.CustomerType.ToString() + ", " + c.CustomerCharge.ToString(); // make a line with data
sw.WriteLine(line); // and write it to the file
}
}
catch(Exception ex)
{
throw ex;
}
finally
{
if (sw != null) sw.Close(); // stream writer close
if (fs != null) fs.Close();
}
}
Calculation:
public override decimal CalculateCharge()
{
decimal peak;
decimal offpeak;
if (Kwh1 <= INDUST_BASE_HOURS)
{
peak = KWH_PEAK_BASE_PRICE;
}
else
{
peak = ((Kwh1 - INDUST_BASE_HOURS) * KWH_INDUST_PEAK) + KWH_PEAK_BASE_PRICE;
}
if (Kwh2 <= INDUST_BASE_HOURS)
{
offpeak = KWH_OFF_PEAK_BASE_PRICE;
}
else
{
offpeak = ((Kwh2 - INDUST_BASE_HOURS) * KWH_INDUST_OFFPEAK) + KWH_OFF_PEAK_BASE_PRICE;
}
return peak + offpeak;
}
In SaveCustomers(), are you sure you want to open the file:
fs = new FileStream(path, FileMode.Create, FileAccess.Write);
You may want:
fs = new FileStream(path, FileMode.Append, FileAccess.Write);
FileMode.Create will destroy the file if it exists.
FileMode.Append will append to an existing file it exists.
Maybe for the purposes of clarity around testing, you output to another file rather than the one you read in.
Try using this by using the append parameter:
new StreamWriter("c:\\file.txt", true);
http://msdn.microsoft.com/en-us/library/36b035cb.aspx
Or you can see related answers here, which had similar problems
C# add text to text file without rewriting it?
I'm use MS-Visual Studio 2015, develop a Winforms application in C#.
What I'm trying to reach is a reader&writer which opens a CSV file with UTF-8 coding, and reads line for line. My program actually reads a line, split it at the semicolons (;) and send that informations to my database. Now it should mark that line as already read, by appending a text or a special sign e.g. ("read" or "done" or "§$%").
Because it's possible that someone or something (ERP-Systems), appends new data to that CSV file. So, the next time my program iterates through that file, it shall only read the line without my special mark.
my program:
foreach (string sFile in Directory.GetFiles(sImportPfad, "*.*", SearchOption.TopDirectoryOnly))
{
var oStream = new FileStream(sFile, FileMode.Append, FileAccess.Write, FileShare.Read);
var iStream = new FileStream(sFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var sw = new System.IO.StreamWriter(oStream);
var sr = new System.IO.StreamReader(iStream);
int c = 0;
// alle Zeilen jedes Files laden
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
String[] splitLine = line.Trim().Split(txtDivider.Text.Trim().ToCharArray());
if (line.Contains("§$%"))
break;
DatenbankEintragAuftragsPool dbEintrag = new DatenbankEintragAuftragsPool();
foreach (myImportFilterObject ob in arrImportFilterObjects)
{
.
.
.
}
String result = Program.myPaletti.AuftragInDieDatenbankSchreiben(dbEintrag);
if (result.Equals("ok"))
{
sw.WriteLine(line + " §$%"); sw.Flush();
}
}
}
My problem is the writer is appending the line+"special mark" to the end of my file.
Additionally I didn't figure out how to read the file with UTF-8 coding.
I appreciate your answers !!
EDIT: ##############
This code would do the trick...
string[] lines = System.IO.File.ReadAllLines("test");
lines[0] = lines[0] + " $%&"; /* replace with whatever you need */
System.IO.File.WriteAllLines("test", lines);
But for my usage it's not recommended to read all lines, 'cause it's possible that the guys never delete any data for the next 20 years.
I'll go further to find a solution line by line...
There are some problems in your code that I will try to solve here
using(var stream = new FileStream(sFile, FileMode.Open, FileAccess.Read)
using(var reader = new StreamReader(stream, Encoding.UTF8))
{
long position = GetFirstNewRecordOfFile(sFile);
stream.Seek(position, SeekOrigin.Begin);
while(!reader.EndOfStream)
{
var line = reader.ReadLine();
// Process line
}
SaveFirstNewRecordOfFile(sFile, stream.Position);
}
Now you just need to figure out where and how to save the position of the file.
If you have a writer that appends data to the file the file might grow to a huge size over time, maybe it is better to truncate or delete the file when it has been read.
I recommend deleting the file since you will not have to loop through a lot of empty files, that will however require that you rename/move the file before processing it to avoid that the writer process appends data to it after you close it but before you delete it.
If you just move the file to a sub folder you can use that as a backup.
My solution now is to create a new file, write into this file, delete the original file and rename the new file.
foreach (string sFile in Directory.GetFiles(sImportPfad, "*.*", SearchOption.TopDirectoryOnly))
{
FileStream iStream;
try
{
using (iStream = new FileStream(sFile, FileMode.Open, FileAccess.Read, FileShare.None))
{
var sr = new System.IO.StreamReader(iStream, Encoding.UTF8);
if (rbCSVfilesMarkieren.Checked)
{
using (var oStream = new FileStream(sFile + "_new", FileMode.Create, FileAccess.Write, FileShare.None))
{
var sw = new System.IO.StreamWriter(oStream, Encoding.UTF8);
int c = 0;
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
String[] splitLine = line.Trim().Split(txtDivider.Text.Trim().ToCharArray());
if (line.Contains("$$$"))
{
sw.WriteLine(line);
sw.Flush();
continue;
}
String result = Program.myPaletti.Irgendwasneues(splitLine, arrImportFilterObjects);
if (result.Equals("ok"))
{
sw.WriteLine(line + "$$$");
sw.Flush();
anzNeueDatensätze++;
}
}
}
}
System.IO.File.Delete(sFile);
System.IO.File.Move(sFile + "_new", sFile);
}
}
}
I also included the UTF-8 coding.
Furthermore I've found a way to block the file I'm reading/writing, by using FileShare.None.
Thank you guys for your help !! I appreciate it !
I'm using a FileStream to lock the File to be not writeable for other processes and also read and write to it, I'm using following method for it:
public static void ChangeOrAddLine(string newLine, string oldLine = "")
{
string filePath = "C:\\test.txt";
FileMode fm = FileMode.Create;
//FileMode fm = FileMode.OpenOrCreate;
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
using (StreamReader sr = new StreamReader(fs))
using (StreamWriter sw = new StreamWriter(fs))
{
List<string> lines = sr.ReadToEnd().Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList();
bool lineFound = false;
if (oldLine != "")
for (int i = 0; i < lines.Count; i++)
if (lines[i] == oldLine)
{
lines[i] = newLine;
lineFound = true;
break;
}
if (!lineFound)
lines.Add(newLine);
sw.Write(string.Join("\r\n", lines));
}
}
I want to overwrite it with the new content but i don't find the right FileMode, using FileMode.OpenOrCreate just appends the new content to the old and FileMode.Create deletes the file-content at the time, the FileStream fm has been initialized, so the file is empty.
I need to just clear the old content at the moment, when i write the new content to it without losing the write-lock on it during the method is running.
OpenOrCreate just appends ...
Because you don't reposition after the reading.
That also shows the main problem with your approach: The FileStream only has one Position, and the Reader and the Writer heavily use caching.
However, as long as you want to replace everything and really need that locking scheme:
using (FileStream fs = new FileStream(filePath,
FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read))
{
using (StreamReader sr = new StreamReader(fs))
{
... // all the reading
}
fs.Position = 0;
using (StreamWriter sw = new StreamWriter(fs))
{
sw.Write(string.Join("\r\n", lines));
}
fs.SetLength(fs.Position); // untested, something along this line
}
and maybe you have to convince the sw and sr to leave their stream open.
But I have to note that the FileShare.Read flag doesn't make too much sense in this scenario. A reader could see al sorts of inconsistent data, including torn lines and broken UTF8 characters.
I have a windows service writes its log in a text file in a simple format.
Now, I'm going to create a small application to read the service's log and shows both the existing log and the added one as live view.
The problem is that the service locks the text file for adding the new lines and at the same time the viewer application locks the file for reading.
The Service Code:
void WriteInLog(string logFilePath, data)
{
File.AppendAllText(logFilePath,
string.Format("{0} : {1}\r\n", DateTime.Now, data));
}
The viewer Code:
int index = 0;
private void Form1_Load(object sender, EventArgs e)
{
try
{
using (StreamReader sr = new StreamReader(logFilePath))
{
while (sr.Peek() >= 0) // reading the old data
{
AddLineToGrid(sr.ReadLine());
index++;
}
sr.Close();
}
timer1.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
using (StreamReader sr = new StreamReader(logFilePath))
{
// skipping the old data, it has read in the Form1_Load event handler
for (int i = 0; i < index ; i++)
sr.ReadLine();
while (sr.Peek() >= 0) // reading the live data if exists
{
string str = sr.ReadLine();
if (str != null)
{
AddLineToGrid(str);
index++;
}
}
sr.Close();
}
}
Is there any problem in my code in reading and writing way?
How to solve the problem?
You need to make sure that both the service and the reader open the log file non-exclusively. Try this:
For the service - the writer in your example - use a FileStream instance created as follows:
var outStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Write, FileShare.ReadWrite);
For the reader use the same but change the file access:
var inStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite);
Also, since FileStream implements IDisposable make sure that in both cases you consider using a using statement, for example for the writer:
using(var outStream = ...)
{
// using outStream here
...
}
Good luck!
Explicit set up the sharing mode while reading the text file.
using (FileStream fs = new FileStream(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (sr.Peek() >= 0) // reading the old data
{
AddLineToGrid(sr.ReadLine());
index++;
}
}
}
new StreamReader(File.Open(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
-> this doesn't lock the file.
The problem is when you are writing to the log you are exclusively locking the file down so your StreamReader won't be allowed to open it at all.
You need to try open the file in readonly mode.
using (FileStream fs = new FileStream("myLogFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (!fs.EndOfStream)
{
string line = fs.ReadLine();
// Your code here
}
}
}
I remember doing the same thing a couple of years ago. After some google queries i found this:
FileStream fs = new FileStream(#”c:\test.txt”,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite);
i.e. use the FileShare.ReadWrite attribute on FileStream().
(found on Balaji Ramesh's blog)
Have you tried copying the file, then reading it?
Just update the copy whenever big changes are made.
This method will help you to fastest read a text file and without locking it.
private string ReadFileAndFetchStringInSingleLine(string file)
{
StringBuilder sb;
try
{
sb = new StringBuilder();
using (FileStream fs = File.Open(file, FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
string str;
while ((str = sr.ReadLine()) != null)
{
sb.Append(str);
}
}
}
}
return sb.ToString();
}
catch (Exception ex)
{
return "";
}
}
Hope this method will help you.