c# file path string comparison case insensitivity - c#

I would like to compare two strings containing file paths in c#.
However, since in ntfs the default is to use case insensitive paths, I would like the string comparison to be case insensitive in the same way.
However I can't seem to find any information on how ntfs actually implements its case insensitivity. What I would like to know is how to perform a case insensitive comparison of strings using the same casing rules that ntfs uses for file paths.

From MSDN:
The string behavior of the file system, registry keys and values, and environment variables is best represented by StringComparison.OrdinalIgnoreCase.
And:
When interpreting file names, cookies, or anything else where a combination such as "å" can appear, ordinal comparisons still offer the most transparent and fitting behavior.
Therefore it's simply:
String.Equals(fileNameA, fileNameB, StringComparison.OrdinalIgnoreCase)
(I always use the static Equals call in case the left operand is null)

While comparison of paths the path's separator direction is also very important. For instance:
bool isEqual = String.Equals("myFolder\myFile.xaml", "myFolder/myFile.xaml", StringComparison.OrdinalIgnoreCase);
isEqual will be false.
Therefore needs to fix paths first:
private string FixPath(string path)
{
return path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
.ToUpperInvariant();
}
Whereas this expression will be true:
bool isEqual = String.Equals(FixPath("myFolder\myFile.xaml"), FixPath("myFolder/myFile.xaml"), StringComparison.OrdinalIgnoreCase);

string path1 = "C:\\TEST";
string path2 = "c:\\test";
if(path1.ToLower() == path2.ToLower())
MessageBox.Show("True");
Do you mean this or did i not get the question?

I would go for
string.Compare(path1, path2, true) == 0
or if you want to specify cultures:
string.Compare(path1, path2, true, CultureInfo.CurrentCulture) == 0
using ToUpper does a useless memory allocation every time you compare something

Related

string.IsNullOrEmpty & string.IsNullOrWhiteSpace return false for empty string

I have run into a curious case where a block of code that is designed to weed out blank strings, periods dashes and the like after a paragraph of text is processed from the MSFT Azure Phrase Breaker. I could use help figuring out how to debug the issue.
The following block of code returns true when given a value of "". Obviously the expectation is the method should return false after the first if statement. Out of 899 phrases to be looked at, only two seem to have this problem. Happens on another machine as well.
public static bool IsSentenceTranslatable(string sentence)
{
string trimmedSentence = sentence.Trim();
if (string.IsNullOrEmpty(trimmedSentence) || string.IsNullOrWhiteSpace(trimmedSentence))
{
return false;
}
switch (trimmedSentence)
{
case " ":
case ".":
case "-":
case "·":
return false;
}
return true;
}
Here is a snapshot of the debugger.
Could it be a bug in Visual Studio or .NET? I tried using the various visualizers, but still couldn't see anything in the box. .NET 4.5 C# 7.3
Try to get the string's byte representation. I suspect that it actually contains some character which is invisible in VS debugger but doesn't count as a whitespace.
See this questions for hints:
Invisible characters - ASCII
Converting string to byte array in C#
UPD: since your Watch window shows that after the call string trimmedSentence = sentence.Trim() you have trimmedSentence.Length == 1, I'd upgrade my suspicion to certainty.
As stated in my comment, in that screenshot you can see that trimmedSentence.Length is 1, therefore it's not empty, and its contents is definitely not a standard space. If the string appears empty, it's because it has one of those so-called invisible characters. To check what your string has, you can directly access that character by doing trimmedSentence[0].
If that character will appear often, you might want to consider doing this:
string trimmedSentence = sentence.Trim().Replace("<this special character>", "");
Alternatively, you can create that replaceable string from the Unicode value by doing Char.ConvertFromUtf32(yourCharCode).ToString(). You cannot use the Replace overload that uses character parameters, as there is no "empty" character, only an empty string. You should be able to get this value while debugging. Or if necessary, by doing (int)trimmedSentence[0].

Cross-platform filepaths comparison

I'm trying to check if two file path strings specify the same path.
We know paths are not case-sensitive in Windows.
Path.GetFullPath(path1).Equals(Path.GetFullPath(path2), StringComparison.CurrentCultureIgnoreCase)
I know it will not work correctly on Linux, cause paths are case-sensitive there. So I'm searching for some indication of platform case-sensitivity for paths. Or for some function like Path.Equals.
In your case, it's probably the easiest (and most reliable) to check if Path.DirectorySeparatorChar is equal to '/' or '\' and if it's the former, call the same method without the "IgnoreCase" part.
In full:
if(Path.DirectorySeparatorChar == '/')
{
Path.GetFullPath(path1).Equals(Path.GetFullPath(path2), StringComparison.CurrentCulture);
}
else
{
Path.GetFullPath(path1).Equals(Path.GetFullPath(path2), StringComparison.CurrentCultureIgnoreCase);
}

How to Compare localized strings in C#

