Restrict my code to write to a specific folder C# - c#

I got a folder in C called "donotcopy". I want to protect it and no matter what not to be allowed to create files within.
My intuitive solution was just to create a str with same name and where user enters a destination it just checks if it's the same.
Example:
class FileCreation
{
public static void Main()
{
string notallowed = ("c:\\donotcopy");
string filename = ("Nick.txt");
Console.WriteLine("Enter the full path to create an empty file.");
string path = Console.ReadLine();
path = path.ToLower();
while (notallowed == path)
{
Console.WriteLine("The chosen path is not allowed please try another one.");
path = Console.ReadLine();
path = path.ToLower();
}
using (FileStream fs = File.Create(path + filename)) ;
}
}
The problem is if the user enters the destination as "c:.\donotcopy" it will still create the file inside the restricted folder.

You can make use of the DirectoryInfo class, which will allow you to retrieve info about the full path of a directory.
class FileCreation
{
public static void Main()
{
string notallowed = ("c:\\donotcopy");
string filename = ("Nick.txt");
Console.WriteLine("Enter the full path to create an empty file.");
DirectoryInfo directory = new DirectoryInfo(Console.ReadLine());
while (notallowed.Equals(directory.FullName, StringComparison.InvariantCultureIgnoreCase))
{
Console.WriteLine("The chosen path is not allowed please try another one.");
directory = new DirectoryInfo(Console.ReadLine());
}
string fullPath = Path.Combine(directory.FullName, filename);
using (FileStream fs = File.Create(fullPath)) ;
}
}

Related

(Updated) Working with files, check if exists or not

