I am creating multiple files using StreamWriter, I want these files to be created in a specific directory
StreamWriter w = new StreamWriter(File.Create(name + ".txt"));
w.WriteLine(name);
w.Close();
here name is variable that is used as file name and also to be written in that file, but my problem is I want this file to be created in specific directory.
Use Path.Combine
Path.Combine uses the Path.PathSeparator and it checks whether the first path has already a separator at the end so it will not duplicate the separators. Additionally, it checks whether the path elements to combine have invalid chars.
Quoted from this SO post
Also it would be fruitful to check if you name variable contains invalid characters for a filename.
You may first remove invalid characters from name variable using Path.GetInvalidFileNameChars method :
var invalidChars = Path.GetInvalidFileNameChars();
string invalidCharsRemoved = new string(name
.Where(x => !invalidChars.Contains(x))
.ToArray());
Quoted from this SO post
string directory = "c:\\temp";
Instead of
File.Create(name + ".txt")
Use
string filename = invalidCharsRemoved + ".txt"
File.Create(Path.Combine(directory , filename ))
You can include the path too:
string path = "C:\\SomeFolder\\";
File.Create( path + name + ".txt");
Or Use Path.Combine like:
File.Create( Path.Combine(path, name + ".txt") );
FileStream fileStream = null;
StreamWriter writer = null;
try
{
string folderPath = #"D:\SpecificDirecory\";
string path = Path.Combine(folderPath , "fileName.txt");
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
fileStream = new FileStream(#path, FileMode.Create);
writer = new StreamWriter(fileStream);
writer.Write(fileBuilder.ToString());
}
catch (Exception ex)
{
throw ex;
}
finally
{
writer.Close();
fileStream.Close();
}
name contains some thing like #"U:\TDScripts\acchf122_0023"
ok according to the new information from your comment you need actually to get rid of the old path and directory.
You can use the Path.GetFileNameWithoutExtension method to achieve that. After that you can use Path.Combine to create your own path.
Here is an example to demonstrate this:
string myDirectory = #"C:\temp";
string oldPathWithName = #"U:\TDScripts\acchf122_0023";
string onlyFileName = Path.GetFileNameWithoutExtension(oldPathWithName);
string myNewPath = Path.Combine(myDirectory, onlyFileName + ".txt");
Console.WriteLine(myNewPath);
I hope this solves your problem.
You can declare a path for your directory like this :
string path = #"c:\folder\....";
Then with the following command:
File.Create( path + name + ".txt");
You will get what you want
I use the following code to scale and crop all images in a folder.
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
string fileExtension = Path.GetExtension(file);
string filePath = Path.GetDirectoryName(file);
string newFileName = string.Empty;
long fileSize = new FileInfo(file).Length;
if (fileSize > fileSizeLimit)
{
string tempFile = System.IO.Path.GetTempFileName();
File.Copy(file, tempFile, true);
Bitmap sourceImage = (Bitmap)System.Drawing.Image.FromFile(tempFile);
System.Drawing.Image imgPhoto = ScaleCrop(sourceImage, sourceImage.Width / 4, sourceImage.Height / 4, AnchorPosition.Top);
Bitmap bitImage = new Bitmap(imgPhoto);
File.Delete(file);
newFileName = filePath + "\\" + fileNameWithoutExtension + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "_" + CoilWarehouseProcessed + fileExtension;
bitImage.Save(newFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
imgPhoto.Dispose();
bitImage.Dispose();
}
If I run the application locally (in debug mode in VS2010) and point it to a network drive then all images are processed every time.
If I run it from a our local webserver the problem is that the app may process no images, it may process 5, it may process 1, it never does all of the images in a given folder, only ever some of them... then it hangs in the clients browser.
There are no events to view via the event log... the application does not crash or error in anyway... the fact that it will process an image proves it's not a permissions issue.
Any ideas why this is happening?
EDIT: Thanks to wazdev, but I ended up testing a less intrusive (and also don't like dependencies relying on 3rd party software) solution, and it all seems good so far... Basically I changed it so that when it copies the stream to produce a new image 'System.Drawing.Image imgPhoto = ...' to use a using statement to ensure that the 'temp' image is disposed of. I also moved the delete of the original (uncropped / unscaled image) file to be the last operation (In tests it has worked fine, only time will tell once more users come online and concurrency is tested):
string tempFile = System.IO.Path.GetTempFileName();
File.Copy(file, tempFile, true);
Bitmap sourceImage = (Bitmap)System.Drawing.Image.FromFile(tempFile);
System.Drawing.Image imgPhoto = ScaleCrop(sourceImage, sourceImage.Width / 4, sourceImage.Height / 4, AnchorPosition.Top);
Bitmap bitImage;
using (var bmpTemp = new Bitmap(imgPhoto))
{
bitImage = new Bitmap(bmpTemp);
}
newFileName = filePath + "\\" + fileNameWithoutExtension + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "_" + CoilWarehouseProcessed + fileExtension;
bitImage.Save(newFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
imgPhoto.Dispose();
bitImage.Dispose();
File.Delete(file);
EDIT2: It's been live now for a few days and i've tested it every day and it is working well.. Here's all that I did;
Basically inside the ScaleCrop() call there was a GC.Collect and a Wait For Pending Finalisers() call. I removed the wait for pending call and moved the GC.Collect() to after the File.Delete().
I've seen this behaviour in the past when RAM was exhausted resulting in paging to disk. I've found a great deal of success in utilising the ImageResizing.net libraries:
http://imageresizing.net/
I updated my code to use this library and have never looked back.
HTH
(I have no affiliation with imageresizing.net - I'm just a very happy user)
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 am actually working on an application where a blob file is retrieved from my database, converted to the original file and then saved on the desktop. I would like to know if it is possible to check if a file named "xxx" already exists on the desktop and then it shall prompt me for another name. Here is my code:
myData.Read();
FileSize = myData.GetUInt32(myData.GetOrdinal("filesize"));
rawData = new byte[FileSize];
myData.GetBytes(myData.GetOrdinal("file"), 0, rawData, 0, (int)FileSize);
// must change paths
String desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
fs = new FileStream(#desktopPath + "\\" + myData.GetString("title") + myData.GetString("extension"), FileMode.OpenOrCreate, FileAccess.Write);
myFilePath = desktopPath + "\\" + myData.GetString("title") +myData.GetString("extension");
fs.Write(rawData, 0, (int)FileSize);
fs.Close();
You're looking for the File.Exists() function.
I do not see where you use OpenFileDialog in your code, but you should use SaveFileDialog class for saving files and set it's property CheckFileExists=true
I need to generate a unique temporary file with a .csv extension.
What I do right now is
string filepath = System.IO.Path.GetTempFileName().Replace(".tmp", ".csv");
However, this doesn't guarantee that my .csv file will be unique.
I know the chances I ever got a collision are very low (especially if you consider that I don't delete the .tmp files), but this code doesn't looks good to me.
Of course I could manually generate random file names until I eventually find a unique one (which shouldn't be a problem), but I'm curious to know if others have found a nice way to deal with this problem.
Guaranteed to be (statistically) unique:
string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";
(To quote from the wiki article on the probabilty of a collision:
...one's annual risk of being hit by a
meteorite is estimated to be one
chance in 17 billion [19], that means
the probability is about 0.00000000006
(6 × 10−11), equivalent to the odds of
creating a few tens of trillions of
UUIDs in a year and having one
duplicate. In other words, only after
generating 1 billion UUIDs every
second for the next 100 years, the
probability of creating just one
duplicate would be about 50%. The
probability of one duplicate would be
about 50% if every person on earth
owns 600 million UUIDs
EDIT: Please also see JaredPar's comments.
Try this function ...
public static string GetTempFilePathWithExtension(string extension) {
var path = Path.GetTempPath();
var fileName = Path.ChangeExtension(Guid.NewGuid().ToString(), extension);
return Path.Combine(path, fileName);
}
It will return a full path with the extension of your choice.
Note, it's not guaranteed to produce a unique file name since someone else could have technically already created that file. However the chances of someone guessing the next guid produced by your app and creating it is very very low. It's pretty safe to assume this will be unique.
public static string GetTempFileName(string extension)
{
int attempt = 0;
while (true)
{
string fileName = Path.GetRandomFileName();
fileName = Path.ChangeExtension(fileName, extension);
fileName = Path.Combine(Path.GetTempPath(), fileName);
try
{
using (new FileStream(fileName, FileMode.CreateNew)) { }
return fileName;
}
catch (IOException ex)
{
if (++attempt == 10)
throw new IOException("No unique temporary file name is available.", ex);
}
}
}
Note: this works like Path.GetTempFileName. An empty file is created to reserve the file name. It makes 10 attempts, in case of collisions generated by Path.GetRandomFileName();
You can also alternatively use System.CodeDom.Compiler.TempFileCollection.
string tempDirectory = #"c:\\temp";
TempFileCollection coll = new TempFileCollection(tempDirectory, true);
string filename = coll.AddExtension("txt", true);
File.WriteAllText(Path.Combine(tempDirectory,filename),"Hello World");
Here I used a txt extension but you can specify whatever you want. I also set the keep flag to true so that the temp file is kept around after use. Unfortunately, TempFileCollection creates one random file per extension. If you need more temp files, you can create multiple instances of TempFileCollection.
The MSDN documentation for C++'s GetTempFileName discusses your concern and answers it:
GetTempFileName is not able to guarantee that the file name is unique.
Only the lower 16 bits of the uUnique parameter are used. This limits GetTempFileName to a maximum of 65,535 unique file names if the lpPathName and lpPrefixString parameters remain the same.
Due to the algorithm used to generate file names, GetTempFileName can perform poorly when creating a large number of files with the same prefix. In such cases, it is recommended that you construct unique file names based on GUIDs.
Why not checking if the file exists?
string fileName;
do
{
fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";
} while (System.IO.File.Exists(fileName));
You can also do the following
string filepath = Path.ChangeExtension(Path.GetTempFileName(), ".csv");
and this also works as expected
string filepath = Path.ChangeExtension(Path.GetTempPath() + Guid.NewGuid().ToString(), ".csv");
How about:
Path.Combine(Path.GetTempPath(), DateTime.Now.Ticks.ToString() + "_" + Guid.NewGuid().ToString() + ".csv")
It is highly improbable that the computer will generate the same Guid at the same instant of time. The only weakness i see here is the performance impact DateTime.Now.Ticks will add.
In my opinion, most answers proposed here as sub-optimal. The one coming closest is the original one proposed initially by Brann.
A Temp Filename must be
Unique
Conflict-free (not already exist)
Atomic (Creation of Name & File in the same operation)
Hard to guess
Because of these requirements, it is not a godd idea to program such a beast on your own. Smart People writing IO Libraries worry about things like locking (if needed) etc.
Therefore, I see no need to rewrite System.IO.Path.GetTempFileName().
This, even if it looks clumsy, should do the job:
//Note that this already *creates* the file
string filename1 = System.IO.Path.GetTempFileName()
// Rename and move
filename = filename.Replace(".tmp", ".csv");
File.Move(filename1 , filename);
I mixed #Maxence and #Mitch Wheat answers keeping in mind I want the semantic of GetTempFileName method (the fileName is the name of a new file created) adding the extension preferred.
string GetNewTempFile(string extension)
{
if (!extension.StartWith(".")) extension="." + extension;
string fileName;
bool bCollisions = false;
do {
fileName = Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString() + extension);
try
{
using (new FileStream(fileName, FileMode.CreateNew)) { }
bCollisions = false;
}
catch (IOException)
{
bCollisions = true;
}
}
while (bCollisions);
return fileName;
}
This could be handy for you... It's to create a temp. folder and return it as a string in VB.NET.
Easily convertible to C#:
Public Function GetTempDirectory() As String
Dim mpath As String
Do
mpath = System.IO.Path.Combine(System.IO.Path.GetTempPath, System.IO.Path.GetRandomFileName)
Loop While System.IO.Directory.Exists(mpath) Or System.IO.File.Exists(mpath)
System.IO.Directory.CreateDirectory(mpath)
Return mpath
End Function
This seems to work fine for me: it checks for file existance and creates the file to be sure it's a writable location.
Should work fine, you can change it to return directly the FileStream (which is normally what you need for a temp file):
private string GetTempFile(string fileExtension)
{
string temp = System.IO.Path.GetTempPath();
string res = string.Empty;
while (true) {
res = string.Format("{0}.{1}", Guid.NewGuid().ToString(), fileExtension);
res = System.IO.Path.Combine(temp, res);
if (!System.IO.File.Exists(res)) {
try {
System.IO.FileStream s = System.IO.File.Create(res);
s.Close();
break;
}
catch (Exception) {
}
}
}
return res;
} // GetTempFile
Based on answers I found from the internet, I come to my code as following:
public static string GetTemporaryFileName()
{
string tempFilePath = Path.Combine(Path.GetTempPath(), "SnapshotTemp");
Directory.Delete(tempFilePath, true);
Directory.CreateDirectory(tempFilePath);
return Path.Combine(tempFilePath, DateTime.Now.ToString("MMddHHmm") + "-" + Guid.NewGuid().ToString() + ".png");
}
And as C# Cookbook by Jay Hilyard, Stephen Teilhet pointed in Using a Temporary File in Your Application:
you should use a temporary file whenever you need to store
information temporarily for later retrieval.
The one thing you must remember is to delete this temporary file
before the application that created it is terminated.
If it is not deleted, it will remain in the user’s temporary
directory until the user manually deletes it.
This is what I am doing:
string tStamp = String.Format("{0:yyyyMMdd.HHmmss}", DateTime.Now);
string ProcID = Process.GetCurrentProcess().Id.ToString();
string tmpFolder = System.IO.Path.GetTempPath();
string outFile = tmpFolder + ProcID + "_" + tStamp + ".txt";
This is a simple but effective way to generate incremental filenames. It will look in the current directly (you can easily point that somewhere else) and search for files with the base YourApplicationName*.txt (again you can easily change that). It will start at 0000 so that the first file name will be YourApplicationName0000.txt. if for some reason there are file names with junk between (meaning not numbers) the left and right parts, those files will be ignored by virtue of the tryparse call.
public static string CreateNewOutPutFile()
{
const string RemoveLeft = "YourApplicationName";
const string RemoveRight = ".txt";
const string searchString = RemoveLeft + "*" + RemoveRight;
const string numberSpecifier = "0000";
int maxTempNdx = -1;
string fileName;
string [] Files = Directory.GetFiles(Directory.GetCurrentDirectory(), searchString);
foreach( string file in Files)
{
fileName = Path.GetFileName(file);
string stripped = fileName.Remove(fileName.Length - RemoveRight.Length, RemoveRight.Length).Remove(0, RemoveLeft.Length);
if( int.TryParse(stripped,out int current) )
{
if (current > maxTempNdx)
maxTempNdx = current;
}
}
maxTempNdx++;
fileName = RemoveLeft + maxTempNdx.ToString(numberSpecifier) + RemoveRight;
File.CreateText(fileName); // optional
return fileName;
}
Easy Function in C#:
public static string GetTempFileName(string extension = "csv")
{
return Path.ChangeExtension(Path.GetTempFileName(), extension);
}
In this what we can do we can first find the extension of file
which is coming from file and after finding its extension.Then we
can create the temprary name of file and after that we can change
extension by the previous one it will works.
var name = Path.GetTempFileName();
var changename = Path.GetFileName(name);
var fileName = Path.ChangeExtension(changename, fileExtension);
I think you should try this:
string path = Path.GetRandomFileName();
path = Path.Combine(#"c:\temp", path);
path = Path.ChangeExtension(path, ".tmp");
File.Create(path);
It generates a unique filename and creates a file with that file name at a specified location.