Output not being written to the DGV in my code - c#

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!

Related

C# Rewrite textfile when listview is using textfile

I've tried and tried but I can't figure out how I'm supposed to fix this.
I have a listView that reads data from a text file.
private void Form3_Load(object sender, EventArgs e)
{
listView1.View = View.Details;
listView1.FullRowSelect = true;
listView1.Columns.Add("Modell", 200);
listView1.Columns.Add("Kw", 100);
listView1.CheckBoxes = true;
string RD_Paneler = "./Data/Paneler.txt";
try
{
List<string> data = File.ReadAllLines(RD_Paneler).ToList();
foreach (string d in data)
{
string[] items = d.Split(new char[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
listView1.Items.Add(new ListViewItem(items));
}
}
catch
{
}
}
`
So then I wanted the user to be able to press a "DELETE" button and all the checkboxed items would be deleted.
private void button2_Click(object sender, EventArgs e)
{
string exeFolder = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
string settingFile = exeFolder + "/Data/Paneler.txt";
var tempFile = Path.GetTempFileName();
string alltext = File.ReadAllText(settingFile);
foreach (ListViewItem item in listView1.Items)
{
var linesToKeep = File.ReadLines(settingFile).Where(l => l != item.Checked.ToString());
if (item.Checked)
{
listView1.Items.Remove(item);
File.WriteAllLines(tempFile, linesToKeep);
File.Delete(settingFile); //Here is where to program crash happends.
File.Move(tempFile, settingFile);
}
}
}
The problem now is that when the program tries to delete the file and replace it with the new one the program crashes because the file it tries to delete is already in use because of the listview.
Here's few solutions -
Use File.ReadAllLines() instead of File.ReadLines(). This should solve the primary problem you are having.
Since you have already read the settingsFile once in memory into alltext. Just use that to iterate over lines like alltext.Split('\n'). Even better IMO.
Hard to understand what your code is doing. Seems sketchy that in a for loop, you have set it up to write, delete, and move the same two files over and again?

Function not working in Form Load, but works everywhere else

I'm using the function below to add items to a DataGridView.
void addFiles(List<string> files)
{
foreach (var item in filesFound)
{
if (File.Exists(item))
{
fileList.Add(item);
MessageBox.Show(item);
string p = GetFolderPath(Personal) + #"\Music Database\";
Directory.CreateDirectory(p);
string file="";
try
{
StreamReader read = new StreamReader(p + "musicdatabase.txt");
file = read.ReadToEnd();
read.Close();
}
catch (Exception e)
{
if (e.ToString().Contains(""))
{
//add error code here later
}
}
StreamWriter write = new StreamWriter(p + "musicdatabase.txt");
write.WriteLine(file + item);
write.Close();
dataGridView1.Rows.Add(getTitle(item), getArtist(item), getDuration(item), item);
}
else
{
//add file not found error code here
}
}
}
The function works fine. It adds the details perfectly. getTitle();, getArtist(); and getDuration(); do what they say. They use TagLib# to get the details of audio files. The file path of the audio file gets written to a text file in the users documents.
The problem arises when I load the form: I read the text file as a whole, putting each line into a new index of List<string> textlist = new List<string>();. This is fine. The list has each line. I then run addFiles(textlist);. I launch the program and it loads, but nothing is added to the DataGridView.
I have a feeling it may be to do with the fact it might not be loaded when the Form_Load is triggered.
private void Form1_Load(object sender, EventArgs e)
{
string p = GetFolderPath(Personal) + #"\Music Database\musicdatabase.txt";
//MessageBox.Show(p);
//MessageBox.Show(File.Exists(p).ToString());
if (File.Exists(p))
{
string[] text = File.ReadAllLines(p);
List<string> textlist = new List<string>();
textlist = text.ToList();
// -- THIS PROVES THE textlist LIST CONTAINS ITEMS --
//foreach (var item in textlist)
//{
//MessageBox.Show(item);
//MessageBox.Show(textlist[0]);
//}
//THIS IS THE PROBLEM
addFiles(textlist);
}
}
Your problem is here:
foreach (var item in filesFound)
You are referencing what appears to be a global variable called filesFound,
rather than the variable files that is passed to the function.

Overwrite file only works once

I have a simple program that copies files and directories from one place to another. I have it set-up that if there are any exceptions (such as if access to the path is denied) it will create a log file with the error.
I have a button that when pressed, performs the copy action. Everything works fine the first time I press the button and the log file is either created or overwritten with the appropriate error messages.
However, if I press the button a second time, the text file is not overwritten and instead the error messages append. If I close out of my program and run it again, the file is overwritten on the first button press. Any thoughts would be greatly appreciated.
target is a string filepath which I'm getting from a FolderBrowserDialog and taking the selected path and setting it to a textbox. loglist is just a simple List<string> I'm using to store the error messages from any exceptions that occur during the copy process.
public partial class Form1 : Form
{
static List<string> logList = new List<string>();
public Form1()
{
InitializeComponent();
}
private static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
if (source.FullName.ToLower() == target.FullName.ToLower())
return;
if (Directory.Exists(target.FullName) == false)
{
Directory.CreateDirectory(target.FullName);
}
foreach (FileInfo fi in source.GetFiles())
{
try
{
fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
}
catch (Exception ex)
{
logList.Add(ex.Message);
}
}
foreach (DirectoryInfo diSourceSub in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSub.Name);
CopyAll(diSourceSub, nextTargetSubDir);
}
}
private void directoryPickerBtn1_Click(object sender, EventArgs e)
{
FolderBrowserDialog folderDialog = new FolderBrowserDialog();
DialogResult folderResult = folderDialog.ShowDialog();
if (folderResult == DialogResult.OK)
{
directoryTextbox1.Text = folderDialog.SelectedPath;
}
}
private void directoryPickerBtn2_Click(object sender, EventArgs e)
{
FolderBrowserDialog folderDialog = new FolderBrowserDialog();
DialogResult folderResult = folderDialog.ShowDialog();
if (folderResult == DialogResult.OK)
{
directoryTextbox2.Text = folderDialog.SelectedPath;
}
}
private void copyBtn_Click(object sender, EventArgs e)
{
string source = (directoryTextbox1.Text);
string target = (directoryTextbox2.Text);
DirectoryInfo dirSource = new DirectoryInfo(source);
DirectoryInfo dirTarget = new DirectoryInfo(target);
try
{
CopyAll(dirSource, dirTarget);
if (logList.Count > 0)
{
using (StreamWriter sw = new StreamWriter(target + #"\log.txt", false))
{
foreach (string error in logList)
{
sw.WriteLine(error);
}
}
}
DialogResult result = MessageBox.Show("Copy Succeeded", "Success");
if (result == DialogResult.OK)
{
string myPath = dirTarget.ToString();
System.Diagnostics.Process prc = new System.Diagnostics.Process();
prc.StartInfo.FileName = myPath;
prc.Start();
}
}
catch (Exception)
{
MessageBox.Show("Copy Failed", "Failed");
}
}
}
}
As #Reza Aghaei pointed out in comments, the problem is that you do not clear the logList.
The file gets created anew every time, but each time you click the Copy button, the loglist still contains the results of the previous copy action.
So you need to clear the list when starting a new copy:
private static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
logList.Clear();
// ...
From your code it seems that you never clear the logList, this means that it appears the file is being appending because the logList still contains all of the old entries.
You'll need to clear the list between copies if you only want relevant entries to that copy, either before you start copying or after you finish writing the file.
This would be better as a separate method
try
{
CopyAll(dirSource, dirTarget);
SaveLog(target + #"\log.txt");
ClearLog();
//...
}
private void SaveLog(string filename)
{
if (logList.Count > 0)
{
FileStream fs = File.Open(target + #"\log.txt", FileMode.Create);
using (StreamWriter sw = new StreamWriter(fs))
{
foreach (string error in logList)
{
sw.WriteLine(error);
}
}
}
}

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?

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