C# Best way to create folder-structures - c#

I'd like to automatically generate diffrent folder structures (As a preperation for new Video/Film-Editing projects). It also allows to add special folders like After Effects and Photoshop to every folder-structure.
It should read the structure from a config file and then create the folders.
My current code looks like this:
if(tbPath.Text == "_______________________________________________________"
|| tbConfigPath.Text == "_______________________________________________________"
|| tbPath.Text == ""
|| tbConfigPath.Text == "")
{
System.Windows.MessageBox.Show("You didn't enter a valid Path.", "Invalid Path", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
//List for the paths
List<string> paths = new List<string>();
List<string> finalpaths = new List<string>();
string outPath = tbPath.Text;
//Where to get the config from
string configPath = tbConfigPath.Text;
string line = "";
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader(configPath);
while ((line = file.ReadLine()) != null)
{
paths.Add(line);
}
file.Close();
for (int i = 0; i < paths.Count(); i++)
{
finalpaths.Add(outPath + paths[i]);
}
//----------------Folder Generatring------------
for (int i = 0; i < paths.Count(); i++)
{
Directory.CreateDirectory(finalpaths[i]);
}
// Add After Effects
if (cbAE.IsChecked == true)
{
string AEpath = outPath + "\\AfterEffects";
Directory.CreateDirectory(AEpath);
}
// Add Photoshop
if (cbAE.IsChecked == true)
{
string PSpath = outPath + "\\Photoshop";
Directory.CreateDirectory(PSpath);
}
System.Windows.MessageBox.Show("The folders where generated successfully", "Success", MessageBoxButton.OK, MessageBoxImage.Information);
pgStartUp pgStart = new pgStartUp();
NavigationService.Navigate(pgStart);
But I feel like this isn't really efficient. Is there any better way?

When you use:
Directory.CreateDirectory(path);
This line creates all or missing directories in the path string you are passing as a parameter. So you don't need anything else.
All your logic should be focused on creating a correct path string, taking into account the root directory and things like that.

As coders we often think in code and try to solve everything with it.
If the base structure is the same, create the folder structure once, zip it up, and then:
Directory.CreateDirectory(tbPath.Text);
ZipFile.ExtractToDirectory("yadayada.zip", tbPath.Text);
// Add After Effects
if (cbAE.IsChecked == true)
{
string AEpath = outPath + "\\AfterEffects";
Directory.CreateDirectory(AEpath);
}
// Add Photoshop
if (cbAE.IsChecked == true)
{
string PSpath = outPath + "\\Photoshop";
Directory.CreateDirectory(PSpath);
}

Related

how to alert the user on duplications in the moving file procces in a Web-Application

I have a source and destination path with the same folder and file names (source has some extra files). my question is when I have cut source locations files and folders and to paste the destination location
how to copied initially the extra files(destination not having files)?
how to through the error after paste the extra files "the folder and files already exist do you want to replace it" message?
after getting the response how can I move and delete the source files?
somebody can help me guys I am stuck with this logic nearly 2 days.
Note: am the beginner of the C# server side code.
thanks, advance. Hi All, thank you for your reply, I have written the same structure with #RezaNoei mentioned my code was
private void DirectoryCopy(string sourceDirName, string destDirName, bool replace, string action)
{
try
{
// Gets the subdirectories for the specified directory.
var dir = new DirectoryInfo(sourceDirName);
var dirs = dir.GetDirectories();
// If the destination directory doesn't exist, creates it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Gets the files in the directory and copy them to the new location.
var files = dir.GetFiles();
foreach (var file in files)
{
var oldPath = Path.Combine(sourceDirName, file.Name);
var temppath = Path.Combine(destDirName, file.Name);
var fileExist = File.Exists(temppath);
if (!fileExist)
{
if (action != "paste")
{
file.CopyTo(temppath, true);
}
else
{
File.Move(oldPath, temppath);
}
}
else if (fileExist && replace)
{
File.Delete(temppath);
if (action != "paste")
{
file.CopyTo(temppath, true);
}
else
{
File.Move(oldPath, temppath);
}
}
}
if (action == "paste")
{
DeleteDirectory(sourceDirName);
}
}
catch (Exception e)
{
throw e;
}
}
Use this Function:
Note: If you are developing a web-application and you want to alert this through Html, it doesn't help you. Please read the Next Section "For Web-Application"
Note2: this function doesn't check for inner folders. so if you have a nested path, we should write a recursive function.
public void Copy(string Source, string Destination)
{
string[] SourceFiles = System.IO.Directory.GetFiles(Source);
for (int i = 0; i < SourceFiles.Length; i++)
{
string DestinationFilePath = System.IO.Path.Combine(Destination, System.IO.Path.GetFileName(SourceFiles[i]));
if (System.IO.File.Exists(DestinationFilePath))
{
var DialogResult = MessageBox.Show($"File `{System.IO.Path.GetFileName(SourceFiles[i])}` Exists in the Destination. Are you want to overwrite this file ?", "File Exist !", MessageBoxButtons.YesNo);
if (DialogResult == DialogResult.Yes)
System.IO.File.Copy(SourceFiles[i], DestinationFilePath, true);
}
else
{
System.IO.File.Copy(SourceFiles[i], DestinationFilePath);
}
}
}
For Web-Application:
You actually need to interact with User. And it make our work more complicated than before.
You will Work with Session and you must keep track of this Operation. I don't know which technology are you using but you must but added these ones to Session:
1-1 **Destination Folder**
1-2 **List of Duplicated SourceFiles**
So:
Next Step is to copy non-duplicated files and Added Duplication on Session:
public void Copy(string Source, string Destination)
{
/// Set Session ....
Session["Destination"] = Destination;
List<string> DuplicatedFiles = new List<string>();
string[] SourceFiles = System.IO.Directory.GetFiles(Source);
for (int i = 0; i < SourceFiles.Length; i++)
{
string DestinationFilePath = System.IO.Path.Combine(Destination, System.IO.Path.GetFileName(SourceFiles[i]));
if (System.IO.File.Exists(DestinationFilePath))
{
// Add into Duplication List
DuplicatedFiles.Add(SourceFiles[i]);
}
else
{
System.IO.File.Copy(SourceFiles[i], DestinationFilePath);
}
}
/// Set Session .....
Session["DouplicatedFiles"] = DuplicatedFiles;
}
above code is psudo and the goal is Clear.
Next Step is to show the result of copying or duplications:
I don'n know how do you want to implement such a view for duplication errors and it will not the part of the answer. anyway you may want to let the user to choose the action on each files separately or whole of them at the same time.
depend on your preferences you will have an ActionMethod (In MVC) or something else in WebForm that will do these things:
(If user doesn't want replace the files, it's easy to forget the action)
public void CopyDuplications(bool Overwrite)
{
if (!Overwrite)
return "OK";
else
{
string Destination = Session["Destination"] as string;
var DuplicatedFiles = Session["DouplicatedFiles"] as List<string>();
for (int i = 0; i< DuplicatedFiles.Count; i++)
{
string DestinationFilePath = System.IO.Path.Combine(Destination, System.IO.Path.GetFileName(DuplicatedFiles[i]));
System.IO.File.Copy(DuplicatedFiles[i], DestinationFilePath, true);
}
}
}

Cannot Create a file when using File.Move Error

I have a .csv file as the attached image which has a list of folders and files . I would like to read the .csv file and recreate the same folder structure under different folder.
Say for example I have C:\Data\SourceFolder\Folder2\Folder4\File1.txt , I would like the file to be moved to C:\Data\FilesCopiedfromC\SourceFolder\Folder2\Folder4\File1.txt . In the above destinaton path , the C:\Data\FilesCopiedfromC is going to be the same always . I am able to create the folder structure in the destination but when I do the file.move from source to destination I get a "File cannot be created when it already exists error".
try
{
string inputfile = textBox1.Text.ToString();
using(StreamReader reader = new StreamReader(inputfile))
{
string headerline = reader.ReadLine();
Boolean firstline = true;
string line = string.Empty;
string SourceFileNameCSV;
string SourceFilePathCSV,totalSourceFilePath, strConstructedDestinationfullpath;
string[] parts;
while ((line = reader.ReadLine()) != null)
{
char[] delimiters = new char[] { ',' };
parts= line.Split(delimiters);
if (parts.Length > 0)
{
SourceFilePathCSV = parts[0];
SourceFileNameCSV = parts[1];
totalSourceFilePath = SourceFilePathCSV + "\\" + SourceFileNameCSV;
strDestinationDynamicPath = SourceFilePathCSV.Replace("C:\\Data\\", " ").TrimEnd();
strConstructedDestinationfullpath = Path.Combine(strDestinationStaticPath, strDestinationDynamicPath);
if (!string.IsNullOrEmpty(strConstructedDestinationfullpath))
{
if (!Directory.Exists(strDestinationDynamicPath))
{
Directory.CreateDirectory(strConstructedDestinationfullpath);
}
// File.Move(totalSourceFilePath, strConstructedDestinationfullpath);
}
}
}
}
}//try
Any help is appreciated.
You need to specify a file name for the destination, currently you are just providing a path:
File.Move(
totalSourceFilePath,
Path.Combine(strConstructedDestinationfullpath, Path.GetFileName(totalSourceFilePath));
It's because, apparently, the file already exists in the destination. What you can do is check if the file exists an delete if so:
if (System.IO.File.Exists("filename"))
{
//delete
System.IO.File.Delete("filename"); //try/catch exception handling
needs to be implemented
}

How to read and update multiple files

I have 10 txt files in Debug\Tests\Text\ (10 txt files). I need to write a program to open all 10 files and updated every single file. I'm not sure how to do it. Now, I'm actually reading the folder and getting the file name and storing the file name in an array. Below is my code:
private void getFilesName()
{
string[] fileArray = Directory.GetFiles(#"Tests\Text");
//looping through the folder and get the fileNames
for (int i = 0; i<fileArray.Length; i++)
{
MessageBox.Show(fileArray[i]); // I'm doing this is to double check i manage to get the file name.
}
}
After doing this, it do read all the text file name, but the challenge now is for me to access the filename and updating every file in it. I have also created another method just for updating the values in the txt files, below is the code:
private bool modifySQLFile()
{
string destFileName = #"Tests\Text\" // I need the fileName?
string[] fileTexts = File.ReadAllLines(destFileName);
int counter = 0;
//Processing the File
foreach(string line in fileTexts)
{
//only read those non-comments line
if(line.StartsWith("--") == false)
{
//Start to replace instances of Access ID
if(line.Contains(Variable) == true)
{
fileTexts[counter] = fileTexts[counter].Replace(Variable, textBox2.Text);
}
}
counter++;
}
//check if file exists in the backup folder
if(File.Exists("Tests\\Text\\file name "+ textBox1.Text +".sql") == true)
{
MessageBox.Show("This file already exist in the backup folder");
return false;
}
else
{
//update the file
File.WriteAllLines(destFileName, fileTexts);
File.Move(destFileName, "Tests\\Text\\file name"+ textBox1.Text +".sql");
MessageBox.Show("Completed");
return true;
}
}
Your problem seems to be passing the filename variable from the loop to the method.
In order to do what you want, add a parameter to the method:
private bool ModifySQLFile(string filename)
{
string[] fileTexts = File.ReadAllLines(filename);
// ...
}
Then call the method with this parameter:
for (int i = 0; i<fileArray.Length; i++)
{
ModifySQLFile(fileArray[i]);
}
But in general you really don't want to treat a formal language as plaintext like you do. It's very easy to break the SQL like that. What if the user wanted to replace the text "insert", or replaces something with "foo'bar"?
First, implement one (file) modification:
private bool modifySQLFile(String file) {
// given source file, let´s elaborate target file name
String targetFile = Path.Combine(
Path.GetDirectoryName(file),
String.Format("{0}{1}.sql",
Path.GetFileNameWithoutExtension(file),
textBox1.Text));
// In case you want a back up
//TODO: given source file name, elaborate back up file name
//String backUpFile = Path.Combine(...);
// Check (validate) before processing: do not override existing files
if (File.Exists(targetFile))
return false;
//TODO: what if back up file exists? Should we override it? skip?
// if line doesn't start with SQL commentary --
// and contains a variable, substitute the variable with its value
var target = File
.ReadLines(file)
.Select(line => (!line.StartsWith("--") && line.Contains(Variable))
? line.Replace(Variable, textBox2.Text)
: line);
// write modified above lines into file
File.WriteAllLines(targetFile, target);
// In case you want a back up
// Move file to backup
//File.Move(file, backUpFile);
return true;
}
Then call it in the loop:
// enumerate all the text files in the directory
var files = Directory
.EnumerateFiles("#"Tests\Text", "*.txt");
//TODO: you may want filter out some files with .Where
//.Where(file => ...);
// update all the files found above
foreach (var file in files) {
if (!modifySQLFile(file))
MessageBox.Show(String.Format("{0} already exist in the backup folder", file));
}
Please, do not do:
Use Magic values: what is #"Tests\Text\" within your modifySQLFile
Mix UI MessageBox.Show(...) and logic: modifySQLFile returns true or false and it's caller who can display message box.
Materialize when it's not required (Directory.GetFiles, File.ReadAllLines)
If you would like to edit the files in parallel. With threads you can parallelize work.
for (int i = 0; i < fileArray.Length; i++)
new Thread(UpdateFileThread).Start(fileArray[i]);
private void UpdateFileThread(object path)
{
string filePath = (string)path;
//ToDo: Edit file
}
In your case you would create 10 Threads. That solution works, but is a bad pattern if you have to deal with more than 10 files.
Below i have posted the real time code ,which i have used project
protected void btnSqlfinder_Click(object sender, EventArgs e)
{
//Defining the path of directory where all files saved
string filepath = # "D:\TPMS\App_Code\";
//get the all file names inside the directory
string[] files = Directory.GetFiles(filepath);
//loop through the files to search file one by one
for (int i = 0; i < files.Length; i++)
{
string sourcefilename = files[i];
StreamReader sr = File.OpenText(sourcefilename);
string sourceline = "";
int lineno = 0;
while ((sourceline = sr.ReadLine()) != null)
{
lineno++;
//defining the Keyword for search
if (sourceline.Contains("from"))
{
//append the result to multiline text box
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
if (sourceline.Contains("into"))
{
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
if (sourceline.Contains("set"))
{
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
if (sourceline.Contains("delete"))
{
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
}
}
}
This code will fetch the multiple files in the given directory,and show the lines as per the keyword in a separate text.
But you can easily change as per your requirement,Kindly let me know your thoughts.
Thanks

How to override a specific line in a text file in c#

I have the following situation. I am creating a quiz game in c# visual studio and want to create a Register and Login forms. When a user registers a new account the text file will store their username and password and will set the high score to 0. Each line in the text file looks like that: username;password;highscore. ';' is the delimiter. I have created a new project to create a practice login/ register form. Here is my code for the register form:
private void btnRegister_Click(object sender, EventArgs e)
{
if (txtPassword.Text == txtConfirmPassword.Text)
{
string newAccount = txtName.Text + ";" + txtConfirmPassword.Text + ";" + "0";
TextWriter account = new StreamWriter("../../TextFile/LogonDetails.txt", true);
account.WriteLine(newAccount);
account.Close();
MessageBox.Show("Account created");
}
and here is my code for the login form
string line = "";
StreamReader myReader = new StreamReader("../../TextFile/LogonDetails.txt");
string[] accounts = new string[900000]; int value = 0;
while ((line=myReader.ReadLine()) != null)
{
string[] data = line.Split(';');
if ((data[0] == txtLoginName.Text) && (data[1] == txtLoginPassword.Text) && (int.Parse(data[2]) > int.Parse(txtScore.Text)))
{
value = 1;
break;
}
if ((data[0] == txtLoginName.Text) && (data[1] == txtLoginPassword.Text) && (int.Parse(data[2]) < int.Parse(txtScore.Text)))
{
value = 2;
break;
}
else
{
value = 3;
}
}
if (value == 1)
{
MessageBox.Show("Your score remains the same");
}
else if (value == 2)
{
string updatedAccount = txtLoginName.Text + ";" + txtLoginPassword.Text + ";" + txtScore;
TextWriter textAccounts = new StreamWriter("../../TextFile/LogonDetails.txt");
textAccounts.WriteLine(updatedAccount);
textAccounts.Close();
}
else if (value == 3)
{
MessageBox.Show("Account not found");
}
}
So my question is how can I override the line stored in the text file if in this case 'txtScore' is greater than data[2]? I have tried creating a new line each time the score is greater but that seems inefficient. Is there a way that i can override the line to change the score value? Any help is greatly appreciated
If the file is not that long you can do something like this:
String fileName = #"C:\LogonDetails.txt";
var data = File
.ReadLines(fileName)
.Select(line => line.Split(';'))
.Select(items => {
if ((items[0] == txtLoginName.Text) &&
(items[1] == txtLoginName.Text) &&
(int.Parse(items[2]) < int.Parse(txtScore.Text)))
items[2] = int.Parse(txtScore.Text);
return items;
})
.ToList(); // materialize in oreder to prevent file read/write collision
File.WriteAllLines(fileName, data);
There is no straightforward way to target a specific line in a text file to update the contents on that line. I would suggest storing your information in an XML (structured data) format; .NET already has the capabilities built in for reading and writing to specific nodes in an XML file.
If you don't want to do that, then my suggestion would be that you load all the lines from the text file into memory as instances of, e.g. a User class that has as properties your username, password, and score, and then write them all back out to your data file all at once with any updates to the scores.
By the way, it's generally not a good idea to store passwords in plain text, so I would hope you're at least employing a hashing algorithm.
Well, based on your question you know the line number, so do something like this:
var lines = File.ReadAllLines(#"path to file");
if (lines.Contains("1234"))
{
lines[Array.IndexOf(lines, "1234")] = "new york";
}
File.WriteAllLines(#"path to file", lines);
try like this.

How to pass in name of file when using List<> to store payment records from filename

I've wrote an app to iterate through a directory which contains x amount of files, and import each of them into objects within my program. I create an instance of a class for each of the files which are "payment", and the FileHelpers library reads each line of the file as a new record - into a List. If the files are "info", they are simply moved to preset directories. I am wanting to either append the name of the file to the end of the List or just include this as a variable?
I need to know the name of the file, as each of the "payments" within x amount of files are combined into one fixed width text file to load into our legacy housing management system.
MORE INFO:
When I create the fixed width file, I need to output each of the payments within the List<Payment> PLUS the name of the file they came from. I am unsure of how to do this
within FileHelpers/C# world :(
E.G. (headers for display purposes - not required in export file)
PAYMENTID PAYMENTAMOUNT REFERENCE DATE FILETYPE FILENAME
011102010 000000010000 20148366 26102011 PO SHGR1234.PO
011102011 000000020000 20148367 26102011 PP SHGF6585.PP
011102012 000000030000 20148368 26102011 DD SHGI9854.DD
Any ideas? Below are some code snippets...
UPDATE - FileHelpers lib = http://www.filehelpers.com/
UPDATE 2 - Code used to loop through text file and get payments
public List<SundryPayment> getOAPayments()
{
FileHelperEngine engine = new FileHelperEngine(typeof(SundryPayment));
res = (SundryPayment[])engine.ReadFile(getFilePath());
foreach (SundryPayment record in res)
{
OAPaymentsList.Add(record);
}
return OAPaymentsList;
}
Update 2 - Code to load files
public List<object> getFiles()
{
List<object> obj = new List<object>();
foreach (string file in files)
{
fileExt = Path.GetExtension(file).ToUpper();
filePath = Path.GetFullPath(file).ToUpper();
fileName = Path.GetFileNameWithoutExtension(file).ToUpper();
fullFileName = Path.GetFileName(file).ToUpper();
fileFund = fileName.Substring(0, 4).ToUpper();
if (fileExt == ".DIR" || fileExt == ".ERR" || fileExt == ".CRF" || fileExt == ".STA")
{
//Create Info File
InfoFile infofile = new InfoFile(filePath);
obj.Add(infofile);
}
else if (fileExt == ".PO" || fileExt == ".PP" || fileExt == ".TDC" || fileExt == ".TCC" || fileExt == ".DD" || fileExt == ".CSH" || fileExt == ".CQE"
|| fileExt == ".PZ")
{
if (fileFund == "SHGS" || fileFund == "GGEN")
{
//Create OA Payment File
OAPaymentFile oafile = new OAPaymentFile(filePath);
obj.Add(oafile);
}
else if (fileFund == "SHGF")
{
InfoFile infofile = new InfoFile(filePath);
obj.Add(infofile);
}
else
{
//Create AH Payment File
AHPaymentFile ahfile = new AHPaymentFile(filePath);
//Console.WriteLine("Object Created: {0}", filePath);
obj.Add(ahfile);
}
}
}
return obj;
}
Update 2 - (prototype) code used to create fixed width file. Need to put filename where paymetns came from into this file
public new void Create()
{
string fileToCreate = Path.Combine("\\\\san\\ict\\allpay\\test\\", "cash.txt");
using (StreamWriter sw = new StreamWriter(fileToCreate))
{
foreach (Payment r in ArchousePayments)
{
string archouseref = r.TenancyRef + r.SubAccount + r.CheckDigit;
string firstamount = r.AmountPaid.Replace(".", "");
string amount = firstamount.PadRight(10, 'x');
string transcode = "ALPY";
string date = r.PaymentDate.Substring(0, 2) + r.PaymentDate.Substring(3, 2) + r.PaymentDate.Substring(6, 4);
string siteref;
string comment;
sw.WriteLine(archouseref + amount + transcode + date + amount.Length);
}
}
}
I figured this one one by adding another fixed width record to the end of my Import class, then used this to store the filename via Path.GetFileName(). I could then pass this into the class as required.

Categories

Resources