I'm writing a function which is going to serialize class and save it to file, some classes must be saved in a different folder. I'm using Unity and C#. Here's my code:
public void save<T>(T data, string fileName) where T : class{
if (fileName == "")
Debug.Log ("Empty file path");
FileStream file = null;
try{
if(fileName.IndexOf("/") > 0){
string[] strDirName = fileName.Split(new char[] {'/'});
string dirName = strDirName[0];
if(!Directory.Exists(Application.persistentDataPath + dirName)){
Directory.CreateDirectory(Application.persistentDataPath + "/" + dirName);
}
}
file = File.Create(constructFilePath(fileName));
string a = constructFilePath(fileName);
binFormatter.Serialize(file, data);
Debug.Log ("File saved succesfully" + fileName);
}catch(IOException e){
Debug.Log(e.ToString());
}finally{
if(file != null)
file.Close();
}
}
string constructFilePath(string fileName){
return Path.Combine(Application.persistentDataPath, fileName);
}
I have no idea why it's saving files as folder, this happens since I added this line to construct constructFilePath
if(fileName[0] != "/")
fileName = "/" + fileName;
But without this file it's creating different folder. It's concatenating the Application.persistentDataPath with the folder name and creates the file there
so if my persistentDataPath = C:/Users/User/AppData/LocalLow/DefaultCompany/TestGame and I want to store the file inside this folder in folder a and store file b in it
C:/Users/User/AppData/LocalLow/DefaultCompany/TestGame/a/b
it creates folder with name TestGamea and stores b inside it
C:/Users/User/AppData/LocalLow/DefaultCompany/TestGamea/b
You are evaluating one thing and performing something different here:
if(!Directory.Exists(Application.persistentDataPath + dirName)){
Directory.CreateDirectory(Application.persistentDataPath + "/" + dirName);
}
Change this to:
if(!Directory.Exists(Path.Combine(Application.persistentDataPath, dirName))){
Directory.CreateDirectory(Path.Combine(Application.persistentDataPath, dirName));
}
Like Eric said, use Path.Combine. it will reliably combine path parts and ensure you get the same result every time so you don't have to worry about string manipulation.
Related
I have made a view that takes a file upload and my controller has a http post method that basically saves the path in the db and then saves the file within the app_data dir. However, I want to make sure the file doesnt over write another file. I.e. if another files exists, rename it. I know I could do this in 2 ways, either by ensuring all file names are unique with guid or by renaming the file. I have tried the second approach, but my methodology seems cumbersome. I would appreciate it if anyone can advise on if there is another approach:
here is what I have:
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName); //Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), fileName);
if (System.IO.File.Exists(path))
{
for (int i = 1; true; i++)
{
path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), (fileName + "_" + i));
if (!System.IO.File.Exists(path))
{
break;
}
}
}
file.SaveAs(path);
model.Image = path;
}
First of all, don't check if exists, it does not help you in any way, because a file may get added before your following lines execute. You want to have a Try...Catch block instead. And you need to actually create a file, not just return a path, which did not exist at some point of execution.
Second, separate your logic of creating a file from your MVC, so code like Server.MapPath and model.Image = path; would be somewhere else.
Third, timestamp sounds like the best option here, just make sure you include milliseconds. If not enough you can include partial checksum at the end, whichever approach makes it unique. You still need to have code in place that checks uniqueness, even if it would rarely happen, and just regenerate file name again, maybe wait 50ms, to make sure it will be a different file name.
Try this:
if (file != null && file.ContentLength > 0)
{
var extension = Path.GetExtension(file.FileName)
var fileName = Path.GetFileNameWithoutExtension(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), fileName);
for (int i = 1; System.IO.File.Exists(path); i++)
path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), fileName + "_" + i.ToString() + extension);
file.SaveAs(path);
model.Image = path;
}
Happy to Help you!
hopefully this works for you:
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var fullFileName = fileName + "_" + Date.Now.ToString("yyyyMMdd_hhss")
path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), fullFileName );
file.SaveAs(path);
model.Image = path;
}
I'm trying make a program that extracts a specific zip file everytime the program launches.
this is my code to create the zip file:
//creating the file
ZipFile File = new ZipFile(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\ABCD.zip");
//Adding files
File.AddFile(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\ab.dat", "");
File.AddFile(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\cd.dat", "");
//Save the file
File.Save();
I want to Extract the files ab.dat and cd.dat from ABCD.zip to the .exe file directory automatically.
Thanks for helping.
Taken mostly from the DotNetZip documentation:
private void Extract()
{
//Zip Location
string zipToUnpack = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\ABCD.zip";
// .EXE Directory
string unpackDirectory = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location);
using (ZipFile zip = ZipFile.Read(zipToUnpack))
{
foreach (ZipEntry e in zip)
{
//If filename matches
if (e.FileName == "ab.dat" || e.FileName == "cd.dat")
e.Extract(unpackDirectory, ExtractExistingFileAction.OverwriteSilently);
}
}
}
You can also filter the results using ExtractSelectEntries by selecting the files there:
zip.ExtractSelectedEntries("name = 'ab.dat' OR name = 'cd.dat'", "\", unpackDirectory, ExtractExistingFileAction.OverwriteSilently)
Or selecting all .dat files with a wildcard
zip.ExtractSelectedEntries("name = '*.dat'", "\", unpackDirectory, ExtractExistingFileAction.OverwriteSilently)
Use each ZipEntry's FileName property to see if it has the name you would like to extract.
I have written some code which requires me to save a text file. However, I need to get it to save to my project root so anyone can access it, not just me.
Here's the method in question:
private void saveFileToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
string fileName = Microsoft.VisualBasic.Interaction.InputBox("Please enter a save file name.", "Save Game");
if (fileName.Equals(""))
{
MessageBox.Show("Please enter a valid save file name.");
}
else
{
fileName = String.Concat(fileName, ".gls");
MessageBox.Show("Saving to " + fileName);
System.IO.File.WriteAllText(saveScene.ToString(), AppDomain.CurrentDomain.BaseDirectory + #"\" + fileName);
}
}
catch (Exception f)
{
System.Diagnostics.Debug.Write(f);
}
}
Many people told me that using AppDomain.CurrentDomain.BaseDirectory would contain the dynamic location of where the app was stored. However, when I execute this, nothing happens and no file is created.
Is there another way of doing this, or am I just using it completely wrong?
File.WriteAllText requires two parameters:
The first one is the FileName and the second is the content to write
File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + #"\" + fileName,
saveScene.ToString());
Keep in mind however that writing to the current folder could be problematic if the user running your application has no write permission for the folder. (And in latest OS writing to the Program Files is very limited). If it is possible, change this location to the ones defined in Environment.SpecialFolder enum
I wish also to suggest using the System.IO.Path class when you need to build paths and not a string concatenation where you use the very 'OS specific' constant "\" to separate paths.
In your example I would write
string destPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,fileName);
File.WriteAllText(destPath, saveScene.ToString());
no need for the extra + #"\" just do:
AppDomain.CurrentDomain.BaseDirectory + fileName
and replace the parameters
saveScene.ToString()
and
AppDomain.CurrentDomain.BaseDirectory + fileName
your code should be:
private void saveFileToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
string fileName = Microsoft.VisualBasic.Interaction.InputBox("Please enter a save file name.", "Save Game");
if (fileName.Equals(""))
{
MessageBox.Show("Please enter a valid save file name.");
}
else
{
fileName = String.Concat(fileName, ".gls");
MessageBox.Show("Saving to " + fileName);
System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + fileName, saveScene.ToString());
}
}
catch (Exception f)
{
System.Diagnostics.Debug.Write(f);
}
}
you can read on File.WriteAllText here:
Parameters
path Type: System.String
The file to write to.
contents Type: System.String
The string to write to the file.
Instead of using AppDomain.CurrentDomain.BaseDirectory you can just do it this way:
File.WriteLine("data\\Mytxt.txt", "Success!");
When you don't add anything, the basedirectory is automatically assumed.
I am making a program to distribute to people. Currently I'm using:
bitmap.Save("C:/My OVMK Photos//OpenVMK" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".jpg", ImageFormat.Jpeg);
I want to make it to auto detect their computer file path to desktop so it will save to the folder on the desktop.
I'm looking to use This code:
string filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
filePath =filePath +#"\Error Log\";
string extension = ".log";
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
How would I implement that?
I'm assuming that it's not working for some reason. You need to:
Make sure that you already have an "Error Log" folder on the desktop
Use Path.Combine to combine filepath with "Error Log", rather than concatenation
You have everything in place. Just save the bitmap to the filePath that you created instead of
"C:/My OVMK Photos//OpenVMK"
bitmap.Save(filePath + DateTime.Now.ToString("yyyyMMddHHmmss") + ".jpg", ImageFormat.Jpeg);
Use a function like this
void SaveToDesktop(Bitmap bitmap)
{
string filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
filepath = Path.Combine(filePath,"Error Log");
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
filepath = Path.Combine(filepath, DateTime.Now.ToString("image_yyyyMMddHHmmss") + ".jpg");
bitmap.Save(filepath, ImageFormat.Jpeg);
}
then instead of using bitmap.Save
do SaveToDesktop(bitmap);
I need to copy a file to another path, leaving the original where it is.
I also want to be able to rename the file.
Will FileInfo's CopyTo method work?
Have a look at File.Copy()
Using File.Copy you can specify the new file name as part of the destination string.
So something like
File.Copy(#"c:\test.txt", #"c:\test\foo.txt");
See also How to: Copy, Delete, and Move Files and Folders (C# Programming Guide)
Yes. It will work: FileInfo.CopyTo Method
Use this method to allow or prevent overwriting of an existing file. Use the CopyTo method to prevent overwriting of an existing file by default.
All other responses are correct, but since you asked for FileInfo, here's a sample:
FileInfo fi = new FileInfo(#"c:\yourfile.ext");
fi.CopyTo(#"d:\anotherfile.ext", true); // existing file will be overwritten
I tried to copy an xml file from one location to another. Here is my code:
public void SaveStockInfoToAnotherFile()
{
string sourcePath = #"C:\inetpub\wwwroot";
string destinationPath = #"G:\ProjectBO\ForFutureAnalysis";
string sourceFileName = "startingStock.xml";
string destinationFileName = DateTime.Now.ToString("yyyyMMddhhmmss") + ".xml"; // Don't mind this. I did this because I needed to name the copied files with respect to time.
string sourceFile = System.IO.Path.Combine(sourcePath, sourceFileName);
string destinationFile = System.IO.Path.Combine(destinationPath, destinationFileName);
if (!System.IO.Directory.Exists(destinationPath))
{
System.IO.Directory.CreateDirectory(destinationPath);
}
System.IO.File.Copy(sourceFile, destinationFile, true);
}
Then I called this function inside a timer_elapsed function of certain interval which I think you don't need to see. It worked. Hope this helps.
You could also use File.Copy to copy and File.Move to rename it afterwords.
// Copy the file (specify true or false to overwrite or not overwrite the destination file if it exists.
File.Copy(mySourceFileAndPath, myDestinationFileAndPath, [true | false]);
// EDIT: as "astander" notes correctly, this step is not necessary, as File.Copy can rename already...
// However, this code could be adapted to rename the original file after copying
// Rename the file if the destination file doesn't exist. Throw exception otherwise
//if (!File.Exists(myRenamedDestinationFileAndPath))
// File.Move(myDestinationFileAndPath, myRenamedDestinationFileAndPath);
//else
// throw new IOException("Failed to rename file after copying, because destination file exists!");
EDIT
Commented out the "rename" code, because File.Copy can already copy and rename in one step, as astander noted correctly in the comments.
However, the rename code could be adapted if the OP desired to rename the source file after it has been copied to a new location.
string directoryPath = Path.GetDirectoryName(destinationFileName);
// If directory doesn't exist create one
if (!Directory.Exists(directoryPath))
{
DirectoryInfo di = Directory.CreateDirectory(directoryPath);
}
File.Copy(sourceFileName, destinationFileName);
File::Copy will copy the file to the destination folder and File::Move can both move and rename a file.
This is what I did to move a test file from the downloads to the desktop.
I hope its useful.
private void button1_Click(object sender, EventArgs e)//Copy files to the desktop
{
string sourcePath = #"C:\Users\UsreName\Downloads";
string targetPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string[] shortcuts = {
"FileCopyTest.txt"};
try
{
listbox1.Items.Add("Starting: Copy shortcuts to dektop.");
for (int i = 0; i < shortcuts.Length; i++)
{
if (shortcuts[i]!= null)
{
File.Copy(Path.Combine(sourcePath, shortcuts[i]), Path.Combine(targetPath, shortcuts[i]), true);
listbox1.Items.Add(shortcuts[i] + " was moved to desktop!");
}
else
{
listbox1.Items.Add("Shortcut " + shortcuts[i] + " Not found!");
}
}
}
catch (Exception ex)
{
listbox1.Items.Add("Unable to Copy file. Error : " + ex);
}
}
TO Copy The Folder I Use Two Text Box To Know The Place Of Folder And Anther Text Box To Know What The Folder To Copy It And This Is The Code
MessageBox.Show("The File is Create in The Place Of The Programe If you Don't Write The Place Of copy And You write Only Name Of Folder");// It Is To Help The User TO Know
if (Fromtb.Text=="")
{
MessageBox.Show("Ples You Should Write All Text Box");
Fromtb.Select();
return;
}
else if (Nametb.Text == "")
{
MessageBox.Show("Ples You Should Write The Third Text Box");
Nametb.Select();
return;
}
else if (Totb.Text == "")
{
MessageBox.Show("Ples You Should Write The Second Text Box");
Totb.Select();
return;
}
string fileName = Nametb.Text;
string sourcePath = #"" + Fromtb.Text;
string targetPath = #"" + Totb.Text;
string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
string destFile = System.IO.Path.Combine(targetPath, fileName);
if (!System.IO.Directory.Exists(targetPath))
{
System.IO.Directory.CreateDirectory(targetPath);
//when The User Write The New Folder It Will Create
MessageBox.Show("The File is Create in "+" "+Totb.Text);
}
System.IO.File.Copy(sourceFile, destFile, true);
if (System.IO.Directory.Exists(sourcePath))
{
string[] files = System.IO.Directory.GetFiles(sourcePath);
foreach (string s in files)
{
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(targetPath, fileName);
System.IO.File.Copy(s, destFile, true);
}
MessageBox.Show("The File is copy To " + Totb.Text);
}
Old Question,but I would like to add complete Console Application example, considering you have files and proper permissions for the given folder, here is the code
class Program
{
static void Main(string[] args)
{
//path of file
string pathToOriginalFile = #"E:\C-sharp-IO\test.txt";
//duplicate file path
string PathForDuplicateFile = #"E:\C-sharp-IO\testDuplicate.txt";
//provide source and destination file paths
File.Copy(pathToOriginalFile, PathForDuplicateFile);
Console.ReadKey();
}
}
Source: File I/O in C# (Read, Write, Delete, Copy file using C#)
File.Move(#"c:\filename", #"c:\filenamet\filename.txt");