I am working with files on C# and I got to a point where I don't know how to continue anymore.
The scenario is this: If I upload 3 or more files with the same name at the same time, I want to handle them and change their name to from "myfile.pdf" to "myfile.pdf(1)/(2)/(3)..." depending on how much files I upload.
This is what I have tried so far and in this case, this only works for only the second file because when the third one comes, it will check there is any file with the same - yes, okay name it "myfile.pdf(2) - but this exists too so it will go to another place.
How can I achieve having the same three files in the same folder with this naming convention?
Here's what I have tried so far:
string FileName = "MyFile.pdf";
string path = #"C:\Project\MyPdfFiles\"
if (File.Exists(path))
{
int i = 1;
var FileExists = false;
while (FileExists==false)
{
if (FileExists == false)
{
FileName = FileName + "(" + i + ")";
}
else
return;
i++;
}
}
And the result of this code is: "MyFile.pdf", "MyFile.pdf(1)" And the third one doesn't load here.
I think I'm missing something in the loop or idk :(.
Can someone help me?
I have tried also this:
if(File.Exists(path) || File.Exists(path+"(")
//because when the second file its uploaded, its name will be SecondFile.pdf(1), so this will return true and will proceed running, but still the iteration will "always" start from 0 since everytime I upload a file, I have to refresh the process.
Don't use return inside your while loop, better set 'FileExists = true' whenever you want you loop to stop. A return statement will exit your current method.
I think your problem can be easily solved using recursion, something like this (untested):
public class Program
{
public string FileName { get; set; }
public Program() {
string fileName = "MyFile.pdf";
string path = #"C:\Project\MyPdfFiles\";
FileName = CheckFileName(path, fileName);
}
public string CheckFileName(string path, string fileName, int iteration = 0) {
if (File.Exists($"{path}{fileName}")) {
iteration++;
CheckFileName(path, $"{fileName}({iteration})", iteration);
}
return fileName;
}
}
What this does is: it CheckFileName method will keep calling itself until it finds a name that doesn't exist yet.
This should do the job.
public class Program
{
public static string GetUnusedFilePath(string directorypath, string filename, string ext)
{
string fullPath = $"{directorypath}{filename}{ext}";
int inc = 0;
// check until you have a filepath that doesn't exist
while (File.Exists(fullPath))
{
fullPath = $"{directorypath}{filename}{inc}{ext}";
inc++;
}
return fullPath;
}
public static void UploadFile(string filepath)
{
using (FileStream fs = File.Create(filepath))
{
// Add some text to file
Byte[] title = new UTF8Encoding(true).GetBytes("New Text File");
fs.Write(title, 0, title.Length);
}
}
public static void Main()
{
string[] filestoUpload = { "file", "file", "file", "anotherfile", "anotherfile", "anotherfile" };
string directorypath = #"D:\temp\";
string ext = ".txt";
foreach(var file in filestoUpload)
{
var filePath = GetUnusedFilePath(directorypath, file, ext);
UploadFile(filePath);
}
}
}
I solved this by creating new folders with special names using the code below:
DirectoryInfo hdDirectoryInWhichToSearch = new DirectoryInfo(FileDirectory);
FileSystemInfo[] filesAndDirs = hdDirectoryInWhichToSearch.GetFileSystemInfos("*" + FullFileName + "*");
int i = filesAndDirs.Length;
if (i>1)
{
FileName = Filename + "(" + i ")";
}
So what this does is that it will count how many files we have in that folder with the same name, so I have to check if we have more than 1 file, then change it's name to file(1).
Thank you to everyone that tried to help me, much appreciated.

Concatenating folder names to file name and copy file to a folde

My folder structure is as .. temp\2016\09\11\16
In the last folder I have multiple text/json files.
I would like to run a console application that would loop through every folder and rename the files with foldernames concatenated.
So a file abcd.json would become 2016091116_abcd.json
Then copy this file to another folder.
I tried..
using System;
using System.IO;
using System.Collections;
namespace concatdf
{
class Program
{
static void Main(string[] args)
{
string folderPath = "D:\\500GBNP\\Projects\\temp";
DirectoryInfo startDir = new DirectoryInfo(folderPath);
RecurseFileStructure recurseFileStructure = new RecurseFileStructure();
recurseFileStructure.TraverseDirectory(startDir);
}
public class RecurseFileStructure
{
public void TraverseDirectory(DirectoryInfo directoryInfo)
{
var subdirectories = directoryInfo.EnumerateDirectories();
foreach (var subdirectory in subdirectories)
{
TraverseDirectory(subdirectory);
}
var files = directoryInfo.EnumerateFiles();
foreach (var file in files)
{
HandleFile(file);
}
}
void HandleFile(FileInfo file)
{
string destfolderPath = "D:\\500GBNP\\Projects\\temp1\\";
file.CopyTo(destfolderPath+file.Name);
}
}
}
}
With the above code I'm able to traverse and copy all files to target directory but file names do not get concatenated with foldernames.
So a file abcd.json in folder temp\2016\09\11\16 would become 2016091116_abcd.json and all files get copied to temp1 folder.
I would sincerely appreciate if someone could help.
You can append the folder name in each recursion and append the destination filename.
using System;
using System.IO;
using System.Collections;
namespace concatdf
{
class Program
{
static void Main(string[] args)
{
string folderPath = "D:\\500GBNP\\Projects\\temp";
DirectoryInfo startDir = new DirectoryInfo(folderPath);
RecurseFileStructure recurseFileStructure = new RecurseFileStructure();
recurseFileStructure.TraverseDirectory(startDir, string.Empty);
}
public class RecurseFileStructure
{
public void TraverseDirectory(DirectoryInfo directoryInfo, string fileAppend)
{
var subdirectories = directoryInfo.EnumerateDirectories();
foreach (var subdirectory in subdirectories)
{
TraverseDirectory(subdirectory, fileAppend + subdirectory.Name);
}
var files = directoryInfo.EnumerateFiles();
foreach (var file in files)
{
HandleFile(file, fileAppend);
}
}
void HandleFile(FileInfo file, string fileAppend)
{
string destfolderPath = "D:\\500GBNP\\Projects\\temp1\\";
file.CopyTo(destfolderPath + fileAppend +"_"+ file.Name);
}
}
}
}
We just need to make HandleFile a bit more intelligent. Let's take the last 4 folder names and add it to the name..
void HandleFile(FileInfo file)
{
string destfolderPath = "D:\\500GBNP\\Projects\\temp1\\";
var pathBits = file.DirectoryName.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var s = string.Concat(pathBits[^4..]);
file.CopyTo(Path.Combine(destfolderPath, s+'_'+file.Name));
}
This renames the file as it copies (which seemed a more sensible way to go, to me). If you truly want to rename the file before you copy, insert a call to FileInfo.MoveTo() after you copy
Strive to use Path when working with paths, not string concatenation
What about something simpler like this?:
public static void CopyFiles(DirectoryInfo sourceDirectory, DirectoryInfo targetDirectory)
{
// This will provide all files in sourceDirectory and nested directories
foreach (var file in sourceDirectory.EnumerateFiles("*", SearchOption.AllDirectories))
{
// work out what the relative path from sourceDirectory is
// e.g. 2016\09\11\16\abcd.json
string relativePath = Path.GetRelativePath(sourceDirectory.FullName, file.FullName);
// get the directory part and replace the separator with an empty string (this could be
// made more efficient)
string directoryPart = Path.GetDirectoryName(relativePath)
.Replace(Path.DirectorySeparatorChar.ToString(), string.Empty);
// get just the filename
string filePart = Path.GetFileName(relativePath);
// combine the target directory, the directory part, and the filename part
// I've made the assumption that you don't want files in the base directory
// to be called _filename, so we just use filePart when there is no directoryPart
string newFileName = string.IsNullOrEmpty(directoryPart) ? filePart : $"{directoryPart}_{filePart}";
string newFullName = Path.Combine(targetDirectory.FullName, newFileName);
// copy the file to the new location
file.CopyTo(newFullName);
}
}

Exception: Given path format is not supported when the user input C:\Name

I made a small console app to help users copy all content from one directory to another. Here is the code:
using System;
using System.IO;
namespace CopyEdriveContentToLocalFolder
{
class Program
{
public static void Copy(string sourceDirectory, string targetDirectory)
{
DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
CopyAll(diSource, diTarget);
}
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
Directory.CreateDirectory(target.FullName);
// Copy each file into the new directory.
foreach (FileInfo fi in source.GetFiles())
{
Console.WriteLine(#"Copying {0}\{1}", target.FullName, fi.Name);
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir =
target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
static void Main(string[] args)
{
// Specify a name for your Parent folder.
string ParentFolderName;
string ChildFolderName;
Console.WriteLine("Welcome!!\n\nThis program will help you copy all content of your CD/DVD to a new directry \n\n" +
"naming convention must be in this format: ### #####\n\nPress Enter to start...\n");
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
{
Console.Write("Enter Parent folder Name: ");
ParentFolderName = Console.ReadLine();
string text = ParentFolderName;
string contains = " ";
bool b = text.Contains(contains);
if ( b == true)
{
//Set the Child folder name to be same as Parent.
ChildFolderName = ParentFolderName;
string TopLevel = #"" + ParentFolderName;
if (!System.IO.Directory.Exists(TopLevel))
{
string pathString = System.IO.Path.Combine(TopLevel, ChildFolderName);
System.IO.Directory.CreateDirectory(pathString);
}
else
{
Console.WriteLine("The Folder: \"{0}\" already exists.\n\n", TopLevel);
Console.WriteLine("Please Exit the program and re-name the folder .\n\n");
System.Console.WriteLine("Press Enter twice to exit.");
System.Console.ReadKey();
return;
}
// To create a string that specifies the path to a subfolder under your
// top-level folder, add a name for the subfolder to folderName.
//string pathString2 = #"c:\"+ ParentFolderName +"\\" + ChildFolderName;
// You can extend the depth of your path if you want to.
//pathString = System.IO.Path.Combine(pathString, "SubSubFolder");
string sourceDirectory = #"E:\";
string targetDirectory = TopLevel +"\\" + ChildFolderName;
Copy(sourceDirectory, targetDirectory);
string root = TopLevel + "\\" + ChildFolderName + "\\System Volume Information";
//This part will delete the System generated folder.
// If directory does not exist, don't even try
if (Directory.Exists(root))
{
foreach (string files in Directory.GetFiles(root))
{
FileInfo fileInfo = new FileInfo(files);
fileInfo.Delete(); //delete the files first.
}
Directory.Delete(root);
}
// Keep the console window open in debug mode.
System.Console.Write("All Neccery folders have been copied..\n\n" + "Pleace check the target directory.\n\n" +
"Hit Escape twice to exit or Enter to continue.\n");
// System.Console.ReadKey();
}
else
{
//Console.WriteLine("The Folder: \"{0}\" already exists.\n\n", TopLevel);
Console.WriteLine("\nAn Error has occurred due to NOT following the naming convention.\n\n");
Console.WriteLine("Please Make sure the Folder name correct\n\nExit the program and restart.\n\n");
System.Console.WriteLine("Press Enter twice to exit.");
System.Console.ReadKey();
return;
}
}
}
}
}
The Exception I get of wrong format on this line:
DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
if I have the drive hard coded Like #"C:\" it works fine..
string targetDirectory = #"c:\" + ParentFolderName + "\\" + ChildFolderName;
can some one help me please. I need to set the target directory and the source to be completely up to the user.
Thank you
Try this:
string targetDirectory = #"c:\" + ParentFolderName + "\" + ChildFolderName;
or this:
string targetDirectory = "c:\\" + ParentFolderName + "\\" + ChildFolderName;
The issue is that "\" is used as an escape character inside strings. When users input D:\ C# doesn't treat it as a path. Therefor, DirectoryInfo diTarget = new DirectoryInfo(targetDirectory); Throws exception of unrecognized path becuse string targetDirectory has incorrect path value. To solve the issue we do this:
Console.Write("Enter Parent folder Name: ");
path = #"" + Console.ReadLine();
This way users can input any directory. Ex) D:\test
In my code it creates a parent and child directory by saying ChildFolderName = ParentFolderName; The issue now is I can't have a path of D:\testD:\test
To solve this you create another variable that store user input - first 3 char and assign it to childFolderName.
path = #"" + Console.ReadLine();
ParentFolderName = path.Substring(3);
ChildFolderName = ParentFolderName;
And:
string sourceDirectory = #"E:\";
string targetDirectory = path + "\\" + ChildFolderName;

Rename file 20181207_ProdAndPressuresExport.csv to ProdAndPressuresExport.csv

I have the following C# code but having issues renaming the file to what I want (ProdAndPressuresExport.csv). It is renaming the file as ProdAndPressuresExportProdAndPressuresExport.csv and also moving the rename file up 1 folder. I would like for it to stay in its original file path C:\TEMP\CSVFile\ProdAndPressuresExport. Please help.
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
const string DIRECTORY_PATH = #"C:\TEMP\CSVFile\ProdAndPressuresExport";
const string FILE_NAME_TEMPLATE = "*_ProdAndPressuresExport.CSV";
if (Directory.Exists(DIRECTORY_PATH))
{
string[] filePathList = Directory.GetFiles(DIRECTORY_PATH, FILE_NAME_TEMPLATE);
foreach (string filePath in filePathList)
{
if (File.Exists(filePath))
{
string newName = DIRECTORY_PATH + filePath.Split('_')[1];
File.Move(filePath, newName);
}
}
}
}
}
}
Always use Path.Combine to construct paths, rather than string concatenation.
string newName = DIRECTORY_PATH + filePath.Split('_')[1];
Should be
string newName = Path.Combine(DIRECTORY_PATH, filePath.Split('_')[1]);
Otherwise you miss the directory separator character, and your file will end up in the parent folder above your intended folder with an unintentionally concatenated name.