I am doing localization for ASP.NET Web Application, when user enters a localized string "XXXX" and i am comparing that string with a value in my localized resource file.
Example :
if ( txtCalender.Text == Resources.START_NOW)
{
//do something
}
But When i do that even when the two strings(localized strings) are equal, it returns false. ie.
txtCalender.Text ="இப்போது தொடங்க"
Resources.START_NOW="இப்போது தொடங்க"
This is localized for Tamil.
Please help..
Use one of the string.Equals overloads that takes a StringComparison value - this allows you to use the current culture for comparison..
if ( txtCalender.Text.Equals(Resources.START_NOW, StringComparison.CurrentCulture))
{
//do something
}
Or, if you want case insensitive comparison:
if ( txtCalender.Text.Equals(Resources.START_NOW,
StringComparison.CurrentCultureIgnoreCase))
{
//do something
}
I found the answer and it works. Here is the solution,
it was not working when i tried from Chrome browser and it works with Firefox. Actually when i converted both string to char array,
txtCalender.Text Returns 40 characters and Resource.START_NOW returned 46. So i have tried to Normalize the string using Normalize() method
if(txtCalender.Text.Normalize() == Resources.START_NOW.Normalize())
It was interpreting one character as two different characters when i didn't put normalize method.
it has worked fine. Thanks for your answers.
You can compare with InvariantCulture in String.Equals (statis method):
String.Equals("XXX", "XXX", StringComparison.InvariantCulture);
Not sure whether this helps though, could others comment on it? I've never come across your actual error.
Use String.Equals or String.Compare.
There is some performance differences between these two. String.Compare is faster than String.Equal because String.Compare is static method and String.Equals is instance method.
String.Equal returns a boolean. String.Compare returns 0 when the strings equal, but if they're different they return a positive or negative number depending on whether the first string is before (less) or after (greater) the second string. Therefore, use String.Equals when you need to know if they are the same or String.Compare when you need to make a decision based on more than equality.
You probably need to use .Equals
if(txt.Calendar.Text.Equals(Resources.START_NOW))
{ //...
And if case-insensitive comparison is what you're after (often is) use StringComparison.OrdinalIgnoreCase as the second argument to the .Equals call.
If this isn't working - then can I suggest you breakpoint the line and check the actual value of Resources.START_NOW - the only possible reason why this equality comparison would fail is if the two strings really aren't the same. So my guess is that your culture management isn't working properly.

Stringcomparison OrdinalIgnoreCase for true false values

Does this make sense? MyValue can be "true" or "false"
Should it not be Stringcomparison.OrdinalIgnoreCase ?
MyValue.Equals("true", StringComparison.CurrentCultureIgnoreCase))
I would not do that. Just because a string is not equal to "true" does not mean it's equal to "false". This is an easy way to let ugly bugs slip in. I think you should parse the string
bool value;
if(!Boolean.TryParse(MyValue, out value)) {
// it did not parse
}
// it parsed
This is more likely to be correct, and it's more readable. Plus, culture issues just got swept under the rug.
It really depends on your situation and how the rest of your program is crafted. From the docs on OrdinalCompareCase
The StringComparer returned by the OrdinalIgnoreCase property treats the characters in the strings to compare as if they were converted to uppercase using the conventions of the invariant culture, and then performs a simple byte comparison that is independent of language. This is most appropriate when comparing strings that are generated programmatically or when comparing case-insensitive resources such as paths and filenames.
So basically, if the values are culture independent (generated progamatically, etc) use OrdinalIgnoreCase
Bool.Parse
looks better to me.

String Case Sensitivity [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Is there a C# case insensitive equals operator?
string string1 = "aBc"
string string2 = "AbC"
how can I check if string1 is equal to string2 and have it return true, regardless of case sensitivity.
Two approaches:
You can .ToLower() and do string-equality, or you can use this:
string.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase)
Edit: To appease the downvoters, this operation is useful if your data is culturally significant (i.e., you're comparing Scandinavian words and your current locale is set correctly). If this data is culturally agnostic, and you don't care about locales (bad idea, particularly since .NET lives for Unicode), you can do this:
string.Equals(string1, string2, StringComparison.OrdinalIgnoreCase)
You should use the recommendations here MSDN: "Recommendations for String Use" :
DO: Use StringComparison.Ordinal or OrdinalIgnoreCase for comparisons as your safe default for culture-agnostic string matching.
DO: Use StringComparison.Ordinal and OrdinalIgnoreCase comparisons for increased speed.
DO: Use StringComparison.CurrentCulture-based string operations when displaying the output to the user.
DO: Switch current use of string operations based on the invariant culture to use the non-linguistic StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase when the comparison is linguistically irrelevant (symbolic, for example).
DO: Use ToUpperInvariant rather than ToLowerInvariant when normalizing strings for comparison.
DON'T: Use overloads for string operations that don't explicitly or implicitly specify the string comparison mechanism.
DON'T: Use StringComparison.InvariantCulture-based string operations in most cases; one of the few exceptions would be persisting linguistically meaningful but culturally-agnostic data.
I must admit they were an eyeopener for me. Especially the last one.
You can also use string.Compare, adding the third parameter, which is ignoreCase:
if (string.Compare(string1, string2, true) == 0)
{
// string are equal
}
And you could use also the CompareInfo class:
if (CultureInfo.CurrentCulture.CompareInfo.Compare(string1, string2,
CompareOptions.IgnoreCase) == 0)
{
// string are equal
}
string.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);
:D
string.Equals("aBc", "AbC", StringComparison.CurrentCultureIgnoreCase)

Categories

Resources