How to remove duplicate line results from textbox - c#

Here is my data result code
it gets duplicate line results
I wanna remove duplicate result
Please help me
private void DataResult(string result, string acc, string file)
{
lock (this)
{
if (result == "good")
{
MetroTextBox metroTextBox = this.textBox1;
metroTextBox.Text = metroTextBox.Text + acc + Environment.NewLine;
file = Path.Combine(this.papka, "good.txt");
if (!Directory.Exists(this.papka))
{
Directory.CreateDirectory(this.papka);
}
File.AppendAllText(file, acc + "\r\n");
Listing.good++;
}
if (result == "error")
{
Listing.error++;
}
}
}

Add this to using directives at top of page:
using System.Linq;
Then simply use like so:
metroTextBox.Text = string.Join(Environment.NewLine, metroTextBox.Lines.Distinct());
In your example:
private void DataResult(string result, string acc, string file)
{
lock (this)
{
if (result == "good")
{
MetroTextBox metroTextBox = this.textBox1;
metroTextBox.Text = string.Join(metroTextBox.Lines.Distinct(), acc, Environment.NewLine);
file = Path.Combine(this.papka, "good.txt");
if (!Directory.Exists(this.papka))
{
Directory.CreateDirectory(this.papka);
}
File.AppendAllText(file, acc + "\r\n");
Listing.good++;
}
if (result == "error")
{
Listing.error++;
}
}
}

Assuming this method is the only way lines can get added to the text box, maybe you should check if the text box contains acc before you add it...
if(!metroTextBox.Text.Contains(acc))
metroTextBox.Text = metroTextBox.Text + acc + Environment.NewLine;
Side note; if you rename your text box on the form, you won't need to establish variables to it with other names. Click the text box on the form, and in the properties grid where it says (Name) textbox1, change that to metroTextBox
Side note 2; this code appends the contents of the text box to a file every time it adds a line to the text box. This could also be a source of duplication if the file name doesn't change because after adding 3 lines your file will look like:
line1
line1
line2
line1
line2
line3
I don't recommend you write a file as often as you add a line to a text box; one operation is trivial, the other is really slow and involved. Separate these things into different methods and call write file less often

You can try collecting unique results, with a help of HashSet<string>, e.g.
private HashSet<string> m_Results = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
then
private void DataResult(string result, string acc, string file)
{
lock (this)
{
if (result == "good")
{
if (m_Results.Add(result)) {
// result is unique (not in m_Results)
MetroTextBox metroTextBox = this.textBox1;
metroTextBox.Text = metroTextBox.Text + acc + Environment.NewLine;
file = Path.Combine(this.papka, "good.txt");
//DONE: no need to check for directoty exitance
Directory.CreateDirectory(this.papka);
File.AppendAllText(file, acc + "\r\n");
}
else {
// result has been appeared before
}
Listing.good++;
}
if (result == "error")
{
Listing.error++;
}
}
}

Related

How to check if multiple checkboxes are checked

So in my program, i have three checboxes (A, B and C). and I want to save the content of the checkbox the is checked to a text file. I am doing this using if statements as shown below:
if (a.IsChecked == true)
{
res = a.Content.ToString() + " is checked";
}
else if (b.IsChecked == true)
{
res = b.Content.ToString() + " is checked";
}
else if (c.IsChecked == true)
{
res = c.Content.ToString() + " is checked";
}
And here is where i am saving the above values to a string and then later in my code to a text file
string test = res;
Now this is working for me. So i decided to try to check if multiple checkboxes are being checked. So added the below if statements:
else if ((a.IsChecked == true) && (b.IsChecked == true) && (c.IsChecked == true))
{
res= a.Content.ToString() + " " + b.Content.ToString() + " " + c.Content.ToString()
}
but this isn't working with me because in the end res is printed in the text file as a rather than a b c. Any idea what i am doing wrong?
Also please note that i already initialized res at the top of my code as string:
string res;
I am not getting any error when i run my code so i am not sure where my mistake is. any help with this is much much appreciated.
thanks a lot :)
Its a good practice to use a StringBuilder in these cases.
On the other hand, if it is ok to have one line for each CheckBox, you can use the following:
StringBuilder sb = new StringBuilder();
checkappend(ref sb, a);
checkappend(ref sb, b);
checkappend(ref sb, c);
string res = sb.ToString();
in which
static void checkappend(ref StringBuilder sb, CheckBox ck)
{
sb.Append(ck.Content.ToString());
sb.Append(ck.IsChecked == true ? "is checked." : " is NOT checked.");
sb.Append(Environment.NewLine);
}
Note that creating a separate class can help you when there are many CheckBoxes in a List. You can simply use
foreach (var ck in listOfCheckBoxes)
checkappend(ref ck, c);
You can implement it this way:
string res = "";
if (a.IsChecked)
{
res += a.Content.ToString();
}
if (b.IsChecked)
{
res += b.Content.ToString();
}
if (c.IsChecked)
{
res += c.Content.ToString();
}
or simple
string res = $"{(a.IsChecked?a.Content+" ":"")}{(b.IsChecked?b.Content+" ":"")}{(c.IsChecked?c.Content:"")}";
That's multiple combinations to check. Simply remove else from first code snippet to run all checks one after another. You will get only report from last successful check, to have several reports you have to accumulate them somehow (add to a list, combine in multi-line string, etc.).
Here is a simple one-liner (using linq):
var result = string.Join(" and ", new[] { a, b, c }.Where(o => o.IsChecked).Select(o => $"{o.Content} is checked"));

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.

Adding Payout to User using TextFile

I'm having problems adding a payout amount to a user in a text file. Here's my current code:
public string payout = 1;
public static void AddPayout(int tPayout, string nickx) {
if (UserIsSub(nickx)) {
tPayout = payout * 2;
File.WriteAllLines("loyalty.txt", File.ReadAllLines("loyalty.txt")
.Select(x => {
if (x.StartsWith(nickx)) return nickx + " " + tPayout + "\n\r";
return x;
}));
} else {
tPayout = payout + 1;
File.WriteAllLines("loyalty.txt", File.ReadAllLines("loyalty.txt")
.Select(x => {
if (x.StartsWith(nickx)) return nickx + " " + tPayout + "\n\r";
return x;
}));
}
}
public static bool UserIsSub(String value)
{
if (File.ReadAllLines("subscribers.txt").Contains(value.ToLower())) { return true; }
else { return false; }
}
So far it just adds the same person, and keeps the number the same. What can I do the change that?
I guess you are using the wrong newline code,
try using \r\n instead of \n\r
(by the way, I dont think you need any newline sign, because writealllines should also write newlines)
then, you should insert a .ToArray after the select, because the file could be still open
then, you are replacing the line of code with the new amount. if you want to add the old one, you need to parse that line and replace the result.

In file, if line contains substring, get all of the line from the right

I have a file. Each line looks like the following:
[00000] 0xD176234F81150469: foo
What I am attempting to do is, if a line contains a certain substring, I want to extract everything on the right of the substring found. For instance, if I were searching for 0xD176234F81150469: in the above line, it would return foo. Each string is of variable length. I am using C#.
As a note, every line in the file looks like the above, having a base-16 number enclosed in square brackets on the left, followed by a hexadecimal hash and a semicolon, and an english string afterwards.
How could I go about this?
Edit
Here is my code:
private void button1_Click(object sender, EventArgs e)
{
Form1 box = new Form1();
if(MessageBox.Show("This process may take a little while as we loop through all the books.", "Confirm?", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
{
XDocument doc = XDocument.Load(#"C:\Users\****\Desktop\books.xml");
var Titles = doc.Descendants("Title");
List<string> list = new List<string>();
foreach(var Title in Titles)
{
string searchstr = Title.Parent.Name.ToString();
string val = Title.Value;
string has = #"Gameplay/Excel/Books/" + searchstr + #":" + val;
ulong hash = FNV64.GetHash(has);
var hash2 = string.Format("0x{0:X}", hash);
list.Add(val + " (" + hash2 + ")");
// Sample output: "foo (0xD176234F81150469)"
}
string[] books = list.ToArray();
File.WriteAllLines(#"C:\Users\****\Desktop\books.txt", books);
}
else
{
MessageBox.Show("Aborted.", "Aborted");
}
}
I also iterated through every line of the file, adding it to a list<>. I must've accidentally deleted this when trying the suggestions. Also, I am very new to C#. The main thing I am getting stumped on is the matching.
You could use File.ReadLines and this Linq query:
string search = "0xD176234F81150469:";
IEnumerable<String> lines = File.ReadLines(path)
.Select(l => new { Line = l, Index = l.IndexOf(search) })
.Where(x => x.Index > -1)
.Select(x => x.Line.Substring(x.Index + search.Length));
foreach (var line in lines)
Console.WriteLine("Line: " + line);
This works if you don't want to use Linq query.
//"I also iterated through every line of the file, adding it to a list<>." Do this again.
List<string> li = new List<string>()
//However you create this string make sure you include the ":" at the end.
string searchStr = "0xD176234F81150469:";
private void button1_Click(object sender, EventArgs e)
{
foreach (string line in li)
{
string[] words;
words = line.Split(' '); //{"[00000]", "0xD176234F81150469:", "foo"}
if (temp[1] == searchStr)
{
list.Add(temp[2] + " (" + temp[1] + ")");
// Sample output: "foo (0xD176234F81150469)"
}
}
}
string file = ...
string search= ...
var result = File.ReadLines(file)
.Where(line => line.Contains(search))
.Select(line => line.Substring(
line.IndexOf(search) + search.Length + 1);
Unfortunately, none of the other solutions worked for me. I was iterating through the hashes using foreach, so I would be iterating through all the items millions of times needlessly. In the end, I did this:
using (StreamReader r = new StreamReader(#"C:\Users\****\Desktop\strings.txt"))
{
string line;
while ((line = r.ReadLine()) != null)
{
lines++;
if (lines >= 6)
{
string[] bits = line.Split(':');
if(string.IsNullOrWhiteSpace(line))
{
continue;
}
try
{
strlist.Add(bits[0].Substring(10), bits[1]);
}
catch (Exception)
{
continue;
}
}
}
}
foreach(var Title in Titles)
{
string searchstr = Title.Parent.Name.ToString();
string val = Title.Value;
string has = #"Gameplay/Excel/Books/" + searchstr + ":" + val;
ulong hash = FNV64.GetHash(has);
var hash2 = " " + string.Format("0x{0:X}", hash);
try
{
if (strlist.ContainsKey(hash2))
{
list.Add(strlist[hash2]);
}
}
catch (ArgumentOutOfRangeException)
{
continue;
}
}
This gave me the output I expected in a short period of time.

Categories