Copy all files in subfolders to another folder using c# with subfolder name

My source path is C:\images\ in which I have hundreds of folders called Album-1, Album-2 etc. I create a target path F:\AllPics. And then I want to move all the files inside my albums to the target path, so that I get all the images in one folder with subfolder names like album-1_img1,album2-img2. How can I do this ?
namespace MassFileMoverConsole
{
class Program
{
string _sourcePath;
string _targetPath;
static void Main(string[] args)
{
Program massMover = new Program();
massMover.MoveThemAll();
}
void MoveThemAll()
{
Console.WriteLine("Enter source path : ");
_sourcePath = Console.ReadLine();
Console.WriteLine("Enter target path : ");
_targetPath = Console.ReadLine();
var subFolderNamesTargetPath = Directory.GetDirectories(_sourcePath);
foreach(var subFolderName in subFolderNamesTargetPath)
{
var subFolder = new DirectoryInfo(subFolderName);
var subFolderFiles = subFolder.GetFiles();
foreach(var subFolderFile in subFolderFiles)
{
var fileNewName = subFolder.Name + "_" + subFolderFile.Name;
subFolderFile.CopyTo(Path.Combine(_targetPath, fileNewName));
}
}
}
}
}
Look at the File & Directory classes.
You can iterate through the files in a directory similar to this (may need tweeks)
There are options to include directories etc.
// Process the list of files found in the directory.
string [] fileEntries = Directory.GetFiles(targetDirectory);
foreach(string fileName in fileEntries)
ProcessFile(fileName);
// Recurse into subdirectories of this directory.
string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach(string subdirectory in subdirectoryEntries)
ProcessDirectory(subdirectory);

Categories

Resources