I have a main List of Files Filelist.The Main List Contains Full File Paths and there is a second list copylist it is poupulated by fetching the contents from a directory.I need to replace the File Names in Filelist that matches with the ones in the temporary folder,so i used the following code.
Filelist = new List<string>();
//Code to Populate File List from openfiledialog
try
{
copylist = Directory.GetFiles(temppath + #"\mydir\");
List<string> tempfiles = new List<string>(Filelist);
int x = 0;
foreach (string file in tempfiles)
{
for (int i = 0; i < copylist .Length; i++)
{
if (Path.GetFileName(file) == Path.GetFileName(copylist [i]))
{
MessageBox.Show("Removed: " + file + " \ninserted:" + copylist [i]);
Filelist.RemoveAt(x);
Filelist.Insert(x,copylist [i]);
}
x++;
}
}
}
catch (Exception)
{
}
I tested with 4 files... The File names matched when i checked manually(ie: the same file name in temp folder and in the FileList).The equality check ie:Path.GetFileName(file) == Path.GetFileName(copylist [i]) is satisfied for just 2 files and finally only 1 file is replaced in Filelist even though all 4 files are present in temp folder.
What im i doing wrong.Please advice.
The logic of your program relies on the fact that positions in tempfiles and Filelist are related, and that x corresponds to the position of file in tempfiles. In order for this to work you need to add a break inside the if, and move x++ to the outside loop:
foreach (string file in tempfiles) {
for (int i = 0; i < copylist .Length; i++) {
if (Path.GetFileName(file) == Path.GetFileName(copylist [i])) {
MessageBox.Show($"Removed: {file}\ninserted:{copylist [i])}";
Filelist.RemoveAt(x);
Filelist.Insert(x,copylist[i]);
break; // << Added
}
}
x++; // << Moved
}
Related
I want to rename folder in directory with C# and I write below code :
for (int i = 0; i < datagridview.Rows.Count; i++)
{
System.IO.Directory.Move(#"E:\scan\" + datagridview.Rows[i].Cells[0].Value, #"E:\scan\" + datagridview.Rows[i].Cells[1].Value);
}
cell 0 is number and cell 1 is name
I want replace number with name
its ok when folder is exist same number in datagridview else if dont exist (number) occur exception
I want if dont exist folder in directory with same number in datagridview, continue to end.
Check if the directory exists with System.IO.Directory.Exists(directoryPath).
In your case the code would be:
for (int i = 0; i < datagridview.Rows.Count; i++)
{
if (System.IO.Directory.Exists(#"E:\scan\" + datagridview.Rows[i].Cells[0].Value))
{
System.IO.Directory.Move(#"E:\scan\" + datagridview.Rows[i].Cells[0].Value, #"E:\scan\" + datagridview.Rows[i].Cells[1].Value);
}
else
{
break;
}
}
You're looking for Directory.Exists(string) method.
Also, for the sake of brevity, you might want to import the System.IO namespace. See using directive.
for (int i = 0; i < datagridview.Rows.Count; i++)
{
var sourceFolder = #"E:\scan\" + datagridview.Rows[i].Cells[0].Value;
var destinationFoler = #"E:\scan\" + datagridview.Rows[i].Cells[1].Value;
if (Directory.Exists(sourceFolder))
{
Directory.Move(sourceFolder, destinationFolder);
}
else
{
// Warn the user. E.g.
// MessageBox.Display("Directory not found.");
}
}
I add some files to a listbox on a button:
if (Directory.Exists(DirString))
{
DirectoryInfo dirETC = new DirectoryInfo(DirString);
FileInfo[] Files = dirETC.GetFiles("*.txt");
foreach (FileInfo file in Files)
{
listBox1.Items.Add(file.FullName);
}
If user clicks the delete button, i would like to delete all files in the listbox like this:
try
{
listBox1.BeginUpdate();
for (int i = 0; i < listBox1.Items.Count; i++)
{
string filename = listBox1.Items[i].ToString();
if (File.Exists(filename))
{
File.Delete(filename);
listBox1.Items.Remove(filename);
}
}
listBox1.EndUpdate();
}
catch (Exception)
{
return;
}
The above code works, but its only deleting one file every time i click the delete all button. I think I need to add some kind of foreach loop here to iterate through the items but i'm not sure what is the best way to go about it.
Foreach statement won't allow you to modify a collection you are iterating through, while for will. You just have to be careful with indexes: in your solution after removing the first item (with index=0) the next one become first. Try this approach instead:
listBox1.BeginUpdate();
for (int i = listBox1.Items.Count - 1; i >=0; i--)
{
string filename = listBox1.Items[i].ToString();
if (File.Exists(filename))
{
try
{
File.Delete(filename);
listBox1.Items.Remove(filename);
}
catch (Exception)
{
}
}
}
listBox1.EndUpdate();
When you remove an item from an array that you are iterating over with the for..next statement, you should consider that every time you delete an element, the array count decrease of one element and every element in the array shifts at a lower index. So, when you delete the element at index 0, the previous element that were at index 1 shifts in position 0, but you have already iterated over the index zero, so you end skipping that element and trying to delete the element that was at index 2 before the removal of the item at index 0.
The solution is simple. Loop in reverse order (from highest element to lowest)
for (int i = listBox1.Items.Count-1; i >= 0 ; i--)
{
string filename = listBox1.Items[i].ToString();
if (File.Exists(filename))
{
File.Delete(filename);
listBox1.Items.Remove(filename);
}
}
Copy the contents of the listbox into a string array to prevent errors when remove the items from the listbox in looping.
// Copy the contents of the listbox into a string array
string[] filenameList = listBox1.Items.OfType<string>().ToArray();
try
{
for (int i = 0; i < filenameList.Length; i++)
{
string filename = filenameList[i];
if (File.Exists(filename))
{
File.Delete(filename);
listBox1.Items.Remove(filename);
}
}
}
catch (Exception)
{
}
for (int i = 0; i < BackgroundWorkerConfiguration.urlsDirectories.Count; i++)
{
file_array =Directory.GetFiles(BackgroundWorkerConfiguration.urlsDirectories[i]);
}
DateTime[] creationTimes8 = new DateTime[file_array.Length];
for (int i = 0; i < file_array.Length; i++)
creationTimes8[i] = new FileInfo(file_array[i]).CreationTime;
Array.Sort(creationTimes8, file_array);
file_indxs = 0;
file_indxs = file_array.Length - 1;
timer1.Enabled = true;
urlsDirectories contain 5 directories in which you have a directory on each index.
In each directory there are some files. I have a string Array file_array. The Array I get, file_array at the end of the loop only contains the last directory file and not all the files. I need all the files in that specific directory.
Once that is done, I need to check if the file sizes are greater than 0, and if It is satisfying the condition then continue on.
EDIT** this is the timer1 tick event:
private void timer1_Tick(object sender, EventArgs e)
{
try
{
//this.pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
if (leave == true)
{
pb.Load(file_array[file_indxs]);
}
else
{
pbs[0].Load(file_array[file_indxs]);
}
file_indxs = file_indxs - 1;
if (file_indxs < 0)
{
file_indxs = file_array.Length - 1;
}
}
catch
{
timer1.Enabled = false;
}
}
You can use the following code to get the files with size greater than 0 for all directories into a List:
List<System.IO.FileInfo> fileList = new List<System.IO.FileInfo>();
for (int i = 0; i < BackgroundWorkerConfiguration.urlsDirectories.Count; i++)
{
System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(BackgroundWorkerConfiguration.urlsDirectories[i]);
fileList.AddRange(di.GetFiles("*.*", System.IO.SearchOption.AllDirectories).Where(x => x.Length > 0));
}
Now fileList will contain the list of FileInfo which you can use further in your code.
Please note that I used System.IO.SearchOption.AllDirectories to search in all subdirectories as well - I'm not sure if you need it or not.
You can use the following code to sort the list of files by creation date and convert it to a array of file names:
String[] file_array = fileList.OrderBy(x => x.CreationTime).Select(x => x.FullName).ToArray();
If you want to sort in the descending order, you can use
String[] file_array = fileList.OrderByDescending(x => x.CreationTime).Select(x => x.FullName).ToArray();
You can make a recursive function that gets the files from a directory.
void GetFiles(string directory, ref List<string> directories)
{
var tempFiles = Directory.EnumerateFiles(directory);
var tempDirs = Directory.EnumerateDirectories(directory);
foreach (var x in tempFiles)
directories.Add(x);
foreach (var x in tempDirs)
GetFiles(x, ref directories);
}
This would obtain all the files from a folder and its subfolders. You can then obtain the data for the files you have enumerated.
This piece of code takes a row from 1.txt and splits it into columns. Now I have a directory of 200 + files with ending something.txt and I want them all to open one at a time and this process below run . What is the easiest way to loop thro all the files without changing my code too much ?
Snippet of code currently ;
string _nextLine;
string[] _columns;
char[] delimiters;
delimiters = "|".ToCharArray();
_nextLine = _reader.ReadLine();
string[] lines = File.ReadAllLines("C:\\P\\DataSource2_W\\TextFiles\\Batch1\\1.txt");
//Start at index 2 - and keep looping until index Length - 2
for (int i = 3; i < lines.Length - 2; i++)
{ _columns = lines[i].Split('|');
// Check if number of cols is 3
if (_columns.Length == 146)
{
JazzORBuffer.AddRow();
JazzORBuffer.Server = _columns[0];
JazzORBuffer.Country = _columns[1];
JazzORBuffer.QuoteNumber = _columns[2];
JazzORBuffer.DocumentName =_columns[3];
JazzORBuffer.CompanyNameSoldTo=_columns[4];
}
else
{
// Debug or messagebox the line that fails
MessageBox.Show("Cols:" + _columns.Length.ToString() + " Line: " + lines[i]);
return;
}
}
You can simply use Directory.EnumerateFiles() to iterate over the files colection of the specified directory.
So you can insert your code inside foreach loop, like:
foreach (var file in
Directory.EnumerateFiles(#"C:\\P\\DataSource2_W\\TextFiles\\Batch1", "*.txt"))
{
//your code
}
if i have 4 files. and i want to move half of them to disc 1 and half of them to disc 2.
if im using the:
Directory.Move(source, destination)
im guessing i can change to source by doing a foreach loop + an array or list,
but how could i change the destination after half the source files are transfered and then transfer the other half to the new destination?
string[] files = ... // create a list of files to be moved
for (int i = 0; i < files.Length; i++)
{
var sourceFile = files[i];
var destFile = string.Empty;
if (i < files.Length / 2)
{
destFile = Path.Combine(#"c:\path1", Path.GetFileName(sourceFile));
}
else
{
destFile = Path.Combine(#"d:\path2", Path.GetFileName(sourceFile));
}
File.Move(sourceFile, destFile);
}
UPDATE:
Here's a lazy approach which doesn't require you to load all the file names in memory at once which could be used for example in conjunction with the Directory.EnumerateFiles method:
IEnumerable<string> files = Directory.EnumerateFiles(#"x:\sourcefilespath");
int i = 0;
foreach (var file in files)
{
var destFile = Path.Combine(#"c:\path1", Path.GetFileName(file));
if ((i++) % 2 != 0)
{
// alternate the destination
destFile = Path.Combine(#"d:\path2", Path.GetFileName(file));
}
File.Move(sourceFile, destFile);
}
The simple answer is that you would move the individual files instead.
Use a Directory.GetFiles(source) to get a list of files in the folder, get a .Count() of that and then loop through each file and move it.
public void MoveFilesToSplitDestination(string source, string destination1, string destination2)
{
var fileList = Directory.GetFiles(source);
int fileCount = fileList.Count();
for(int i = 0; i < fileCount; i++)
{
string moveToDestinationPath = (i < fileCount/2) ? destination1 : destination2;
fileList[i].MoveTo(moveToDestination);
}
}
int rubikon= files.Count() / 2;
foreach (var file in files.Take(rubikon))
file.Move(/* first destination */));
foreach (var file in files.Skip(rubikon))
file.Move(/* second destination */));