1

I'm just starting to learn Java, and for my first challenge I am trying to read the ID3v1 tag from an MP3. I read the last 128 bytes of an MP3 in to a byte array and split it up from there. To check I have found a valid ID3 tag I convert the first 3 bytes from the array in to a string and compare it to "TAG". The problem is the string made up from the bytes never matches the "TAG" string, even though it looks like it should when I run it in the eclipse debugger.

I've pasted the code I'm using below, Can anyone please point out what it is I am doing wrong here?

byte tagBytes[] = {84, 65, 71}; //Normally filed from a file, just here as an example.
String tagHeader = null; //String to hold tag header
tagHeader = Character.toString((char)tagBytes[0]) + 
            Character.toString((char)tagBytes[1]) + 
            Character.toString((char)tagBytes[2]);
if (tagHeader != "TAG"){
    System.out.println("No ID3v1 tag found");
    return null;
}
dimo414
  • 47,227
  • 18
  • 148
  • 244
Ian
  • 13
  • 1
  • 3
  • 1
    [How to compare strings in Java](http://stackoverflow.com/search?q=java+string+compare) – Eran Mar 23 '13 at 21:52

5 Answers5

2

Strings cannot be compared by == as this checks if the literal references in memory are the same. Instead do "TAG".equals(tagHeader) or "TAG".equalsIgnoreCase(tagHeader) to do a case-insensitive comparison.

You can also simplify your string building, like so:

StringBuilder sb = new StringBuilder();
for(int i = 0; i < 3; i++) {
    sb.append((char)tagBytes[i]);
}
tagHeader = sb.toString();

Or even, as @Vulcan suggest, simply:

tagHeader = new String(tagBytes,0,3);

You'll likely want to specify the charset as well, otherwise the bytes may be converted incorrectly. Depending on how your data's encoded, you may want to specify a different charset:

tagHeader = new String(tagBytes,0,3,Charset.forName("UTF-8"));
dimo414
  • 47,227
  • 18
  • 148
  • 244
2

This will turn bytes into a String and properly:

byte tagBytes[] = {84, 65, 71}; 
String s = new String(tagBytes, Charset.forName("US-ASCII"));

Your solution also works. It's your comparison that is the problem. You want:

if (!tagHeader.equals("TAG")) {

In the case of a String, != or == test that the two String are the same instance, not the same value. You need to use the equals() method to compare them by value.

Variants: To select just a portion of the byte array:

String s = new String(tagBytes, 0, 3, Charset.forName("US-ASCII"));

If the entire byte array has been converted to a string, and you want to see if it does not start with "TAG":

if (!tagHeader.startsWith("TAG")) {
Charles Forsythe
  • 1,831
  • 11
  • 12
1

You can convert the bytes to a String if you are sure that they are all ASCII (or if you know the encoding). Then you should compare with equals not != since the later checks if it is not the same instance. In your case it is always a different instance.

    byte tagBytes[] = {84, 65, 71};
    String tagHeader = new String(tagBytes, Charset.forName("US-ASCII"));
    if (!"TAG".equals(tagHeader)){
        System.out.println("No ID3v1 tag found");
        return null;
    }

Or you can avoid creating redundant String objects altogether by just doing this:

    byte tagBytes[] = {84, 65, 71};
    if (!('T' == tagBytes[0] && 'A' == tagBytes[1] && 'G' == tagBytes[2])){
        System.out.println("No ID3v1 tag found");
        return null;
    }
jdb
  • 4,419
  • 21
  • 21
1

in simple way you can do as follows:

public static void main(String[] args) {
    byte tagBytes[] = {84, 65, 71}; //Normally filed from a file, just here fro example.
    String tagHeader = null; //String to hold tag header
    tagHeader = new String(tagBytes);
    if (!tagHeader.equals("TAG")){
        System.out.println("No ID3v1 tag found");
    }
 }
dimo414
  • 47,227
  • 18
  • 148
  • 244
Vishal K
  • 12,976
  • 2
  • 27
  • 38
0

change tagHeader != "TAG" to !tagHeader.equals("TAG")

Currently, you are comparing memory addresses and not the actual values.

I wrote it this way for clarity. For null safe code, you should always use the literal first.

i.e.

"TAG".equals(tagHeader)
Jonathan Henson
  • 8,076
  • 3
  • 28
  • 52