Remove duplicates not working - c#

Hi can i know why this code not working, it's working but it will also remove non duplicates entry and for some lists it will throw some error
ex:
This list working but it will also remove http://test1.com
http://test.com
http://test.com
http://test1.com
http://1test.com
And with this lists will throw this "System.ArgumentNullException was unhandled" error
http://test.com
http://test.com
http://test1.com
http://1test.com
http://etest.com
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog buka = new OpenFileDialog();
buka.InitialDirectory = "";
buka.Filter = "Text files(*.txt)|*.txt|All files (*.*)|*.*";
buka.FilterIndex = 2;
buka.RestoreDirectory = true;
buka.Title = "Cari";
buka.ShowDialog();
string bukafile = buka.FileName;
if (!String.IsNullOrEmpty(bukafile))
{
StreamReader isiFile = File.OpenText(bukafile);
while (isiFile.Peek() != -1)
{
if (!listBox1.Items.Contains(isiFile.ReadLine()))
{
listBox1.Items.Add(isiFile.ReadLine());
}
}
isiFile.Close();
}
}

You should cache the line from isiFile.ReadLine() so you compare the same line as you're adding.
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog buka = new OpenFileDialog();
buka.InitialDirectory = "";
buka.Filter = "Text files(*.txt)|*.txt|All files (*.*)|*.*";
buka.FilterIndex = 2;
buka.RestoreDirectory = true;
buka.Title = "Cari";
buka.ShowDialog();
string bukafile = buka.FileName;
if (!String.IsNullOrEmpty(bukafile))
{
StreamReader isiFile = File.OpenText(bukafile);
while (isiFile.Peek() != -1)
{
// use local variable here
string line = isiFile.ReadLine();
if (!listBox1.Items.Contains(line))
{
listBox1.Items.Add(line);
}
}
isiFile.Close();
}
}

If you don't have a very huge file you could replace a lot of your code using
var lines = File.ReadLines(bukafile).Distinct();
listBox1.DataSource = lines.ToList();

You're reading two lines, one for each ReadLine() call. You use the first line to do the .Contains check, and the second line to add to the listbox. These two lines aren't related to each other in any way.
So for the first list, you first check if http://test.com, the first line, is in the listbox. It isn't, so you read the next line, coincidentally also http://test.com, and add that to the listbox. Then, you check if http://test1.com is in the listbox, find that it isn't, and then proceed to add http://1test.com to the listbox.
For the second list, you have an odd number of entries, so the final call to ReadLine returns, I'm guessing, null, which you can't add to the listbox.
The fix is
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog buka = new OpenFileDialog();
buka.InitialDirectory = "";
buka.Filter = "Text files(*.txt)|*.txt|All files (*.*)|*.*";
buka.FilterIndex = 2;
buka.RestoreDirectory = true;
buka.Title = "Cari";
buka.ShowDialog();
string bukafile = buka.FileName;
if (!String.IsNullOrEmpty(bukafile))
{
StreamReader isiFile = File.OpenText(bukafile);
while (isiFile.Peek() != -1)
{
string line = isiFile.ReadLine();
if (!listBox1.Items.Contains(line))
{
listBox1.Items.Add(line);
}
}
isiFile.Close();
}
}

Related

How to manipulate or edit a txt file from textbox and save the modification to the main file or new file

