How to properly use File.Exists in windows application - c#

I have a windows application with an "images" folder. I need to check if an image exists, which it will, during runtime. The below code is what I have but it always returns false.
if ( File.Exists("images/" + item.tool_image) )
{
Image img;
img = Image.FromFile("images/" + item.tool_image);
titem.Image = img;
}
Whats the problem or the proper way to do this.

If the file you're looking for doesn't exist in the working directory of your application, call File.Exists with a fully-qualified path:
if (File.Exists(#"C:\images\" + item.tool_image))
{ ... }
Of course, verify that a file actually exists at that location.
You'll find life easier if you use the tools provided by the Path class:
if (File.Exists(Path.Combine(#"C:\images", item.tool_image)))
{ ... }

The path is wrong try to change it to
string basePath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
string imageFileName = System.IO.Path.Combine(basePath, "Images",item.tool_image);
if ( File.Exists(imageFileName) )
{
Image img;
img = Image.FromFile(imageFileName);
titem.Image = img;
}

How to properly use File.Exists in windows application?
You don't!
It's almost never appropriate to check if a file exists before trying to open. There are other things at work here: permissions, locking, sharing, time.
Instead, the correct way to do this is to try to open the file, whether it exists or not, and then catch the exception if your attempt to open the file fails. You have to be able to handle this exception anyway, even after performing the File.Exists() check. This makes your initial File.Exists() check not only redundant to your code, but wasteful, because it causes an extra trip out to the file system... and there's not much you can do in programming that's slower than going to the file system.

it is looking from the location where the code is currently running, also the '/' is the wrong direction. also, you are defining the path in multiple places, which can lead to problems later.
var path = string.Format(#"c:\somewhere\images\{0}", item.tool_image);
if (File.Exists(path))
{
Image img;
img = Image.FromFile(path);
titem.Image = img;
}
it's up to you to set the variable path , but in all likelihood, in your code example the location you expect isn't being checked.

The way you're calling it, you are looking for a file of whatever is in the string item.tool_image inside the images folder. Note that this images folder is located inside whatever directory contains your executable.
For instance, i just called File.Exists("images/image.jpg") and it worked.

As everyone has mentioned, use the fully qualified path. I also make heavy use of the Path.Combine, so I don't have to worry about missing a slash or two when I'm combining directories. The current executing directory is also useful...
File.Exists(Path.Combine(Environment.CurrentDirectory, "Images", item.tool_image));

Related

C# winforms get nth folders from path

I've got an absolute path available to me. Say: C:/Program/CoreFiles/Folder1/Folder2/File.txt.
I need to copy that file to C:/Program/Projects/ProjectName/ but it needs to keep Folder1/Folder2/File.txt intact. So the end result should be C:/Program/Projects/ProjectName/Folder1/Folder2/File.txt.
My first attempt at solving this was to try and get the relative path between 2 absolute paths. Found Path.GetRelativePath(string, string) which obviously didn't help as it wasn't meant for WinForms. It would mess up anyway as the final result would be C:/Program/Projects/ProjectName/CoreFiles/Folder1/Folder2/File.txt.
The target directory is empty and I don't know the relative path to copy beforehand other than somehow getting that info out of the absolute path. Since File.Copy won't create folders that don't exist yet, I need to create them first. So how do I get the path that leads up to the file from the CoreFiles directory out of the absolute path?
The only working solution I can come up with is using regex to just replace CoreFiles with Projects/ProjectName in the path string and work with that. But that somehow seems the wrong approach.
Since you can't use Path.GetRelativePath. I suggest looking at another answer that describes how to do this yourself.
Like here...
How to get relative path from absolute path
Using the method in that answer, you can do the rest of your task as shown below.
string sourcePath = "C:/Program/CoreFiles/Folder1/Folder2/File.txt";
string sourceRoot = "C:/Program/CoreFiles/";
string destinationRoot = "C:/Program/Projects/ProjectName/";
// Use built-in .NET Path.GetRelativePath if you can. Otherwise use a custom function. Like here https://stackoverflow.com/a/340454/1812944
string relativePath = MakeRelativePath(sourceRoot, sourcePath);
// Combine the paths, and make the directory separators all the same.
string destinationPath = Path.GetFullPath(Path.Combine(destinationRoot, relativePath));
// Create nested folder structure for your files.
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));
// Copy the file over.
File.Copy(sourcePath, destinationPath);

Issue in file access with absolute paths

I've created a .NetCore console application in which am trying to check if a file exists using its absolute path, but am facing issues, I always get a false response even though the file exists. Even though I pass absolute path as parameter to API, it always prefixes the current working directory, so the path gets evaluated as doesn't exists.
I'm running this code on a windows 10 desktop and the application is created using .NetCore 2.1. I've tried various different methods to evaluate the existence of file like FileInfo Class instance and File.Exists static method. They've failed so far. I've diagnosed the issue, but I couldn't find a way to fix it.
using System;
using System.IO;
namespace FileAccess
{
class Program
{
static void Main(string[] args)
{
FileInfo fileInfo = new FileInfo(#"‪D:\ScriptData\test.zip");
Console.WriteLine($"Full Name: {fileInfo.FullName}");
Console.WriteLine($"FileInfo.Exists: {fileInfo.Exists}");
Console.Write($"File.Exists with #: {File.Exists(#"‪D:\ScriptData\test.zip")}")
Console.ReadLine();
}
}
}
The output of the code is:
Full Name: D:\Work\Samples\FileAccess\FileAccess\bin\Debug\netcoreapp2.1\?D:\ScriptData\test.zip
False
False
Even though am passing the absolute path, it prefixes the current working directory to the path I've passed. I've checked the Access to the file, its all fine, still I get false as response for both the cases.
Screenshot of Error
Screenshot of Debug Info
Judging your screen shot and the output, there is an invisible character at the start of the file path. That will cause .NET not to recognize it is an absolute path and automatically it will make it an absolute path itself.
If you use this code, you will notice that the inserted ? causes the problem here:
System.IO.FileInfo fi = new System.IO.FileInfo(#"?D:\some_file.ext");
Which outputs: C:\Users\...\ConsoleApp8\bin\Debug\netcoreapp2.2\?D:\some_file.ext.
Instead of:
System.IO.FileInfo fi = new System.IO.FileInfo(#"D:\some_file.ext");
Which outputs: D:\some_file.ext.
If you put your code in a HEX editor, you will see there is indeed a character before D:.
Thank goodness you cut and paste your original code! I know you did because when I cut and paste your code I can see that you have invisible characters after the open quote and before the D:\.
These two lines look identical but they're not! Cut and paste them if you don't believe me!
Your code:
FileInfo fileInfo = new FileInfo(#"‪D:\ScriptData\test.zip");
Fixed code:
FileInfo fileInfo = new FileInfo(#"D:\ScriptData\test.zip");
Here's what the binary editor shows.
You've got E2 80 AA secretly stuck in your source code file at the beginning of your filename. Which happens to be the UTF-8 representation of the LEFT-TO-RIGHT EMBEDDING character.

"A generic error occurred in GDI+" when attempting to use Image.Save

I am developing an Outlook 2010 Add-In, and am loading an image from a serialized XML file. The image loads fine, and am able to assign it to a pictureBox object on a Winform no problem. The object is saved in
[XmlIgnore]
public Bitmap Image
{
get { return this.templateImage; }
set { this.templateImage = value; }
}
When, I attempt to save the physical file onto the harddisk however, I am doing:
string filePath = Path.Combine(dirPath, item.Id + ".jpg");
try
{
item.Image.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception e)
{
Debug.WriteLine("DEBUG::LoadImages()::Error attempting to create image::" + e.Message);
}
and am getting an A generic error occurred in GDI+. I've checked the write permissions on the folder, and it does have write permissions. I'm unsure what is wrong here. I've also changed the ImageFormat to bmp and png and so forth to see if it was a conversion problem... but it isn't. Would anybody suggest something to try?
Thank you to Simon Whitehead for answering this in the comments. He said, "3) Make sure the file is not in use by anything else (including your code)."
So the problem was that my own code was using the item.Image object, and was preventing GDI+ to call the dispose() method on it. The solution was to copy the object into a new object, then use that object to "Write." The resulting code is as follows:
try
{
using (Bitmap tempImage = new Bitmap(item.Image))
{
tempImage.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);
}
}
catch (Exception e)
{
Debug.WriteLine("DEBUG::LoadImages()::Error attempting to create image::" + e.Message);
}
I too faced same error for code line:
wmImg.Save(BrandImgPath,ImageFormat.Png);
BrandImgPath = "D:/XYZ/fileName;
Found cause:
XYZ folder didn't exist in D: drive. So my code was creating this folder later. One should ensure if that path exist or not.
if (Directory.Exists(#"D:/XYZ")) return;
Hope it will help someone to solve his code mistakes.
1. Make Sure That your destination folder have read/write permission (check it twice!).
2. Using Server.MapPath is better
3. Make Sure you have free space on your destination drive or folder.
4. Most of the times we cant user Memory Streamers On Shared Servers, So we should be make sure that provider allow us to use it.
Hope Microsoft Give Detailed Exception Errors instead of "Generic GDI+ Errror" !!!
Had this issue myself, needed to check that the folder existed, GDI didn't tell me what went wrong, would have been nice.
In my case it was a spelling mistake in the path to the directory where I was saving the image:
if (Directory.Exists(directory_path))
{
image.SaveAs(directory_path + filename);
}
As gaffleck said it would be nice if GDI+ had thrown more informative exception.
I had the same generic exception, but then I gave write permission to the IIS on parallel plesk file manager. if you are on windows server, make sure to give write permission to IIS user which was IIS_IUSR in my server
also make sure that the folder you are trying to save is correct as mentioned in above comments

getting file name and moving it

string fName = Path.GetFileName(tempPaths[z]);
if (!File.Exists(subAch + fName))
{
File.Move(tempPaths[z], subAch + fName);
Console.WriteLine("moved!!! from " + tempPaths[z] + " tooooo ");
}
tempPaths is a list with all the image file paths. e.g. ./images/image4.jpg
subAch is a directory string.
I wish to get the file name of the file then move them to another directory. But with the code above i kept getting error: file is being used by other process.
Is there anyway which get the file name and move them? I have tried fileStream but was confused by it.
Please advice.
Thank you!
Your code should work just fine. You just need to figure out who is locking the files.
I'd put the code inside the if-block in a try-catch block to deal with the locked files.
I will also recommend you to use Path.Combine instead of dir + file.
One thing: you are checking if subAch + tempPaths[z] exists, yet you are copying to a different location; subAch + fName.
File is being used by another process means exactly that. Someone/something is already using the file, so can't move it. You can always catch the error and moving everything else?
I have use a non-ideal way to grab the file name and move the files to another place.
tempPaths.AddRange(Directory.GetFiles(rawStorePath, filter, SearchOption.AllDirectories));
The code above gets all the directories of all the files in the folder set. The outcome with be something like this. tempPaths is a List.
"./images/glass_numbers_5.jpg"
"./images/G.JPG"
"./images/E.JPG"
"./images/F.JPG"
"./images/glass_numbers_0.jpg"
"./images/C.JPG"
"./images/B.JPG"
"./images/A.JPG"
"./images/D.JPG"
"./images/glass_numbers_7.jpg"
then after i use a loop to grab the file names.
for (int i = 0; i < tempPaths.Count; i++)
{
//Getting the original names of the images
int pLength = rawStorePath.Length;
string something = tempPaths[i].Remove(0, pLength);
if (!_tfileName.ContainsKey(tempPaths[i]))
{ _tfileName.Add(tempPaths[i], something); }
}
rawStorePath is the path of the targeted path e.g.: ./images/
tempPath[i] e.g. : ./images/G.JPG
So with the length i remove the letters and get the file name back.
Please advice me for a ideal way to do this if there is any.
Thanks!

File.Copy and WPF

I have a little problem with the File.Copy method in WPF, my code is very simple and I get an exception when I run it,
Could not find a part of the path 'Images\37c31987-52ee-4804-8601-a7b9b4d439fd.png'.
where Images is a relative folder.
Here is my code, as I said simple and the same code works fine in a console application, no problem at all.
string filenamae = System.IO.Path.Combine(images, Guid.NewGuid().ToString() + System.IO.Path.GetExtension(imageFile)); ;
System.IO.File.Copy(imageFile, filenamae);
this.ImageLocation = string.Empty;
So if any can help, thanks.
Does the images folder exist? File.Copy doesn't create it automatically.
Do you know what your current directory is? File open/save boxes can change that. So it's always safer to work with absolute paths.
Do a
Path.GetFullPath(filename)
and see where that points to. Is it the right location?
If you use the absolute instead of the relative path, does it work then?
Before you access a file, you should call System.IO.File.Exists(). It's not clear from your error description if the origin file exists or not before the copy.
If you don't specify an absolute path, your relative path with often be resolved from unexpected places, usually the current working directory of the process. Calling this method may tell you were the process is currently running:
System.IO.Directory.GetCurrentDirectory()
You should never make assumptions about the current working directory of a running process as the user could start your program from anywhere. Even if you think you always control the current working directory, you will be surprised how often you will be wrong.
Do you have a debugger? Why not insert a breakpoint and check the values used at each step?
If the file system says "cannot find file", I wouldn't bother arguing with it...
use \\ for the file path directory if it in local.. if your file exists in network path use \\\\(atfirst).. So that it look for network drive..
Thanks
It is necessary to embed all external files into the executable and change your code to work with these embedded files rather than to expect files on the disk.
To use images or whatever you need files("xml/txt/doc"), you need to set the build action of your file to Embedded Resource, and call the method with the fully qualified name of the file, where the name is assembled like this:
[RootNameSpaceOfTheProject].[NameOfFolderInTheProject].[FileNameWithExtension]
Example:
Call the method:
var b = ResourceOperations.GetResourceAsByteArray("Store.Resources.EmbeddedIcons.toolbox.png");
Now you can write the byte array to a temporary file for example and use this as an image source, or you can build an image from the byte array directly. At least, you've got your data...
and to save this files to a disk we should write a code by #Jon Skeet :
public static void CopyStream(Stream input, Stream output)
{
// Insert null checking here for production
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
then call it:
using (Stream input = assembly.GetManifestResourceStream(resourceName))
using (Stream output = File.Create(path))
{
CopyStream(input, output);
}

Categories

Resources