Searching a text file using List.FindAll and List.Find - c#

I'm a beginner in C#, trying to work on searching through a text file I'm just testing how it works on a quick and small app, the result should show the searched unique number followed by records of the name and phone number in a list box, for example (001 John 0123456789)
Here is my code:
private void SearchButton_Click(object sender, EventArgs e)
{
string match = "";
try
{
StreamReader inputFile = File.OpenText("Transactions.txt");
List<string> TransList = new List<string>();
{
while (!inputFile.EndOfStream)
{
TransList.Add(inputFile.ReadLine());
}
TransList = TransList.FindAll(x=>x.Equals(match)).ToList();
string[] RecordsArray = TransList.ToArray();
foreach (string record in RecordsArray)
{
if (match == textBox1.Text)
{
DataListBox.Items.Add(RecordsArray[0]);
DataListBox.Items.Add(RecordsArray[1]);
DataListBox.Items.Add(RecordsArray[2]);
}
}
inputFile.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

Related

In C# a Try block, the catch section i want a exception to be thrown if in my textbock a int is entered?

So if you push the enter button, and the user enters a number i want the program to throw out a exception that no integers may be entered in the text block.
private void btnEnter_Click(object sender, RoutedEventArgs e)
{
try
{
string[] words = { txtInfo.Text };
foreach (string f in words)
{
lstResults.Items.Add(f);
}
txtInfo.Text = "";
}
catch (Exception ex)
{
}
}
Very small project for school but would like to specify the exception.
the best way to do this is to implement Guard Clauses. Guard Clause is just a simple checking of the input parameters at the top of your method.
I would totally remove try catch from your code and just check if the text in the box is an integer.
private void btnEnter_Click(object sender, RoutedEventArgs e)
{
//this will check if the text from the box can be parsed as an integer then
//exit this method but show message box with your message.
if(int.TryParse(txtInfo.Text, out var test)
{
MessageBox.Show("Integers are not allowed");
return;
}
string[] words = { txtInfo.Text };
foreach (string f in words)
{
lstResults.Items.Add(f);
}
txtInfo.Text = "";
}
I hope this helps.

Why word in listbox line removed not just one line but 2 lines?

I launch the program, add some words to a listbox and try to remove it. If the selected item is last one, then it works fine, but if I select a word in the middle, then it removes the selected word. Then I loaded listbox again, and the last word disappeared somewhere. Any solutions?
public List<string> words = new List<string>();
public Form2()
{
InitializeComponent();
Load();
listBox1.DataSource = words;
}
public void Save()
{
const string sPath = "Data.txt";
System.IO.StreamWriter sw = new System.IO.StreamWriter(sPath);
foreach (string item in words)
{
sw.WriteLine(item);
}
sw.Close();
}
private void Load()
{
string line;
var file = new System.IO.StreamReader("Data.txt");
while ((line = file.ReadLine()) != null)
{
words.Add(line);
}
}
// This Part ???
private void Remove()
{
string contents = null;
List<string> itemAll = new List<string>();
foreach (string str in words)
{
itemAll.Add(str);
}
foreach (string lstitem in listBox1.SelectedItems)
{
itemAll.Remove(lstitem);
//File.AppendAllText(strFile + "Currently In.txt", strName + Environment.NewLine);
}
foreach (string s in itemAll)
{ contents += s + Environment.NewLine; }
System.IO.File.WriteAllText(#"Data.txt", contents);
}
private void button2_Click(object sender, EventArgs e)
{
// The Remove button was clicked.
int selectedIndex = listBox1.SelectedIndex;
try
{
// Remove the item in the List.
words.RemoveAt(selectedIndex);
}
catch
{
}
listBox1.DataSource = null;
listBox1.DataSource = words;
Remove();
}
Since words in your code is a global variable to all of your functions what happen is you are trying to remove items twice when you call this:
words.RemoveAt and itemAll.Remove
To prevent it, instead of calling Remove() method you can rename it as UpdateListBox() passing the words as argument like:
private void UpdateListBox(List<string> words)
{
string contents = null;
List<string> itemAll = new List<string>();
foreach (string str in words)
{
itemAll.Add(str);
}
}
Then you will have a separate method to save back:
private void Save(List<string> words)
{
StringBuilder contents = new StringBuilder();
foreach (string s in words)
{
contents.AppendLine(s);
}
System.IO.File.WriteAllText(#"Data.txt", contents);
}
Then you will call it like:
private void button2_Click(object sender, EventArgs e)
{
// The Remove button was clicked.
int selectedIndex = listBox1.SelectedIndex;
try
{
// Remove the item in the List.
words.RemoveAt(selectedIndex); //Remove item from words
UpdateListBox(words); //Update contents on GUI
Save(words); //Save on IO
}
catch
{
}
}
I just created it here and haven't tested it on my IDE, but you may have an idea how it is working.

Loading large amount of text files from a share drive to search for a world. C#

Im trying to perform a search in a share drive that contains at least 90,000 files.
The code below is what I have:
private void button2_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBox1.Text))
{
MessageBox.Show("No folder: Not listed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
List<string> allFiles = new List<string>();
AddFilesnames(sourceFolder, allFiles);
foreach (string fileName in allFiles)
{
string contents = File.ReadAllText(fileName);
if (contents.Contains(searchword))
{
listBox1.BeginUpdate();
listBox1.Items.Add(fileName);
listBox1.EndUpdate();
label4.Text = (Convert.ToInt32(label4.Text) + 1).ToString();
}
}
if (listBox1.Items.Count == 0)
{
MessageBox.Show("no files");
}
}
}
public void listboxtofile()
{
DialogResult resDialog = dlgSaveFile.ShowDialog();
if (resDialog.ToString() == "OK")
{
FileInfo fi = new FileInfo(dlgSaveFile.FileName);
StreamWriter sw = fi.CreateText();
foreach (string sItem in listBox1.Items)
{
sw.WriteLine(sItem);
}
sw.Close();
}
}
public void AddFilesnames(string sourceDir, List<string> allFiles)
{
string[] fileEntries = Directory.GetFiles(sourceDir);
foreach (string fileName in fileEntries)
{
DateTime from1 = dateTimePicker1.Value.Date;
DateTime to1 = dateTimePicker2.Value.Date;
DateTime creationTime = File.GetCreationTime(fileName);
if (creationTime >= from1 && creationTime <= to1)
{
allFiles.Add(fileName);
}
}
//Recursion
string[] subdirectoryEntries = Directory.GetDirectories(sourceDir);
foreach (string item in subdirectoryEntries)
{
// Avoid "reparse points"
if ((File.GetAttributes(item) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
{
AddFileNamesToList(item, allFiles);
label4.Text = (Convert.ToInt32(label4.Text) + 1).ToString();
}
}
}
private void button3_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
textBox1.Clear();
}
private void button5_Click(object sender, EventArgs e)
{
listboxtofile();
}
}
}
So far this is working with 3,000 files but I need to have access to a shared drive that contains 90,000 files and when I try to search in the share drive the windows form get frozen. I will really apreciate any help from you all.
My suggestion would be to do any file system work in a separate thread. If you do the file searching in the same thread as your form, Windows has no chance to update the form. You won't be able to update any of your form controls (like listBox1) directly from the new thread, but you can look into delegates and C# threading in general for ways to work around this.
Also, if you just need to search files for a specific word, have you looked into existing tools like grep?

Output not being written to the DGV in my code

I'm not exactly sure what's going on here--I tried to debug but couldn't really come up with any explanation as to why nothing is being written to my datagridview.
Anybody have any idea?
public partial class CleanPathResults : Form
{
public CleanPathResults()
{
InitializeComponent();
}
public void RenameFolder(string folderName)
{
string regPattern = (#"[~#&$!%+{}]+");
string replacement = "";
List<string> normal = new List<string>();
Regex regExPattern = new Regex(regPattern);
dataGridView1.Rows.Clear();
List<string> cleanDirNames = new List<string>();
try
{
if (regExPattern.IsMatch(folderName))
{
string cleanup = regExPattern.Replace(folderName, replacement);
System.IO.Directory.Move(folderName, cleanup);
DataGridViewRow grid = new DataGridViewRow();
grid.CreateCells(dataGridView1);
grid.Cells[0].Value = folderName;
grid.Cells[1].Value = cleanup;
dataGridView1.Rows.Add(grid);
folderName = cleanup;
cleanDirNames.Add(cleanup);
}
else
{
normal.Add(folderName);
}
}
catch(Exception e)
{
throw;
}
DirectoryInfo di = new DirectoryInfo(folderName);
DirectoryInfo[] diArr = di.GetDirectories();
List<string> subdirectories = new List<string>();
try
{
foreach (DirectoryInfo subdir in diArr)
{
subdirectories.Add(subdir.ToString());
}
}
catch(Exception e)
{
throw;
}
try
{
foreach (string folder in subdirectories)
{
string sF = folder;
RenameFolder(folderName + "\\" + sF);
}
}
catch(Exception e)
{
throw;
}
}
private void button1_Click_1(object sender, EventArgs e)
{
Application.Exit();
}
}
I'm not hitting any errors--the app does what it's supposed to do (in this case, make sure folder names do not contain the invalid chars defined in the regex)...however it's just an issue of output not displaying on the dgv.
Any help would be appreciated.
Probably there's no match for your regex... this way no row is being created and added to dataGridView1.
Have you debugged the code? Try to insert a breakpoint within the if statement right after regExPattern.IsMatch. See if the debugger stops there. This way you can assert that a new row is being created.
I'll try to help you more if that holds true.
actually nevermind. figured out that b/c my method keeps calling itself, the datagridview1.Rows.Clear() would clear out everything, everytime the method called itself. Hence no output. Thanks for all your help though Leniel!

Trouble getting my button to call my class

I have a Windows Form application. What this application does, is let the user browse to a drive/folder they wish to have files renamed for. This app renames files that have "invalid" characters (that are defined in a RegEx pattern).
What i want to happen here is, after the user decides which drive/folder to use, a datagridview pops up showing the user files in the drive/folder that are going to be renamed. The user then clicks a button to actually rename the files. I'm having trouble though getting the code for my button in DriveRecursion_Results.cs set up. Can anybody help me? Code plz -- i'm extremely new to this and need syntax to look at to understand.
Form1 code:
namespace FileMigration2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
FolderSelect("Please select:");
}
public string FolderSelect(string txtPrompt)
{
//Value to be returned
string result = string.Empty;
//Now, we want to use the path information to population our folder selection initial location
string initialPathDir = (#"C:\");
System.IO.DirectoryInfo info = new System.IO.DirectoryInfo(initialPathDir);
FolderBrowserDialog FolderSelect = new FolderBrowserDialog();
FolderSelect.SelectedPath = info.FullName;
FolderSelect.Description = txtPrompt;
FolderSelect.ShowNewFolderButton = true;
if (FolderSelect.ShowDialog() == DialogResult.OK)
{
string retPath = FolderSelect.SelectedPath;
if (retPath == null)
{
retPath = "";
}
DriveRecursion_Results dw = new DriveRecursion_Results();
dw.Show();
dw.DriveRecursion(retPath);
result = retPath;
}
return result;
}
}
}
DriveRecursion_Results.cs code: [the button is in here that i need help with!]
namespace FileMigration2
{
public partial class DriveRecursion_Results : Form
{
public DriveRecursion_Results()
{
InitializeComponent();
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
}
public void DriveRecursion(string retPath)
{
//recurse through files. Let user press 'ok' to move onto next step
// string[] files = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
string pattern = " *[\\~#%&*{}/<>?|\"-]+ *";
//string replacement = "";
Regex regEx = new Regex(pattern);
string[] fileDrive = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
List<string> filePath = new List<string>();
dataGridView1.Rows.Clear();
try
{
foreach (string fileNames in fileDrive)
{
if (regEx.IsMatch(fileNames))
{
string fileNameOnly = Path.GetFileName(fileNames);
string pathOnly = Path.GetDirectoryName(fileNames);
DataGridViewRow dgr = new DataGridViewRow();
filePath.Add(fileNames);
dgr.CreateCells(dataGridView1);
dgr.Cells[0].Value = pathOnly;
dgr.Cells[1].Value = fileNameOnly;
dataGridView1.Rows.Add(dgr);
filePath.Add(fileNames);
}
else
{
DataGridViewRow dgr2 = new DataGridViewRow();
dgr2.Cells[0].Value = "No Files To Clean Up";
dgr2.Cells[1].Value = "";
}
}
}
catch (Exception e)
{
StreamWriter sw = new StreamWriter(retPath + "ErrorLog.txt");
sw.Write(e);
}
}
private void button1_Click(object sender, EventArgs e)
{
//What do i type in here to call my FileCleanUp method???
}
}
SanitizeFileNames.cs code:
namespace FileMigration2
{
public class SanitizeFileNames
{
public static void FileCleanup(List<string>filePath)
{
string regPattern = "*[\\~#%&*{}/<>?|\"-]+*";
string replacement = "";
Regex regExPattern = new Regex(regPattern);
foreach (string files2 in filePath)
{
try
{
string filenameOnly = Path.GetFileName(files2);
string pathOnly = Path.GetDirectoryName(files2);
string sanitizedFileName = regExPattern.Replace(filenameOnly, replacement);
string sanitized = Path.Combine(pathOnly, sanitizedFileName);
//write to streamwriter
System.IO.File.Move(files2, sanitized);
}
catch (Exception ex)
{
//write to streamwriter
}
}
}
}
}
}
Any help is appreciated!
Thanks :)
Put
public partial class DriveRecursion_Results : Form {
List<string> filePath;
and in driveRecursion method, just use
filePath = new List<string>();
and in the action button method, why don't you do
if(filePath != null)
SanitizeFileNames.FileCleanup(filePath);
You call filePath.Add twice ?
Your 'else' is in the wrong place too.
What is dgr2?

Categories