I've managed to open a txt file to a ComboBox where it shown only the second element"100", and if I select one of the items in ComboBox will show me the the first element witch is "firstName", the problem is I want to modify the first element from the textbox and save it to the main file or new file on the way that I replace the old element with new one from the textbox and save the file as it was at the beginning
TXT FILE
firstName;;;100;;;0;
firstName;;;100;;;1;
firstName;;;100;;;2;
firstName;;;100;;;3;
firstName;;;0100;;;4;
firstName;;;0100;;;5;
firstName;;;0100;;;6;
firstName;;;0100;;;7;
lastName;;;0100;;;0;
lastName;;;0100;;;1;
lastName;;;0100;;;2;
lastName;;;0100;;;3;
lastName;;;0100;;;4;
lastName;;;0100;;;5;
lastName;;;0100;;;6;
lastName;;;0100;;;7;
i want to change the first elements from the textbox and replace it with user input and save the file as in it were,
example:
//output
john;;;100;;;0;
Patrick;;;100;;;1;
firstName;;;100;;;2;
namespace WindowsFormsApp8
{
public partial class Form1 : Form
{
public string[] lines;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = "txt file (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog.FilterIndex = 2;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
//string[] lines = File.ReadAllLines(openFileDialog.FileName);
lines = File.ReadAllLines(openFileDialog.FileName);
List<string> result = new List<string>();
string[] par = new string[1];
par[0] = ";;;";
for (int i = 0; i < lines.Length; i++)
{
string[] row = lines[i].Split(par, StringSplitOptions.None);
if (row.Length > 2)
{
if (!result.Contains(row[1]))
result.Add(row[1]);
}
}
foreach (string line in result)
{
comboBox1.Items.Add(line);
}
}
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var d = lines;
var t = d.Where(g => g.Contains(comboBox1.Text));
string allItems = "";
foreach (string item in t)
{
string[] r = item.Split(new string[] { ";;;" }, StringSplitOptions.None);
allItems += r[0] + Environment.NewLine;
}
textBox1.Text = allItems;
}
}
}
I've read your code carefully and my understanding may not be perfect but it should be close enough that I can help. One way to achieve your objectives is with data binding and I'll demonstrate this step by step.
"open a txt file to a combobox"
In your main form, you'll move the OpenFileDialog so that it is now a member variable:
private OpenFileDialog openFileDialog = new OpenFileDialog
{
InitialDirectory = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Files"),
FileName = "Data.txt",
Filter = "txt file (*.txt)|*.txt|All files (*.*)|*.*",
FilterIndex = 2,
RestoreDirectory = true,
};
In the main form CTor
Handle event buttonLoad.Click to display the dialog
Handle event openFileDialog.FileOk to read the file.
The DataSource of comboBox will be set to the list of lines read from the file.
Initialize
public MainForm()
{
InitializeComponent();
buttonLoad.Click += onClickLoad;
openFileDialog.FileOk += onFileOK;
comboBox.DataSource = lines;
.
.
.
Disposed += (sender, e) => openFileDialog.Dispose();
}
BindingList<Line> lines = new BindingList<Line>();
private void onClickLoad(object? sender, EventArgs e) =>
openFileDialog.ShowDialog();
In a minute, we'll look at those three things step by step. But first...
Serialize and Deserialize
You have a lot of loose code doing string splits to decode your serializer format. Try consolidating this in a class that is also suitable to be used in a BindingList<Line>. This will be the data source of your combo box. Also consider using a standard serialization format like JSON instead!
class Line : INotifyPropertyChanged
{
// Make a Line from serialized like firstName;;;100;;;0;
public Line(string serialized)
{
// Convert to a stored array
_deserialized = serialized.Split(new string[] { ";;;" }, StringSplitOptions.None);
}
// Convert back to the format used in your file.
public string Serialized => string.Join(";;;", _deserialized);
private string[] _deserialized { get; } // Backing store.
// Convert a list of Lines to a collection of strings (e.g. for Save).
public static IEnumerable<string> ToAllLines(IEnumerable<Line> lines) =>
lines.Select(_ => _.Serialized);
// Determine how a Line will be displayed in the combo box (e.g. "0100").
public override string ToString() => _deserialized[1].ToString();
// Use array syntax to access elements of the split array.
public string this[int index]
{
get => _deserialized[index];
set
{
if(!Equals(_deserialized[index],value))
{
// Send event when any array value changes.
_deserialized[index] = value;
OnPropertyChanged($"{index}");
}
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Load
Once the data file is selected, the raw text file will be shown and the combo box will be populated.
private void onFileOK(object? sender, CancelEventArgs e)
{
lines.Clear();
foreach (var serialized in File.ReadAllLines(openFileDialog.FileName))
{
lines.Add(new Line(serialized));
}
textBoxMultiline.Lines = lines.Select(_=>_.Serialized).ToArray();
comboBox.SelectedIndex = -1;
}
Replacement
Going back to the main form CTor there are three more events we care about:
public MainForm()
{
.
.
.
comboBox.SelectedIndexChanged += onComboBoxSelectedIndexChanged;
textBoxEditor.TextChanged += onEditorTextChanged;
lines.ListChanged += onListChanged;
.
.
.
}
When a new item is selected in the combo box, put it in the text editor.
private void onComboBoxSelectedIndexChanged(object sender, EventArgs e)
{
var item = (Line)comboBox.SelectedItem;
if (item != null)
{
textBoxEditor.Text = item[0];
}
}
When the textEditor text changes, modify the item.
private void onEditorTextChanged(object? sender, EventArgs e)
{
var item = (Line)comboBox.SelectedItem;
if (item != null)
{
item[0] = textBoxEditor.Text;
}
}
When the item changes, update the file display in the big textbox.
private void onListChanged(object? sender, ListChangedEventArgs e)
{
switch (e.ListChangedType)
{
case ListChangedType.ItemChanged:
textBoxMultiline.Lines = lines.Select(_=>_.Serialized).ToArray();
break;
}
}
Save
SaveFileDialog saveFileDialog = new SaveFileDialog
{
InitialDirectory = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Files"),
FileName = "Data.txt",
Filter = "txt file (*.txt)|*.txt|All files (*.*)|*.*",
FilterIndex = 2,
RestoreDirectory = true,
};
private void onClickSave(object? sender, EventArgs e) =>
saveFileDialog.ShowDialog(this);
private void onSaveFileOK(object? sender, CancelEventArgs e)
{
File.WriteAllLines(saveFileDialog.FileName, Line.ToAllLines(lines));
}
I hope this is "close enough" to what you have described that if will give you some ideas to experiment with.

How can i count the words from a richtextbox

I want to make a program that counts as example the word "Me" from a richtextbox. How is this possible in c#. The code that i already have is that it loads a textfile.
private void button1_Click(object sender, EventArgs e)
{
Stream myStream;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
if ((myStream = openFileDialog1.OpenFile()) != null)
{
string strfilename = openFileDialog1.FileName;
string filetext = File.ReadAllText(strfilename);
richTextBox1.Text = filetext;
textBox1.Text = openFileDialog1.FileName;
richTextBox1.LoadFile(#"C:\Users\Administrator\Documents\School\C#\DEEL 2\HW5\5.3 opdracht1\Sonnet 14.txt", RichTextBoxStreamType.PlainText);
}
}
}
private void button2_Click(object sender, EventArgs e)
{
}
If you want to use LINQ, you can do it pretty easily. Simply split the text on whitespaces, and then filter the array for words matching what you want. Here's a sample:
string search = "Me";
int count = richTextBox1.Text.Split(' ').Where(word => word == search).Count();
Separete all the words and after that you can do whatever you want
//Variable to store your count
int n = 0;
string stringToCompare = "Me";
string[] data = richTextBox1.Text.Split(' ');
for(int i=0;i<data.Length;i++)
{
if(data[i]==stringToCompare )
n++;
}
Console.WriteLine($"Word {stringToCompare } has appeared {n} times");
If you dont want case sensitive try something like
if(data[i].ToUpper() == stringToCompare.ToUpper() )
n++;

(C# using WPF) Saving and retrieving multiple entries of data onto a txt file

UI for browsing data
Im lookig for a way to save and open multiple entries of data from the text boxes onto a .txt file. By "multiple entries" I mean having a kind of database of (in this instance) members of a certain team, without the use of LINQ. So for example having Messi and his data as the first entry, then when I press "Next", the second player would appear along with their data.
Currently I am using the SaveFileDialog and OpenFileDialog method to save and open entries, however it only saves a single record.
private void menu_save_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() == true)
{
using (StreamWriter write = new StreamWriter(File.Create(sfd.FileName)))
{
write.WriteLine(tbox_name.Text);
write.WriteLine(tbox_dob.Text);
write.WriteLine(tbox_number.Text);
write.WriteLine(tbox_nationality.Text);
write.WriteLine(tbox_height.Text);
write.WriteLine(tbox_weight.Text);
write.WriteLine(tbox_position.Text);
write.Close();
write.Dispose();
}
}
}
private void menu_open_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == true)
{
using (StreamReader read = new StreamReader(File.OpenRead(ofd.FileName)))
{
tbox_name.Text = read.ReadLine();
tbox_dob.Text = read.ReadLine();
tbox_number.Text = read.ReadLine();
tbox_nationality.Text = read.ReadLine();
tbox_height.Text = read.ReadLine();
tbox_weight.Text = read.ReadLine();
tbox_position.Text = read.ReadLine();
read.Close();
read.Dispose();
}
}
}
.txt file after saving data
I would like the application to be able to save, for example, 11 entries (players) on a single .txt file and be able to go through the "database" with the 'Next' and 'Previous' buttons. I would also like to have an option to sort the players in an alphabetical order. Any help would be much appreciated as Im new to WPF and havent quite gotten my head around it yet.
File.Create overwrites existing file (all previous data gets lost). Use File.AppendAllLines method:
private void menu_save_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() == true)
{
File.AppendAllLines(sfd.FileName, new string []
{
tbox_name.Text,
tbox_dob.Text,
tbox_number.Text,
tbox_nationality.Text,
tbox_height.Text,
tbox_weight.Text,
tbox_position.Text,
});
}
}
similarly to read all data use File.ReadAllLines method, but you will have to separate lines into groups after that:
string[] lines;
int index;
private void menu_open_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == true)
{
lines = File.ReadAllLines(ofd.FileName);
index = 0;
Display(index);
}
}
private void Display(int number)
{
int i = number * 7; // 7 is a number of values per item
tbox_name.Text = lines[i];
tbox_dob.Text = lines[i+1];
tbox_number.Text = lines[i+2];
tbox_nationality.Text = lines[i+3];
tbox_height.Text = lines[i+4];
tbox_weight.Text = lines[i+5];
tbox_position.Text = lines[i+6];
}
to display next, do index++; Display(index);
to display previous, do index--; Display(index);

