Append string in a specific place of a text file - c#

I have hundreds of files in a directory. Many of the text files have the Code Column values as blank and i need to iterate over all the text files and fill it. I am able to write the code to add the code value in a new line, but i am not able to write it under code column. String value is: "STRINGTOENTER". I only want it be entered in the 1st line after the header. The last line should be left alone
Id Code File_Number Suffix Check_Number Check_Date
047 7699 01 99999 11/11/2012
1 -6.15
Below is my code snippets that add the value at a newline. I think I need to do a regular expression or a tab delimited type solution here.
public static void AddAStringtoAllTextFiles()
{
try
{
string path = #"C:\Users\ur\Desktop\TestFiles\";
string[] fileEntries = Directory.GetFiles(path);
for (int i = 0; i < fileEntries.Length; i++)
{
File.AppendAllText(fileEntries[i], "STRINGTOENTER" + Environment.NewLine);
}
}
catch (Exception e)
{
throw e;
}
}

EDITED
please try this with the assumption that its space(s) delimited.
its working on my VS2017 and kindly add the using statement on the top as below .
using System.Text.RegularExpressions
public static void AddAStringtoAllTextFiles()
{
try
{
string path = #"C:\Users\ur\Desktop\TestFiles\";
var fileEntries = Directory.GetFiles(path);
int indexPosition2InsertData=1;
foreach (var entry in fileEntries)
{
var lines = File.ReadAllLines(entry);
for (var index = 1; index < lines.Length; index++) //starting from first row, leaving the header
{
var split= Regex.Split(lines[index].Trim(), #"\s{1,}"); //reading the line with space(s)
if(split.Length==5) //edited //checking if the row is not blank
{
var list = split.ToList(); //convert to list to insert
list.Insert(indexPosition2InsertData, "STRINGTOENTER"); //inserting at the index 1
lines[index] = string.Join("\t", list);
}
}
File.WriteAllLines(entry, lines);
}
}
catch (Exception e)
{
throw e;
}
}
I am getting this after running the code.
Id Code File_Number Suffix Check_Number Check_Date
047 STRINGTOENTER 7699 01 99999 11/11/2012
1 -6.15
Please let me know if this helps.

Assuming each file has the right tab delimitation (and that's a big assumption given the question quality)
// Get the files
var fileEntries = Directory.GetFiles(path);
// iterate through each file name
foreach (var entry in fileEntries)
{
// Load the File into the lines array
var lines = File.ReadAllLines(entry);
// Iterate over each line
if(lines.Length >1)
{
// Split the lines by tab
var split = lines[1].Split('\t');
// your code should be at array index 1
split[1] = "STRINGTOENTER";
// write the whole line back
lines[1] = string.Join("\t", split);
// write the file
File.WriteAllLines(entry, lines);
}
}
Note : you should probably do this with a CSV parser, this was only for academic purposes and totally untested

I want to show my desired solution based on your input. Amazing how a simple piece of code can contribute to solving a larger and a complex problem. Thanks again!
public static void AddClientCodetoAllTextFiles(string update_batch_with_clientcode, string batchfilepathtobeupdated)
{
try
{
var fileEntries = Directory.GetFiles(#batchfilepathtobeupdated.Trim());
foreach (var entry in fileEntries)
{
var lines = File.ReadAllLines(entry);
if (lines.Length > 1)
{
for (int i = 1; i < lines.Length - 1; i++)
{
var split = lines[i].Split('\t');
split[1] = update_batch_with_clientcode.Trim();
lines[i] = string.Join("\t", split);
File.WriteAllLines(entry, lines);
}
}
}
}
catch (Exception e)
{
throw e;
}
}

Related

How to remove texts after a character?

I have an array that holds user and passwords in user:pass form, and I like ro remove lines which pass is less than 8 characters or password uses repetitive chars like 111111,22222222222,...
I have tried string.take but it takes lines completely, I need conditional deletion.
public string[] lines;
//open file dialogue to load the user pass file
lines = File.ReadAllLines(openFileDialog1.FileName);
//delete button click event
//the place that I have problem
I have email:pass combination like so:
email1:1234567895121
email2:12345
email4:11111
email5"454545454545
and I would like the output to be like
email1:1234567895121
email5"454545454545
Just loop the characters of every line and see if the current is equal to the previous:
public string[] lines = File.ReadAllLines(openFileDialog1.FileName);
var filteredLines = new List<string>(lines);
foreach(var line in lines)
{
var pair = line.Split(':');
var mail = pair[0];
var pass = pair[1]; // may throw exception on invalid format of your line
for(int i = 1; i < pass.Length; i++)
{
if(pass[i] == pass[i - 1])
{
filteredLines.Remove(line);
break; // will break inner loop and continue on next line
}
}
}
string[] lines =
{
"email1:1234567895121",
"email2:12345",
"email3:22222222222",
"email4:11111",
"email5:454545454545"
};
lines = lines
.Where(s =>
{
string pass = s.Split(new[] { ':' }, 2)[1];
return pass.Length >= 8 && pass.Any(c => c != pass[0]);
})
.ToArray();
foreach (var s in lines)
Console.WriteLine(s);
Output:
email1:1234567895121
email5:454545454545

Reading specific lines with unknown placement in C#

I am trying to code a program to read out user-groups from a .txt-file and to put said groups into a listbox. An example for a group list would be the following:
User
-------------
Group1
Group2
Group3
[space]
[space]
next user
Every user has is in an unknown amount of groups, thats why there are two spaces, just to seperate everything.
Here is my progress so far:
private void Button_Click(object sender, RoutedEventArgs e) {
//users.txt contains all users
//in the same directory there are multiple lists with given groups
StreamReader sr = new StreamReader("c:\\ADHistory\\users.txt", System.Text.Encoding.Default);
string line = string.Empty;
try {
//Read the first line of text
line = sr.ReadLine();
//Continue to read until you reach end of file
while (line != null) {
listboxNames.Items.Add(line);
//Read the next line
line = sr.ReadLine();
}
//close the file
sr.Close();
}
catch (Exception f)
{
MessageBox.Show(f.Message.ToString());
}
finally
{
//close the file
sr.Close();
}
}
private void listboxNames_SelectionChanged(object sender, SelectionChangedEventArgs e) {
//as soon as you choose a user from the first list
//you may choose a date to look at all groups the user is in.
listboxDates.Items.Clear();
DirectoryInfo dinfo = new DirectoryInfo(#"C:\ADHistory");
FileInfo[] Files = dinfo.GetFiles("*.txt");
//this adds all dates into the second listbox
//and removes users.txt from the list.
foreach (FileInfo file in Files) {
listboxDates.Items.Add(file.Name);
}
for (int n = listboxDates.Items.Count - 1; n >= 0; --n)
{
string removelistitem = "users";
if (listboxDates.Items[n].ToString().Contains(removelistitem))
{
listboxDates.Items.RemoveAt(n);
}
//this displays the user below the listboxes,
//because of styling purposes
string user = Convert.ToString(this.listboxNames.SelectedItem);
labelName.Content = user;
}
}
//here we have my main problem.
//I can't find a solution to add the groups to the last listbox
private void listboxDates_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string user = Convert.ToString(labelName.Content);
listboxGroups.Items.Clear();
string path = "C:\\ADHistory\\";
path += Convert.ToString(this.listboxDates.SelectedItem);
foreach (string line in File.ReadLines(path))
{
if (line.Contains(user))
{
while (line != " ")
{
listboxGroups.Items.Add(line);
}
}
}
}
I really hope you can help me.
EDIT
This question has been answered, so there is no need for mor answers.
Thanks for all the comments :)
Your problem is, when the line for the user is found, you test if line == " " without proceeding to the next and your while loop should exit immediately then
Use for loop instead of for each. Have your while loop when you find the line for user as the same, and increase the loop variable with ++ inside the while loop and read the next line. Don't forget to check for the string array length before setting line = fileLines[lineIndex]
Therefore, here is the code that should work for you
string[] fileLines = File.ReadAllLines(path);
for (int lineIndex = 0; lineIndex < fileLines.Length; lineIndex++)
{
string line = fileLines[lineIndex];
if (line.Contains(user))
{
while(++lineIndex < fileLines.Length && (line = fileLines[lineIndex]) != " ")
{
listboxGroups.Items.Add(line);
}
break;
}
}
However, if the file is huge, you might want not to read all it's lines into memory, here is another approach which works with File.ReadLines()
IEnumerator<string> fileLines = File.ReadLines(path).GetEnumerator();
while (fileLines.MoveNext())
{
string line = fileLines.Current;
if (line.Contains(user))
{
while (fileLines.MoveNext())
{
line = fileLines.Current;
if (line == " ")
{
break;
}
listboxGroups.Items.Add(line);
}
break;
}
}

how I can copy the text in a specified field, without mention the line number

I have the next code :
private void button1_Click_1(object sender, EventArgs e)
{
string path = AppDomain.CurrentDomain.BaseDirectory.ToString();
var link = File.ReadLines(path + "test.txt").ToArray();
var lines = File.ReadAllLines(path + "test2.txt");
foreach (var txt in link )
{
if (txt.Contains("Output="))
{
var outputPath = txt.Split('=')[1];
if (File.Exists(path + "test2.txt"))
{
var modifiedLines = lines.Select(line =>
{
if (line.StartsWith("outlog=\""))
{
return string.Format("outlog=\"{0}\"", outputPath);
}
else
{
return line;
}
});
File.WriteAllLines(path+ "test2.txt", modifiedLines);
}
}
}
With this code I whan to copy what is after equel from Output="C:\temp\out.log"(who is in test.txt), after equal in outlog=(who is in test2.txt).
How I can copy the text who exists in one text file test.txt, in a specified location from a second field test2.txt, without mentioned the line number ?
Here I put just a row, but in my files text I have many rows, but I think I make this to work, I handle with another rows.
test.txt have
Licfile="C:\temp\lic.lic"
Output="C:\temp\out.log"
Title="name"
test2.txt have
outlog=
license=
lmgr_files=
license_path=
and after runing the code the test2.txt I want to looks like this:
outlog="C:\temp\out.log"
license_path="C:\temp\lic.lic"
lmgr_files=false
license=true
I am confused about your problem but i just want to try to give you an opinion. I hope it may be help you. But line numbers are really important for these problem.
String[] arrayOld = File.ReadAllLines(#"C:\test.txt");
String[] arrayNew = new string[arrayOld.Length];
if (arrayOld[0].Contains("Licfile=")) // If statements could be more
{
Array.Copy(arrayOld,0,arrayNew,0,2); // How many line will add
}
for (int i = 0; i < 2; i++)
{
File.AppendAllText(#"D:\test2.txt", arrayNew[i] + Environment.NewLine); // It'll add all lines
}
P.S.: Don't forget to add strings like lineOne = "outlog=" + locString; etc.

Clearing a line of a txt file by the line ID

I have looked all over for the answer to this, but I can't find it anywhere. I need to be able to clear a line from a txt file by the last integer in the line (the ID number), but I have no idea how to do that. Please help? Basically I was thinking that I need to find the last integer, and if it does not equal to the input, then it would move to the next line until it finds the right integer. Then that line is cleared. Here is some of my code that obviously doesn't work:
public static void TicID(CommandArgs args)
{
if (args.Parameters.Count == 1)
{
if (i == 1)
{
try
{
string idToDelete = args.Parameters[0];
StreamReader idreader = new StreamReader("Tickets.txt");
StreamWriter iddeleter = new StreamWriter("Tickets.txt");
string id = Convert.ToString(idreader.Read());
string line = null;
while (idreader.Peek() >= 0)
{
if (String.Compare(id, idToDelete) == 0)
{
iddeleter.WriteLine(line);
}
else
{
idreader.ReadLine();
}
}
}
The most straightforward way to delete lines is to write the lines that should not be deleted:
var idToDelete = "1";
var path = #"C:\Temp\Test.txt";
var lines = File.ReadAllLines(path);
using (var writer = new StreamWriter(path, false)) {
for (var i = 0; i < lines.Length; i++) {
var line = lines[i];
//assuming it's a CSV file
var cols = line.Split(',');
var id = cols[cols.Length - 1];
if (id != idToDelete) {
writer.WriteLine(line);
}
}
}
This is the LINQ-way:
var lines = from line in File.ReadAllLines(path)
let cols = line.Split(',')
let id = cols[cols.Length - 1]
where id != idToDelete
select line;
File.WriteAllLines(path, lines);
Create a StreamReader object and read line by line into a string array or something like that using StreamReader's instance method ReadLine() and now find your line of choice in your text array and delete it.
Important note:
do { /*see description above*/ } while (streamReader.Peak() != -1);

comparing string and variable but failing based on contains

What I have going on is I have two files. Both files are delimited by '|'. If file 1 matches a line in file 2 I need to combine the lines. Here is the code:
string[] mathlines = File.ReadAllLines(#"C:\math.txt");
var addlines = File.ReadAllLines(#"K:\add.txt");
foreach (string ml in mathlines)
{
string[] parse = ml.Split('|');
if (addlines.Contains(parse[0]))
{
File.AppendAllText(#"C:\final.txt", parse[0]+"|"+parse[1]+"\n");
}
else
{
File.AppendAllText(#"C:\final.txt", ml + "\n");
}
}
I realize that the math part isn't setup yet, but I need to get the match part working.
Here is an example:
mathlines:
dart|504.91
GI|1782.06
Gcel|194.52
clay|437.35
grado|217.77
greGCR|14.82
rp|372.54
rp2|11.92
gsg|349.92
GSxil|4520.55
addlines:
Gimet|13768994304
GSxil|394735896576
Ho|4994967296
gen|485331304448
GSctal|23482733690
Obr|88899345920
As you can see mathlines contains GSxil and so does addlines but my if (addlines.Contains) never fines the variable in addlines. Any help is always loved! Thanks.
Sorry forgot to mention that I need it to match exactly on the comparison. Also i need to split out the variable on the correct line that matches. So I would need to split out the 394735896576 this example and then append the 394735896576.
addLines.Contains(parse[0]) is going to match on the entire string; you need to match based on part. There are more efficient solutions, but a O(n^2) option is to use LINQ Any():
if (addLines.Any(l => l.StartsWith(parse[0])))
{
...
You could load all lines from addlines.txt into a dictionary and then use that to find a match for each line in mathlines.txt. This method would be much faster than what you have currently.
string[] mathlines = File.ReadAllLines(#"C:\math.txt");
string[] addlines = File.ReadAllLines(#"K:\addlines.txt");
string[] finallines = new string[mathlines.Length];
var addlinesLookup = new Dictionary<string, string>();
for (int i = 0; i < addlines.Length; i++)
{
string[] parts = addlines[i].Split('|');
if (parts.Length == 2) // Will there ever be more than 2 parts?
{
addlinesLookup.Add(parts[0], parts[1]);
}
}
for (int i = 0; i < mathlines.Length; i++)
{
string[] parts = mathlines[i].Split('|');
if (parts.Length >= 1)
{
if (addlinesLookup.ContainsKey(parts[0]))
{
finallines[i] = mathlines[i] + "|" + addlinesLookup[parts[0]] + "\n";
}
{
finallines[i] = mathlines[i] + "\n";
}
}
}
File.AppendAllLines(#"C:\final.txt", finallines, Encoding.ASCII);

Categories