How to make Variable within foreach loop exist? [closed] - c#

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I apologize if this sounds like a ignorant question but I am quite new to C#. I am one error away from getting my program to work:
"the name 'filesInfo' does not exist in the current context"
I am trying to get this variable to exist and attempted at solving this by declaring it outside the foreach loop, but to no avail.
Here is my current script:
public class MyClass
{
public static string src = #"C:\Users\Bold Defiance\Desktop\FolderA";
public static string dst = #"C:\Users\Bold Defiance\Desktop\FolderB";
public static string[] files = System.IO.Directory.GetFiles(src, "*.txt");
public void Move_Modified_Files()
{
foreach (string s in files)
{
string fileName = Path.GetFileName(s);
FileInfo filesInfo = new FileInfo(fileName);
}
try
{
if (filesInfo.LastWriteTime.Date == DateTime.Today.Date)
{
File.Move(src, dst);
Console.WriteLine("Modified files in {0} were moved to {1}", src, dst);
}
else
{
Console.WriteLine("No new or modified files were created today.");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}
}
class Program
{
static void Main(string[] args)
{
MyClass cls = new MyClass();
cls.Move_Modified_Files();
}
}

You are declaring filesInfo within the foreach loop. As such, its scope is restricted to that loop. If you want to use it elsewhere, you have to move it to the corresponding scope:
FileInfo filesInfo;
foreach (string s in files)
{
string fileName = Path.GetFileName(s);
filesInfo = new FileInfo(fileName);
}
try
{
if (filesInfo.LastWriteTime.Date == DateTime.Today.Date)
{
File.Move(src, dst);
Console.WriteLine("Modified files in {0} were moved to {1}", src, dst);
}
else
{
Console.WriteLine("No new or modified files were created today.");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
That being said, you are currently overriding filesInfo on every iteration of the loop. I imagine that you wanted to check filesInfo for every value of s, so what you actually wanted to do is this:
foreach (string s in files)
{
string fileName = Path.GetFileName(s);
FileInfo filesInfo = new FileInfo(fileName);
try
{
if (filesInfo.LastWriteTime.Date == DateTime.Today.Date)
{
File.Move(src, dst);
Console.WriteLine("Modified files in {0} were moved to {1}", src, dst);
}
else
{
Console.WriteLine("No new or modified files were created today.");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}

Try this:
public void Move_Modified_Files()
{
foreach (string s in files)
{
string fileName = Path.GetFileName(s);
FileInfo filesInfo = new FileInfo(fileName);
try
{
if (filesInfo.LastWriteTime.Date == DateTime.Today.Date)
{
File.Move(src, dst);
Console.WriteLine("Modified files in {0} were moved to {1}", src, dst);
}
else
{
Console.WriteLine("No new or modified files were created today.");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}
}

You declared
FileInfo filesInfo = new FileInfo(fileName);
inside the first loop. When this context ends with the } the variable will disappear.
My guess is that you wanted to do this.
public class MyClass
{
public static string src = #"C:\Users\Bold Defiance\Desktop\FolderA";
public static string dst = #"C:\Users\Bold Defiance\Desktop\FolderB";
public static string[] files = System.IO.Directory.GetFiles(src, "*.txt");
public void Move_Modified_Files()
{
foreach (string s in files)
{
// These values will exist until their enclosing context is closed
// The context starts with the most recent opening bracket {
// So these values, will exist until this loop iterates to the next value
string fileName = Path.GetFileName(s);
FileInfo filesInfo = new FileInfo(fileName);
// Attempt to use the currently selected fileinfo
try
{
if (filesInfo.LastWriteTime.Date == DateTime.Today.Date)
{
File.Move(src, dst);
Console.WriteLine("Modified files in {0} were moved to {1}", src, dst);
}
else
{
Console.WriteLine("No new or modified files were created today.");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
// The next } bracket below is the one that closes the context mentioned earlier
// When it closes, all values declared in this sub-context will no longer exist.
}
}
}
class Program
{
static void Main(string[] args)
{
MyClass cls = new MyClass();
cls.Move_Modified_Files();
}
}

Related

How to copy several files at the same time?

I have a number of USB drives that I want to copy a folder to.
I can't transfer files at the same time, but only one file at a time.
Although I manage to be directed to a different drive each time, but it is not at the same time.
Where am I wrong?
static void Main(string[] args)
{
string path = #"....";
Parallel.ForEach(
DriveInfo.GetDrives(), drive =>
{
if (drive.DriveType == DriveType.Removable)
{
CloneDirectory(path, drive.Name);
}
}
);
}
private static void CloneDirectory(string root, string dest)
{
foreach (var directory in Directory.GetDirectories(root))
{
//Get the path of the new directory
var newDirectory = Path.Combine(dest, Path.GetFileName(directory));
//Create the directory if it doesn't already exist
Directory.CreateDirectory(newDirectory);
//Recursively clone the directory
CloneDirectory(directory, newDirectory);
}
try
{
foreach (var file in Directory.GetFiles(root))
{
try
{
File.Copy(file, Path.Combine(dest, Path.GetFileName(file)), false);
Console.WriteLine(Path.Combine(dest, Path.GetFileName(file)));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}

system io file not found exception/ error handling

I'm working in C# and I try to do a program that get some infoes the files in a Directory. I made it but i have a problem with the error Handling. When the program runs and for example I give just random numbers to list file infoes i get this error message:
"System.IO.DirectoryNotFoundException: "'Could not find a part of the path 'C:\Temp\first_project\first_project\bin\Debug\12345'.'"
Please someone help me to do the error handling.
Thank you in advance.
using System;
using System.IO;
class Test
{
static void Main(string[] args)
{
Console.WriteLine("Please :");
string hely = Console.ReadLine();
string[] __file = Directory.GetFiles(hely);
string[] __dir = Directory.GetDirectories(hely);
foreach (string i in __file)
{
FileInfo fajl = new FileInfo(i);
Console.WriteLine("{0},{1},{2}", fajl.Name, fajl.Extension, fajl.LastWriteTime.ToString());
}
foreach (string i in __dir)
{
DirectoryInfo _file = new DirectoryInfo(i);
Console.WriteLine("{0},{1},{2}", _file.Name, _file.Extension, _file.LastWriteTime.ToString());
}
Console.ReadKey();
}
}
You should check existence of a path with
System.IO.Directory.Exists(directory)
and of a file with
System.IO.File.Exists(filePath)
Then, you need to take the try-catch block inside the for-loop, to catch any possible exceptions that occur because of insufficient rights/permissions.
e.g.
foreach (string i in __file)
{
try
{
FileInfo fajl = new FileInfo(i);
Console.WriteLine("{0},{1},{2}", fajl.Name, fajl.Extension, fajl.LastWriteTime.ToString());
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
throw;
}
}
You could also create two try-catch blocks - depends on what you want to do.
try
{
foreach (string i in __file)
{
try
{
FileInfo fajl = new FileInfo(i);
Console.WriteLine("{0},{1},{2}", fajl.Name, fajl.Extension, fajl.LastWriteTime.ToString());
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
throw;
}
}
}
catch (System.Exception exLoop)
{
System.Console.WriteLine(exLoop.Message);
throw;
}
Note that in your example, you should first check if the directory "hely" exists:
if (!System.IO.Directory.Exists(hely))
{
System.Console.Error.WriteLine("Directory \"{0}\" does not exist.", hely);
System.Environment.Exit(1);
// or: return;
}
Since exception handling is usually very slow, I would however recommend that you check for the existence of the file/directory explicitly. It would also be a good idea to do so for the file/directory-listing & read-access rights for the respective user. But even if you do so, keep the try-catch, because there might be cases where your program suddenly fails - e.g. when a removable storage is forcefully removed.
Use try catch
using System;
using System.IO;
class Test
{
static void Main(string[] args)
{
Console.WriteLine("Please :");
string hely = Console.ReadLine();
try
{
string[] __file = Directory.GetFiles(hely);
string[] __dir = Directory.GetDirectories(hely);
foreach (string i in __file)
{
FileInfo fajl = new FileInfo(i);
Console.WriteLine("{0},{1},{2}", fajl.Name, fajl.Extension, fajl.LastWriteTime.ToString());
}
foreach (string i in __dir)
{
DirectoryInfo _file = new DirectoryInfo(i);
Console.WriteLine("{0},{1},{2}", _file.Name, _file.Extension, _file.LastWriteTime.ToString());
}
}
catch(System.IO.DirectoryNotFoundException ex)
{
Console.WriteLine("Directory not found");
}
Console.ReadKey();
}
}
You can check if the file exists
foreach (string i in __file)
{
if (File.Exists(i))
{
FileInfo fajl = new FileInfo(i);
Console.WriteLine("{0},{1},{2}", fajl.Name, fajl.Extension, fajl.LastWriteTime.ToString());
}
}
RTFM?
Read Directory.GetFiles method
It says that you will get the DirectoryNotfound exception if the specified path is not found. Obviously folder 'C:\Temp\first_project\first_project\bin\Debug\12345' does not exist.
Proper code would be:
string hely = ...
try
{
string[] files = Directory.GetFiles(hely);
ProcessFiles(files);
}
catch (DirectoryNotFoundException exc)
{
Console.WriteLine(exc.Message);
}
If you don't know how to react on exceptions read MSDN about exception handling

c# - How to multithreading Iterate Through a Directory Tree, in folder 1000000 files

I need to save in database file Name and Size in byte from folder and all subfolder.
In this folder lay 1 000 000 files.
And when I use example from msdn it works 4 days, that very slowly.
static void Main(string[] args)
{
string pdxPathDocFiles = System.Configuration.ConfigurationManager.AppSettings["PDX_PathDocFiles"] as string;
if (string.IsNullOrEmpty(pdxPathDocFiles))
{
Console.WriteLine("In the configuration file is missing the path to the root directory - PDX_PathDocFiles.");
}
else
{
if (!Directory.Exists(pdxPathDocFiles))
{
Console.WriteLine("Directory not found");
}
else
{
try
{
Console.WriteLine("rootPath: " + pdxPathDocFiles);
PayDox_EPD19_T20_RGMEntities db = new PayDox_EPD19_T20_RGMEntities();
System.IO.DirectoryInfo rootDir = new DirectoryInfo(pdxPathDocFiles);
db.FileDBRecord.RemoveRange(db.FileDBRecord);
WalkDirectoryTree(rootDir, rootDir.ToString(), db);
db.SaveChanges();
}
catch (Exception)
{
Console.WriteLine("Failed to connect to the database");
}
Console.WriteLine("All ok");
}
}
Console.WriteLine("Bye, Good Day.");
}
static void WalkDirectoryTree(System.IO.DirectoryInfo root, string rootDir, PayDox_EPD19_T20_RGMEntities db)
{
System.IO.FileInfo[] files = null;
System.IO.DirectoryInfo[] subDirs = null;
try
{
files = root.GetFiles("*.*");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
}
if (files != null)
{
foreach (System.IO.FileInfo fi in files)
{
db.FileDBRecord.Add(new FileDBRecord { FileName = fi.FullName.Replace(rootDir, ""), FileSize = fi.Length });
}
subDirs = root.GetDirectories();
foreach (System.IO.DirectoryInfo dirInfo in subDirs)
{
WalkDirectoryTree(dirInfo, rootDir, db);
}
}
db.SaveChanges();
}
When I try another way, it throw-out with exception stack overflow exception.
static void Main(string[] args)
{
string pdxPathDocFiles = System.Configuration.ConfigurationManager.AppSettings["PDX_PathDocFiles"] as string;
if (string.IsNullOrEmpty(pdxPathDocFiles))
{
Console.WriteLine("In the configuration file is missing the path to the root directory - PDX_PathDocFiles.");
}
else
{
if (!Directory.Exists(pdxPathDocFiles))
{
Console.WriteLine("Directory not found");
}
else
{
try
{
Console.WriteLine("rootPath: " + pdxPathDocFiles);
PayDox_EPD19_T20_RGMEntities db = new PayDox_EPD19_T20_RGMEntities();
db.FileDBRecord.RemoveRange(db.FileDBRecord);
db.SaveChanges();
Console.WriteLine("Remove data from table");
System.IO.FileInfo[] files = null;
System.IO.DirectoryInfo rootDir2 = new DirectoryInfo(pdxPathDocFiles);
try
{
files = rootDir2.GetFiles("*.*", SearchOption.AllDirectories);
Console.WriteLine("Reed {0} fileName", files.Length);
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("You do not have permission to access one or more folders in this directory tree.");
Console.WriteLine(ex.Message);
return;
}
db.FileDBRecord.AddRange(files.Select(x => new FileDBRecord { FileName = x.FullName.Replace(pdxPathDocFiles, ""), FileSize = x.Length }));
db.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("All ok");
}
}
Console.WriteLine("Bye, Good Day.");
}
How make program faster, maybe add multithreading?
For starters, your code isn't async. Break this out into a separate class and make the methods async. This allows the thread to be used while waiting for an IO operation. Anytime your calling the Database or File system use async equivalent methods.
The second thing I would do is try to make is so each transaction is atomic. If you doing something x amount of times, write the program in such a way that each x time can be done is isolation. Once that is done you can run these is parallel by creating a new Task (Task.Run).
Once those 2 are done and the task is still taking a while, look into TPL Dataflow. That can buffer requests for you to optimize your process.
I improved first example from msdn, by adding there TPL library.
Now it working 4 hour, not 4 days.
static void Main(string[] args)
{
string pdxPathDocFiles = System.Configuration.ConfigurationManager.AppSettings["PDX_PathDocFiles"] as string;
if (string.IsNullOrEmpty(pdxPathDocFiles))
{
Console.WriteLine("In the configuration file is missing the path to the root directory - PDX_PathDocFiles.");
}
else
{
if (!Directory.Exists(pdxPathDocFiles))
{
Console.WriteLine("Directory not found");
}
else
{
try
{
Console.WriteLine("rootPath: " + pdxPathDocFiles);
PayDox_EPD19_T20_RGMEntities db = new PayDox_EPD19_T20_RGMEntities();
System.IO.DirectoryInfo rootDir = new DirectoryInfo(pdxPathDocFiles);
db.Database.ExecuteSqlCommand("TRUNCATE TABLE [FileDBRecord]");
db.SaveChanges();
db.Dispose();
Console.WriteLine("Remove data from table");
WalkDirectoryTree(rootDir, rootDir.ToString());
Console.WriteLine("All ok");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Console.WriteLine("Bye, Good Day.");
Console.WriteLine("Processing complete. Press any key to exit.");
Console.ReadKey();
}
static void WalkDirectoryTree(System.IO.DirectoryInfo root, string rootDir)
{
//Console.WriteLine("Go to folder: "+ root.FullName.Replace(rootDir, ""));
System.IO.FileInfo[] files = null;
System.IO.DirectoryInfo[] subDirs = null;
try
{
files = root.GetFiles("*.*");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
if (files != null)
{
PayDox_EPD19_T20_RGMEntities db = new PayDox_EPD19_T20_RGMEntities();
foreach (var currentElement in files)
{
db.FileDBRecord.Add(new FileDBRecord { FileName = currentElement.FullName.Replace(rootDir, ""), FileSize = currentElement.Length });
}
db.SaveChanges();
db.Dispose();
subDirs = root.GetDirectories();
Parallel.ForEach(subDirs,
currentElement =>
{
try
{
WalkDirectoryTree(currentElement, rootDir);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
});
}
}
}
maybe we can fix your second code.. (untested, but may not throw the exception)
if you test it, let me know if it is faster..
static void Main(string[] args)
{
string pdxPathDocFiles = System.Configuration.ConfigurationManager.AppSettings["PDX_PathDocFiles"] as string;
if (string.IsNullOrEmpty(pdxPathDocFiles))
{
Console.WriteLine("In the configuration file is missing the path to the root directory - PDX_PathDocFiles.");
}
else
{
if (!Directory.Exists(pdxPathDocFiles))
{
Console.WriteLine("Directory not found");
}
else
{
try
{
Console.WriteLine("rootPath: " + pdxPathDocFiles);
PayDox_EPD19_T20_RGMEntities db = new PayDox_EPD19_T20_RGMEntities();
db.FileDBRecord.RemoveRange(db.FileDBRecord);
db.SaveChanges();
Console.WriteLine("Remove data from table");
IList<FileDBRecord> files = null;
System.IO.DirectoryInfo rootDir2 = new DirectoryInfo(pdxPathDocFiles);
try
{
files = rootDir2.GetFiles("*.*", SearchOption.AllDirectories).Select(x => new FileDBRecord { FileName = x.FullName.Replace(pdxPathDocFiles, ""), FileSize = x.Length });
Console.WriteLine("Reed {0} fileName", files.Length);
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("You do not have permission to access one or more folders in this directory tree.");
Console.WriteLine(ex.Message);
return;
}
files.Foreach(db.FileDBRecord);
db.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("All ok");
}
}
Console.WriteLine("Bye, Good Day.");
}

Using webclient to download file in a WPF application

I'm making a WPF application.
I'm using WebClient to download files. I have a list of the name of the files that should be downloaded from a current path. I use an foreach to iterate through each name and then download each file sequency. The name of the file i get from a torrent file which i decode.
public class DownloadGameFile
{
private DownloadTorrentFile DLTorrent;
//List of file that already exist
private List<string> ExistFile = new List<string>();
DirectoryInfo fileInfo;
private volatile bool _completed;
private string savePath = #"C:\Program Files (x86)\program\Client\package\downloads\";
public DownloadGameFile()
{
DLTorrent = new DownloadTorrentFile();
fileInfo = new DirectoryInfo(savePath);
}
public bool StartDownload(int torrentId)
{
try
{
DLTorrent.DecodeTorrent(torrentId);
//File info from a Directory
FileInfo[] files = fileInfo.GetFiles();
foreach (FileInfo i in files)
{
Console.WriteLine("Files exit ");
if (DLTorrent.GameInfomation[i.Name] != i.Length)
{
i.Delete();
}
else
{
Console.WriteLine("add files ");
ExistFile.Add(i.Name);
}
}
//Make a list which file not downloaded yet
var res = DLTorrent.GameInfomation.Keys.Except(ExistFile);
foreach (var x in res)
{
Console.WriteLine(x);
}
foreach (var x in res)
{
DownloadProtocol("http://cdn.path.com/rental/" + torrentId + "/" + x, savePath + x);
}
return true;
}
catch
{
return false;
}
}
public void DownloadProtocol(string address, string location)
{
WebClient client = new WebClient();
Uri Uri = new Uri(address);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress);
client.DownloadFileAsync(Uri, location);
}
private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
// Displays the operation identifier, and the transfer progress.
Console.WriteLine("{0} downloaded {1} of {2} bytes. {3} % complete...",
(string)e.UserState,
e.BytesReceived,
e.TotalBytesToReceive,
e.ProgressPercentage);
}
private void Completed(object sender, AsyncCompletedEventArgs e)
{
if (e.Cancelled == true)
{
Console.WriteLine("Download has been canceled.");
}
else
{
Console.WriteLine("Download completed!");
}
}
This code work fine in an Console app with a current thread blocker. But when I use the same code in an WPF app It doesn't. I'm using a button to execute the StartDownload() function, but when I do that it start downloading all the files at the same time. Example the first file get 3% done and then it switch to another file and so on. I really don't know why this isn't working.
Have you considered not using .DownloadFileAsync? You can try .DownloadFile and start DownloadProtocol() with a single background thread. Although I think you'll have to rethink your DownloadProgress output.
I do something very similar within a winform.

deleting entire folder including all the files inside

The following is what i have when i try to delete a folder:
namespace sortfolder
{
class Program
{
static string path = "C:\\Work\\6.70_Extensions\\NightlyBuild\\";
static void Main(string[] args)
{
var di = new DirectoryInfo("C:\\Work\\6.70_Extensions\\NightlyBuild");
foreach (var file in di.GetFiles("*", SearchOption.AllDirectories))
file.Attributes &= ~FileAttributes.ReadOnly;
var files = Directory.GetDirectories(path, "SASE Lab Tools.*");
foreach(var file in files)
Console.WriteLine(file);
foreach(var file in files.OrderByDescending(x=>x).Skip(7))
Console.WriteLine(file);
foreach(var file in files.OrderByDescending(x=>x).Skip(7))
Directory.Delete(file);
}
}
}
As mentioned in the title, i would like to delete this folder along with all its content. How do i go about doing it? Apparently i have IOException # Directory.Delete(file) as it contains files
You missing true Directory.Delete(file,true);
For example
public static void Main()
{
string path = #"c:\MyDir\temp";
try
{
Directory.Delete(path, true);
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
finally {}
}
Directory.Delete has a second parameter which takes a bool = recrusive. Use that overload instead.
http://msdn.microsoft.com/en-us/library/fxeahc5f.aspx

Categories