How to get a Listbox to read to a Listbox

I am trying to open any selected textfile and have the text input be sent to a listbox... Originally I wrote this code for a textbox which worked great now that I am converting it to a listbox it doesnt seem to work so much. I left the default item names in order for better understanding of what is going on.
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
label1.Text = openFileDialog1.FileName;
listBox1.Items.Add = File.ReadAllText(label1.Text);
}
}
listBox1.Items.AddRange(File.ReadAllLines(label1.Text));
Try this :
listBox1.Items.AddRange(File.ReadLines(label1.Text).ToArray());
.Add() is a method and you are treating it like a property.
Try this code instead:
listBox1.Items.Add(File.ReadAllText(label1.text));
string[] lines = File.ReadLines("SomeFile.txt").ToArray();
foreach (var line in lines)
{
listBox1.Items.Add(line);
}
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
label1.Text = openFileDialog1.FileName;
//till here the same
//open filestream
System.IO.StreamReader file = new System.IO.StreamReader(openFileDialog1.FileName);
//loop trough lines
while ((line = file.ReadLine()) != null)
{
//add line to listbox
listBox1.Items.Add ( line);
}
}
}

If/Else with C#

Okay, so I'm working with some if/else statements now. But, I'm having some trouble.
Here's the full code that is depending on the version clicked.
private void button_Click(object sender, EventArgs e)
{
using (OpenFileDialog file = new OpenFileDialog())
{
file.Filter = "File(*.file)|*.jar|All Files (*.*)|*.*";
file.Title = "Open File...";
if (file.ShowDialog() == DialogResult.OK)
{
string fullFileName = item.FileName;
FileInfo userSelected = new FileInfo(fullFileName);
string fileNameWithExt = Path.GetFileName(fullFileName);
string destPath = Path.Combine(Application.UserAppDataPath, fileNameWithExt);
string mcAD = Environment.ExpandEnvironmentVariables("%AppData%");
File.Copy(item.FileName, mcAD, true);
}
}
But what I'm having trouble is with this.
Below is the code, but here's how the program is lain out.
There's a menu at the bottom of the program. It's named "Version" you click and you can choose version 1.0, 2.0, and 3.0. I have it set so there's text beside it telling it which version you chose.
Now, the issue is I need an if/else statement for all the version for the above code cause all files for each version go to a different location.
Here's the other code...
private void Version_1_0_Click(object sender, EventArgs e)
{
string Version_1_0_Selected = VersionText.Text = "1.0 Selected";
}
private void Version_1_6_1_Click(object sender, EventArgs e)
{
string Version_2_0_Selected = VersionText.Text = "2.0 Selected";
}
private void Version_3_0_Click(object sender, EventArgs e)
{
string Version_3_0_Selected = VersionText.Text = "3.0 Selected";
}
You can use Control.Tag for storing version index. For example:
private void Version_1_0_Click(object sender, EventArgs e)
{
VersionText.Text = "1.0 Selected";
VersionText.Tag= 1;
}
Then, you can define your target paths:
string[] paths = {#"c:\path1.txt", #"c:\path2.txt", #"c:\path3.txt"};
Finally, when you writing your files you can lookup the path like this:
File.Copy(item.FileName, paths[VersionText.Tag], true);
You might need to modify this code if the target file name is based on the source file name, but that should not be difficult.
Abstract the FileDialog code to a separate method and pass in your version string so that you can then perform the checks.
public void OpenVersionDialog(string version)
{
string mcAD = GetCopyPath(version);
if(!String.IsNullOrEmpty(mcAD))
{
using (OpenFileDialog file = new OpenFileDialog())
{
file.Filter = "File(*.file)|*.jar|All Files (*.*)|*.*";
file.Title = "Open File...";
if (file.ShowDialog() == DialogResult.OK)
{
string fullFileName = item.FileName;
FileInfo userSelected = new FileInfo(fullFileName);
string fileNameWithExt = Path.GetFileName(fullFileName);
string destPath = Path.Combine(Application.UserAppDataPath, fileNameWithExt);
File.Copy(item.FileName, mcAD, true);
}
}
}
else
{
//invalid version selected
}
}
public string GetCopyPath(string versionInput)
{
//these are case-insensitive checks but you can change that if you want case-sensitive
if(string.Equals(versionInput, "1.0 Selected", StringComparison.OrdinalIgnoreCase))
return "YOUR_PATH_FOR 1.0";
if(string.Equals(versionInput, "2.0 Selected", StringComparison.OrdinalIgnoreCase))
return "YOUR_PATH_FOR 2.0";
if(string.Equals(versionInput, "3.0 Selected", StringComparison.OrdinalIgnoreCase))
return "YOUR_PATH_FOR 3.0";
return String.Empty;
}
If I understand correctly that should be what you want. If you have more versions, you could store them in a dictionary where the key is the version and the value is the path that the file should be copied to.
I'm not sure what the difference between mcAD and destPath is but I assume mcAD is the variable that changes based on the version as that's being used in File.Copy.

Categories

Resources