File operations - c#

I wanted move the file from one folder to another(target) folder.If the same file is already exist in target folder i wants to rename .how to implement in C#.
Thanks in advance
Sekar

System.IO.File.* has everything you need.
System.IO.File.Exists = To check if the file exists.
System.IO.File.Move = To move (or rename a file).

Fundamentally, this is:
string source = ..., dest = ...; // the full paths
if(File.Exists(dest))
{
File.Move(dest, Path.GetTempFileName());
}
File.Move(source, dest);

You'll want to use the System.IO.File class and check for the file's existence ahead of time.
if(File.Exists("myfile.txt"))
File.Move("myfile.txt", "myfile.bak");
File.Move("myotherfile.txt","myfile.txt");

If you prefer a windows-style behavior, so there is the code I'm using for such an operation
public static void FileMove(string src,ref string dest,bool overwrite)
{
if (!File.Exists(src))
throw new ArgumentException("src");
File.SetAttributes(src,FileAttributes.Normal);
string destinationDir = Path.GetDirectoryName(dest);
if (!Directory.Exists(destinationDir))
{
Directory.CreateDirectory(destinationDir);
}
try
{
File.Move(src,dest);
}
catch (IOException)
{
//error # 183 - file already exists
if (Marshal.GetLastWin32Error() != 183)
throw;
if (overwrite)
{
File.SetAttributes(dest,FileAttributes.Normal);
File.Delete(dest);
File.Move(src,dest);
}
else
{
string name = Path.GetFileNameWithoutExtension(dest);
string ext = Path.GetExtension(dest);
int i = 0;
do
{
dest = Path.Combine(destinationDir,name
+ ((int)i++).ToString("_Copy(#);_Copy(#);_Copy")
+ ext);
}
while (File.Exists(dest));
File.Move(src,dest);
}
}
}

Related

C# checking if more files have one of more of these strings

it's me again , your boi...
Stuck with another problem I didn't find anywhere else strangely...
This is the code I possess in order to check if files in a directory and subdirectiories have a certain string. If they do, I'll add a string at the bottom of the file...
I followed for most part the documentation on Microsoft Docs.
public class OFiles
{
public string PathProgetto
{
get;
set;
}
public void Change()
{
try
{
string docPath = PathProject;
var files = from file in Directory.EnumerateFiles(docPath, "*.h", SearchOption.AllDirectories)
from line in File.ReadLines(file)
where line.Contains("String I want")
// where line.Contains("Other String I want")
// where line.Contains("Another String I want")
select new
{
File = file,
Line = line
};
System.Collections.ArrayList arr = new System.Collections.ArrayList();
foreach (var f in files)
{
arr.Add(f.File.ToString());
}
string sNuovaRiga = "This One";
foreach (var s in arr)
{
File.AppendAllText(s.ToString(), "\r\n" + sNuovaRiga);
}
Console.WriteLine($"{files.Count().ToString()} files found and modified.");
}
catch (UnauthorizedAccessException uAEx)
{
Console.WriteLine(uAEx.Message);
}
catch (PathTooLongException pathEx)
{
Console.WriteLine(pathEx.Message);
}
}
}
You'll notice that there are other strings I want my program to check. The problem is that I have no idea how to do it, I only know that the way I did it I cannot do it with another WHERE so I'm asking here. Ask me anything unclear and thanks in advance
I want to close this question, so I'll just answer it.
As #elgonzo suggested, in this particular all I had to do was putting || when I had to choose between the strings.

C# How to get current Powerpoint Presentation File Name?

As you see I have some object in my hand but I couldn't figure out how to get current file name. I am getting _currentSlideName from an xml file and compare to open new slide.
Do you have any suggestion to get current power point presentation file name?
ppt.Application _pptApplication = new ppt.Application();
private void Open(string fileName)
{
_presentation = _pptApplication.Presentations.Open(fileName, MsoTriState.msoTrue, MsoTriState.msoTrue, MsoTriState.msoFalse);
}
private void CheckSlide()
{
if (_oSlideShowView == null)
{
try
{
Open( _settingObj.Path + _currentSlideName);
}
catch (Exception)
{
Open(_settingObj.Path+ "Test.pptx" );
}
}
else if (_currentSlideName != _presentation.Path)
{
try
{
Open( _settingObj.Path + _currentSlideName);
}
catch (Exception)
{
Open(_settingObj.Path+ "Test.pptx" );
}
}
}
Getting the full filename of the open presentation is simply Presentation.FullName. In your case, this would be:
_pptApplication.ActivePresentation.FullName
Note that this only returns the presentation's name if the file is not currently saved. If it is not saved, the presentation's Path is an empty string.
EDIT: The example above returns the full filename. If you want only the name, use the following. Just to clarify that this only makes sense with saved presentations, I've added a check on Path.
if(!_pptApplication.ActivePresentation.Path.Equals("")) {
var name = _pptApplication.ActivePresentation.Name
... do processing...
}
else {
... error ...
}

File Copy failing to create files with same name

I am copying files from one location to another. I encountered an issue where sometimes a file with the same name would try to save and it would break the program. So I added the logic below to add a number to the filename before copying it:
int counter = 0;
try
{
File.Copy(FileToCopy, FileToSave);
}
catch (Exception)
{
string CurrentFileName = FileToSave.Split('\\', '\\')[4];
string CurretFilePrefix = CurrentFileName.Split('.')[0];
string CurrentFileSuffix = CurrentFileName.Split('.')[1];
string UpdatedFileName = CurretFilePrefix + "_" + counter + "." + CurrentFileSuffix;
File.Copy(FileToCopy, UpdatedFileName);
counter++;
}
However, this is now causing a crash saying the file already exists:
When I check the file does not exist:
Why am I getting this exception? How do I save copies of these files?
A good approach to this problem would include (i) a loop; (ii) use of Path expressions; (iii) avoidance of try-catch when you can test if the file exists; (iv) use of a specific Exception for the extremely unlikely case that two threads or processes are trying to do this same copy at the same time and each get past the File.Exists check; (v) avoidance of while-true-forever loops as even the best code can contain mistakes that could cause a spin-wait forever in production code on a server and it's better to instead have an exception that tells you when something has gone wrong.
int counter = 0;
string proposedDest = dest;
while(counter < 5000)
{
if (!File.Exists(proposedDest))
{
try
{
File.Copy(fileToCopy, proposedDest);
break;
}
catch (IOException ex) when ((uint)ex.HResult == 0x80070050)
{
}
}
counter++;
proposedDest = Path.Combine(Path.GetDirectoryName(dest),
Path.GetFileNameWithoutExtension(dest) +
"_" + counter + Path.GetExtension(dest));
}
;
if (counter == 5000)
throw new Exception($"Could not copy file {fileToCopy} too many retries");
[A better approach would also not use hard coded constants littered through the code ;)]
As CurrentFileName is relative, you are trying to save the file in the location of your executable. Check that directory if your file exists.
Also, there are much better ways to find if the file exists, and also to get the filename and extension of a given file.
i.e. you should use the File.Exists method to determine if the file exists, instead of using exceptions for flow control
if (File.Exists(FileToSave))
{
FileToSave = GetNewFileName(FileToSave)
}
try
{
File.Copy(FileToCopy, FileToSave);
}
catch (Exception)
{
//something went really wrong
}
You should also use the Path methods for getting parts of the name, instead of "knowing" to get the fifth part of the filename (Path.GetExtension, Path.GetFileNameWithoutExtension)
private string GetNewFileName(string oldFileName){
var counter = 0;
var extension = Path.GetExtension(oldFileName);
var directory = Path.GetDirectoryName(oldFileName);
var fileName = Path.GetFileNameWithoutExtension(oldFileName);
var newFileName = Path.Combine(directory,
string.Format("{1}_{2}{3}", filename, counter, extension);
while (File.Exists(newFileName)){
counter++;
newFileName = Path.Combine(directory,
string.Format("{1}_{2}{3}", filename, counter, extension);
}
return newFileName;
}
use this instead:
string CurrentFileName = System.IO.Path.GetFileName(FileToSave);
string CurretFilePrefix = System.IO.Path.GetFileNameWithoutExtension(FileToSave);
string CurrentFileSuffix = System.IO.Path.GetExtension(FileToSave);
string UpdatedFileName = CurretFilePrefix + "_" + counter + "." + CurrentFileSuffix;
Then you have
File.Copy(FileToCopy, UpdatedFileName);
Are you sure this shouldn't be
File.Copy(FileToSave, UpdatedFileName); // FileToSave instead of FileToCopy

Cannot create a file when that file already exists when using Directory.Move

I am trying to move the directory from one location to another location on the same drive. I am getting "Cannot create a file when that file already exists" error. Below is my code.
could any one suggest on this?
string sourcedirectory = #"F:\source";
string destinationdirectory = #"F:\destination";
try
{
if (Directory.Exists(sourcedirectory))
{
if (Directory.Exists(destinationdirectory))
{
Directory.Move(sourcedirectory, destinationdirectory);
}
else
{
Directory.CreateDirectory(destinationdirectory);
Directory.Move(sourcedirectory, destinationdirectory);
}
}
}
catch (Exception ex)
{
log(ex.message);
}
As both of the previous answers pointed out, the destination Directory cannot exist. In your code you are creating the Directory if it doesn't exist and then trying to move your directory, the Move Method will create the directory for you. If the Directory already exists you will need to Delete it or Move it.
Something like this:
class Program
{
static void Main(string[] args)
{
string sourcedirectory = #"C:\source";
string destinationdirectory = #"C:\destination";
string backupdirectory = #"C:\Backup";
try
{
if (Directory.Exists(sourcedirectory))
{
if (Directory.Exists(destinationdirectory))
{
//Directory.Delete(destinationdirectory);
Directory.Move(destinationdirectory, backupdirectory + DateTime.Now.ToString("_MMMdd_yyyy_HHmmss"));
Directory.Move(sourcedirectory, destinationdirectory);
}
else
{
Directory.Move(sourcedirectory, destinationdirectory);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
}
from http://msdn.microsoft.com/en-us/library/system.io.directory.move.aspx
"This method throws an IOException if, for example, you try to move c:\mydir to c:\public, and c:\public already exists. You must specify "c:\public\mydir" as the destDirName parameter, provided that "mydir" does not exist under "c:\public", or specify a new directory name such as "c:\newdir"."
You don't need to create Directory first, it will throw IO Exception, if destination directory exists, Move method automatically creates it for you:
string sourcedirectory = #"F:\source";
string destinationdirectory = #"F:\destination";
if (Directory.Exists(sourcedirectory))
{
if (!Directory.Exists(destinationdirectory))
{
Directory.Move(sourcedirectory, destinationdirectory);
}
}
More infomation of Directory.Move:
http://msdn.microsoft.com/en-us/library/system.io.directory.move.aspx
As per MSDN,
This method throws an IOException if, for example, you try to move
c:\mydir to c:\public, and c:\public already exists.
But, in your method, you are creating the destination directory before you move.
So, you need to change your method from
if (Directory.Exists(destinationdirectory))
{
Directory.Move(sourcedirectory, destinationdirectory);
}
else
{
Directory.CreateDirectory(destinationdirectory);
Directory.Move(sourcedirectory, destinationdirectory);
}
to
if (Directory.Exists(destinationdirectory))
{
//delete or rename
}
Directory.Move(sourcedirectory, destinationdirectory);
You can just call
Microsoft.VisualBasic.FileIO.FileSystem.MoveDirectory(source, destination, true);
What it does internally is it creates the target directory if it's not exists and then it iterates over the source directory's files and moves them to the target directory. That way the problem of "Cannot create a file when that file already exists" won't happen.
You'll need to add Microsoft.VisualBasic as a reference.

File or Folder rename to lower case In C# using DirectoryInfo/FileInfo.MoveTo()

I have a program that renames files or folders to lower case names. I have written this code:
private void Replace(string FolderLocation, string lastText, string NewText)
{
if (lastText == "")
{
lastText = " ";
}
if (NewText == "")
{
NewText = " ";
}
DirectoryInfo i = new DirectoryInfo(FolderLocation);
string NewName = "";
if (checkBox2.Checked)
{
if (i.Parent.FullName[i.Parent.FullName.Length - 1].ToString() != "\\") //For parents like E:/
{
NewName = i.Parent.FullName + "\\" + i.Name.Replace(lastText, NewText);
}
else
{
NewName = i.Parent.FullName + i.Name.Replace(lastText, NewText);
}
NewName = NewName.ToLower();
if (NewName != i.FullName)
{
i.MoveTo(NewName);
}
foreach (DirectoryInfo sd in i.GetDirectories())
{
Replace(sd.FullName, lastText, NewText);
}
}
if (checkBox1.Checked)
{
foreach (FileInfo fi in i.GetFiles())
{
NewName = fi.Directory + "\\" + fi.Name.Replace(lastText, NewText);
NewName = NewName.ToLower();
if (NewName != fi.FullName)
{
fi.MoveTo(NewName);
}
}
}
}
But I get the following exception:
"Source and destination path must be different."
How can I solve this issue?
Since Windows is case insensitive, as far as file names are concerned, you will need to rename the file to a temporary name then rename back with lowercase characters.
Although Windows Filesystems store names case-senstivie they behave case-insensitive on name comparison thus your renaming operation won't work...
IF you really need/want to do that you will need to first rename temporarily the file/directory to something different and unique, then rename it "back" to the "lower case name" you want.
For reference see http://msdn.microsoft.com/en-us/library/ee681827%28v=vs.85%29.aspx and http://support.microsoft.com/kb/100108/en-us .
IF you need NTFS to be case-sensitive you can set the dword ObCaseInsensitive under HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\kernel\ to 0 (NOT RECOMMENDED!).
IF you are dealing with NFS then see http://technet.microsoft.com/en-us/library/cc783185%28WS.10%29.aspx .
This works:
File.Move(destinationFilePath, destinationFilePath);
Unfortunately this is a windows issue as it is case insensitive as Oded mentions in the comments. What you would have to do is to rename the folder twice. By moving the folder to a new temporary name then back to the lowercase of the original name.

Categories

Resources