Comparing Binary Values In ColdFusion
I have a MySQL database table in which I'm storing a binary token (ie, a byte array). This binary token is easily passed from ColdFusion to the database. And, the database will happily compare binary values within an executed SQL statement. But, when that binary token is in a ColdFusion context, there's no native way to compare that binary token to another binary value. As such, I wanted to look at two possible ways to compare binary values in ColdFusion.
The traditional way in which I compare binary values in ColdFusion is to first encode them as a string; and, then, compare the string values. When encoding binary values as a string, the binaryEncode()
function supports hex
and base64
. It's important to remember that the equality operator (==
) in ColdFusion is case-insensitive. As such, it's easiest to select hex
as the target encoding since hex
is also case-insensitive:
<cfscript>
// Generate binary values / byte arrays.
a = charsetDecode( "hello world", "utf-8" );
b = charsetDecode( "hello world", "utf-8" );
// C has different character casing.
c = charsetDecode( "HELLO WORLD", "utf-8" );
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
echo( "<h2> Convert to Strings </h2>" );
// CAUTION: In ColdFusion, the equality operator is case-INSENSITIVE. As such, I'm
// using HEX in order to remove character casing as a possible issue. I could have
// also converted to base64 and then used the compare() function.
dump( binaryEncode( a, "hex" ) == binaryEncode( b, "hex" ) );
dump( binaryEncode( a, "hex" ) == binaryEncode( c, "hex" ) );
</cfscript>
In this ColdFusion code, a
and b
hold the same binary value since they're both produced from the same string. c
is different. And, when we run this ColdFusion code, and convert each binary value to a hex
string, we get the following output:
As you can see, a
and b
were found to be equal while a
and c
were found to be different.
Aside: As an experiment, I wanted to try passing the binary values to the
compare()
function. Thecompare()
function works on string inputs; but, it won't "break" when you pass it a binary value. This is because Lucee CFML is casting the binary value to a string behind the scenes. As such, it will compare two binary values. But, I'm not sure if this will always get you the desired outcome—I don't have the necessary grasp on character-encoding to know what caveats and edge-cases to look out for.
While ColdFusion doesn't have a native way to compare binary values, ColdFusion is built on top of Java. As such, it's possible that Java has a native way to do this. And, after some Googling, I found out that it does. In the java.util.Arrays
class, there are static methods for comparing all sorts of array types; including, byte[]
, which is what a binary value in ColdFusion is.
Here's the same comparison from above, but using Arrays.equals()
to compare the two binary values:
<cfscript>
// Generate binary values / byte arrays.
a = charsetDecode( "hello world", "utf-8" );
b = charsetDecode( "hello world", "utf-8" );
// C has different character casing.
c = charsetDecode( "HELLO WORLD", "utf-8" );
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
// In Java, the Arrays utility class contains many utility methods for comparing
// different types of arrays, including byte-arrays (ie, binary values).
Arrays = createObject( "java", "java.util.Arrays" );
echo( "<h2> Use Array Reflection </h2>" );
dump( Arrays.equals( a, b ) );
dump( Arrays.equals( a, c ) );
</cfscript>
And, when we run this ColdFusion code and dip down into the Java layer, we get the following output:
As you can see, a
and b
were found to be equal while a
and c
were found to be different.
Under the hood, the Array.equals()
method is just comparing the lengths of the two byte arrays. And, if they're the same, it then loops over the arrays and compares each corresponding byte element. Knowing this, it'd be fun to try and write a binaryCompare()
function in ColdFusion. But, I'll save that for another day.
Want to use code from this post? Check out the license.
Reader Comments
A few years ago, I also looked at using the
ByteBuffer
class in Java to represent binary values:www.bennadel.com/blog/3156-experimenting-with-bytebuffer-in-coldfusion-for-binary-manipulation.htm
The
ByteBuffer
class also as a way to compare two byte-buffers; which, in turn, means that they offer a way to compare two binary values. But, probably with more overhead. I'm sharing it here for some cross-pollination of ideas.Ben,
Just wanted to take a moment to thank you for all your CFML posts over the years. Many - many - times when we've run into issues and start Googling, lo-and-behold, Ben Nadel had run into the same issue and provided us a solution! It could have been a post from last week or a post from 10 years ago.
Your research, knowledge and willingness to share are very much appreciated.
Thank you!
@Paul,
Thank you so much for the kind words. I freakin' love this ColdFusion stuff 😎 And, it's just gravy that it actually helps other people.
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →