C# results FALSE at `File.Exists` even if the file EXISTS - c#

As title says I don't know what's wrong with my code but if (File.Exists) give negative result even if the file is there.
Below is my code
if (File.Exists(ZFileConfig.FileName.Replace(".xml", "_abc.xml")))
Here, ZFileConfig.FileName is E:\\Application\\Application\\bin\\Debug\\resources\\FirstFile.xml
And amazingly ZFileConfig.FileName.Replace(".xml", "_abc.xml") gives me E:\\Application\\Application\\bin\\Debug\\resources\\FirstFile_abc.xml that is what is needed. EVENTHOUGH IF falied to return TRUE.

It looks like your file is actually named abc_RotateFlip.xml.xml.
I can't imagine why any programmer would ever allow hidden file extensions, but your Excel file shows that they are indeed hidden. Turn that off! Choose to know what's going on inside your computer!
You can also use this registry script to change that setting;
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"HideFileExt"=dword:00000000

Please check with FileInfo :
FileInfo fi = new FileInfo(#"_abc.xml");
bool isExists = fi.Exists;
Generally if you are performing a single operation on a file, use the File class. If you are performing multiple operations on the same file, use FileInfo.
The reason to do it this way is because of the security checking done when accessing a file. When you create an instance of FileInfo, the check is only performed once. However, each time you use a static File method the check is performed.

Related

FileVersionInfo.GetVersionInfo alternative

I have an application that checks for updates. To check for updates I need to get the version of the file on the user's computer.
I used this code:
if (File.Exists(dataFile))
{
var verLocal = Version.Parse(FileVersionInfo.GetVersionInfo(dataFile).FileVersion);
if (verSite > verLocal)
{
needToAdd = true;
}
}
Today I found out that the method FileVersionInfo.GetVersionInfo(String) may not get the file version! Here is a description from the help:
If the file did not contain version information, the FileVersionInfo
contains only the name of the file requested.
So that there was no error, I did like this:
if (File.Exists(dataFile))
{
if (Version.TryParse(FileVersionInfo.GetVersionInfo(dataFile).FileVersion, out var verLocal))
{
if (verSite > verLocal)
{
needToAdd = true;
}
}
}
But now there is a problem - if the user this method will never return the version of the file, then the user will never receive updates! So I need a way to get the version of the file that always works.
Are there alternatives to this method in c#?
That Version info metadata really only applies the Executeables or DLL's. It is supposed to be set during compilation. I have not seen it apply (be written) to any word document, image or similar non-executeable file.
A pretty dated approach for archiving, would be the old Archive Bit/Atribute. Just throwing it out there for completeness.
Usually for a "did it change?" check, it is sufficient to just check the file Size and LastUpdated dates of the file for changes. If you pick any backup maker, it will not do more advanced checks then this (plus the archive bit thing as a option). That one of those two values does not change can happen. But both of them is to unlikely to bother with.
The only 100%* reliable way to check for changes is to calculate a files hash-value. But that usually is something you only do during stuff like install verifications, not as a basic backup.
*Technically not even that is 100%. Hash Colissions are a thing, but are realistically impossible if you already check size and change date.

OpenFileDialog & SaveFileDialog Pop-up search with filter in C#

I have openFileDialog and saveFileDialog with filter (only .dvbcfg extention):
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "DVB Configuration File (*.dvbcfg)|*.dvbcfg";
saveFileDialog.DefaultExt = "dvbcfg";
saveFileDialog.AddExtension = true;
It works properly, but when I'm trying to type filename manually it shows files with any extentions w/o filtering and opens/saves them (first - open file, second - save file):
ScreenShot
How to show only files that matches saveFileDialog.Filter?
P.S. I have overwrite function in saveFileDialog.
UPD I have another option - throw an exception when user selected wrong filetype, but I have no idea how to get only file extention from saveFileDialog.FileName string.
At a certain point, you have to "trust" your users. You can steer them towards good ways of working with your program, but at a certain point, you have to recognise that you've put enough simple barriers in their way to prevent accidental misuse1 but you're unlikely to be able to create enough barriers (in these dialogs) to prevent malicious misuse.
The problem is that using wrong file may cause damage to expensive equipment (DVB-3030 Digital Modulator in this case) even if I'm using try/catch to get variables from files (they need to be integers, in try segment I have Convert.ToInteger32) and variable ranges in if/else checks (for example Frequency range should be 10MHz - 90 MHz with 100Hz step). Since program will be used by students, they can purposely try to break it.
And nothing in your current question (or sought answer) would prevent someone from renaming any arbitrary file to have a .dvbcfg extension.
At this point, you "trust" that the user has given you the filename they wish to use. What you need to do next is to validate the contents of the file. If it has a .dvbcfg extension but isn't actually a valid DVB config file, you need to reject it. If it doesn't have a .dvbcfg extension (hey, maybe they're working with an old file system that only allows 8.3 file names :-)) but turns out to have valid content, why be churlish and reject that file?
I would recommend more than just wrapping ToInteger32 calls in try/catch. Go through the file. Ensure it contains exactly what it should and nothing else. Read each parameter value and probably use TryParse on those. Because your code now "expects" to receive invalid inputs. Then validate ranges, etc.
1Which I'd say you've already got.

C# - Compare Two Text Files

Background
I'm developing a simple windows service which monitors certain directories for file creation events and logs these - long story short, to ascertain if a file was copied from directory A to directory B. If a file is not in directory B after X time, an alert will be raised.
The issue with this is I only have the file to go on for information when working out if it has made its way to directory B - I'd assume two files with the same name are the same, but as there are over 60 directory A's and a single directory B - AND the files in any directory A may accidentally be the same as another (by date or sequence) this is not a safe assumption...
Example
Lets say, for example, I store a log that file "E17999_XXX_2111.txt" was created in directory C:\Test. I would store the filename, file path, file creation date, file length and the BOM for this file.
30 seconds later, I detect that the file "E17999_XXX_2111.txt" was created in directory C:\FinalDestination... now I have the task of determining whether;
a) the file is the same one created in C:\Test, therefore I can update the first log as complete and stop worrying about it.
b) the file is not the same and I somehow missed the previous steps - therefore I can ignore this file because it has found its way to the destination dir.
Research
So, in order to determine if the file created in the destination is exactly the same as the one created in the first instance, I've done a bit of research and found the following options:
a) filename compare
b) length compare
c) a creation-date compare
d) byte-for-byte compare
e) hash compare
Problems
a) As I said above, going by Filename alone is too presumptuous.
b) Again, just because the length of the contents of a file is the same, it doesn't necessarily mean the files are actually the same.
c) The problem with this is that a copied file is technically a new file, therefore the creation date changes. I would want to set the first log as complete regardless of the time elapsed between the file appearing in directory A and directory B.
d) Aside from the fact that this method is extremely slow, it appears there's an issue if the second file has somehow changed encoding - for example between ANSII and ASCII, which would cause a byte mis-match for things like ascii quotes
I would like not to assume that just because an ASCII ' has changed to an ANSII ', the file is now different as it is near enough the same.
e) This seems to have the same downfalls as a byte-for-byte compare
EDIT
It appears the actual issue I'm experiencing comes down to the reason for the difference in encoding between directories - I'm not currently able to access the code which deals with this part, so I can't tell why this happens, but I am looking to implement a solution which can compare files regardless of encoding to determine "real" differences (i.e. not those whereby a byte has changed due to encoding)
SOLUTION
I've managed to resolve this now by using the SequenceEqual comparison below after encoding my files to remove any bad data if the initial comparison suggested by #Magnus failed to find a match due to this. Code below:
byte[] bytes1 = Encoding.Convert(Encoding.GetEncoding(1252), Encoding.ASCII, Encoding.GetEncoding(1252).GetBytes(File.ReadAllText(FilePath)));
byte[] bytes2 = Encoding.Convert(Encoding.GetEncoding(1252), Encoding.ASCII, Encoding.GetEncoding(1252).GetBytes(File.ReadAllText(FilePath)));
if (Encoding.ASCII.GetChars(bytes1).SequenceEqual(Encoding.ASCII.GetChars(bytes2)))
{
//matched!
}
Thanks for the help!
You would then have to compare the string content if the files. The StreamReader (which ReadLines uses) should detect the encoding.
var areEquals = System.IO.File.ReadLines("c:\\file1.txt").SequenceEqual(
System.IO.File.ReadLines("c:\\file2.txt"));
Note that ReadLines will not read the complete file into memory.

Quirky Directories

I've got an issue with some directory manipulation.
The problem is I have an archive of data that needs to be add or purge backup data based on a series of constraints. The constraint that is an issue is the archive only needs to keep the backup from the previous week.
So when you chart out the steps you would assume:
Check if directory exist.
Grab the files.
Then purge them.
Then move the following week into the directory.
The problem though is when you try keep the code simple and implementation, you create some code that doesn't feel like it is proper practice.
string[] archiveFiles = Directory.GetFiles(
Archive, #"*.*", SearchOption.TopDirectoryOnly);
foreach(string archive in archiveFiles)
File.Delete(archive);
So if you attempt to grab the files with Directory.GetFiles() and it doesn't return a value, according to the documentation:
Return Value Type: System.String[] An array of the full names
(including paths) for the files in the specified directory that match
the specified search pattern and option, or an empty array if no files
are found.
If it returns a null in the array then that would actually have the loop iterate once, an error. If it returns an array with no elements then it will ignore the loop. The second is what I believe it does, which makes this approach feel incorrect.
The only thing I could do would be to use File.Copy() as it can overwrite files, which would avoid this approach but even that could become suceiptable to the same dilemma of that empty array.
Is that right usage and approach for Directory.GetFiles() or is there a better way?
If it returns a null in the array then that would actually have the
loop iterate once, an error. If it returns an array with no elements
then it will ignore the loop. The second is what I believe it does,
which makes this approach feel incorrect.
If there are no files matching the list will be empty, there won't be nulls (how many nulls should return an empty directory?).
So your delete code will not be executed. Makes sense to me.
If you need to delete old files, then copy the new ones you may want to first move old files somewhere safe, then copy new ones, then to delete old files.
Maybe I didnt understand the problem here, but I don't see any. I hope actual code has some try catches though.

Having trouble saving multiple items to Isolated Storage

I have a noteapp, two pages:
MainPage.xaml — the creation of notes;
NoteList.xaml — a list of notes.
Notes are saved by means of IsolatedStorage, and appear in NoteList.xaml (listbox), but notes with the same name is not stored, how to fix it?
I need to be able to add notes with the same name (but with different content).
Thanks!
Are you using the note name as the file name? If so... don't do that. Save each file with a unique name. There are myriad ways of doing this. You could use a GUID or a timestamp, or you could append a timestamp to the end of the file name. If you were so inclined you could store all of the notes in a single formatted file-- perhaps XML.
What you need is a way to uniquely identify each note without using:
a. The note's name
b. The note's contents
While using a timestamp might make sense for your application right now (since a user probably cannot create two disparate notes simultaneously), using a timestamp to identify each note could lead to problems down the line if you wanted to implement say... a server side component to your application. What happens if in version 23 of your application (which obviously sells millions in the first months), you decide to allow users to collaborate on notes, and a Note is shared between two instances of your app where they happened to be created at the EXACT same time? You'd have problems.
A reasonable solution to finding a unique identifier for each Note in your application is through the use of the Guid.NewGuid method. You should do this when the user decides to "save" the note (or if your app saves the note the moment it's created, or at some set interval to allow for instant "drafts".
Now that we've sufficiently determined a method of uniquely identifying each Note that your application will allow a user to create, we need to think about how that data should be stored.
A great way to do this is through the use of XmlSerializer, or better yet using the third party library Json.Net. But for the sake of simplicity, I recommend doing something a bit easier.
A simpler method (using good ole' plain text) would be the following:
1: {Note.Name}
2: {Guid.ToString()}
3: {Note.Contents}
4: {Some delimiter}
When you are reading the file from IsolatedStorage, you would read through the file line by line, considering each "chunk" of lines between the start of the file and each {Some delimiter} and the end of the file to be the data for one "Note".
Keep in mind there are some restrictions with this format. Mainly, you have to keep the user from having the last part of their note's contents be equal to the {Some delimiter} (which you are free to arbitrarily define btw). To this end, it may be helpful to use a string of characters the user is not likely to enter, such as "##&&ENDOFNOTE&&##" Regardless of how unlikely it is the user will type that in, you need to check to make sure before you save to IsolatedStorage that the end of the Note does not contain this string, because it will break your file format.
If you want a simple solution that works, use the above method. If you want a good solution that's scalable, use JSON or XML and figure out a file format that makes sense to you. I highly encourage you to look into JSON, it's value reaches so much further than this isolated scenario.
I've had a need to write notes to IsolatedStorage. What I did was to them them to a file.IsolatedStorageFile I write date on which the note was written and then note. From the list box i store them to two arrays. Then before exiting the app, write them to a file.
try
{
using (IsolatedStorageFile storagefile = IsolatedStorageFile.GetUserStoreForApplication())
{
if (storagefile.FileExists("NotesFile"))
{
using (IsolatedStorageFileStream fileStream = storagefile.OpenFile("NotesFile", FileMode.Open, FileAccess.ReadWrite))
{
StreamWriter writer = new StreamWriter(fileStream);
for (int i = 0; i < m_noteCount; i++)
{
//writer.Write(m_arrNoteDate[i].ToShortDateString());
writer.Write(m_arrNoteDate[i].ToString("d", CultureInfo.InvariantCulture));
writer.Write(" ");
writer.Write(m_arrNoteString[i]);
writer.WriteLine("~`");
}
writer.Close();
}
}

Categories