长了点……不过还是看看!  ^&^ID3 tags
The TAG is used to describe the MPEG Audio file. It contains information about artist, title, album, publishing year and genre. There is some extra space for comments. And in some tags you can also find the track number.
It is exactly 128 bytes long and always is located at very end of the audio data. You can get it by reading the last 128 bytes of the MPEG audio file.AAABBBBB BBBBBBBB BBBBBBBB BBBBBBBB
BCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCD
DDDDDDDD DDDDDDDD DDDDDDDD DDDDDEEE
EFFFFFFF FFFFFFFF FFFFFFFF FFFFFFGH
  Sign Length
(bytes) Description 
A 3 Tag identification. Must contain "TAG" if tag exists and is correct. 
B 30 Title 
C 30 Artist 
D 30 Album 
E 4 Year 
F 30 Comment (if ID3v1.1 then it's only 28 followed by a '\0') 
G 1 In most cases this is a part of the 30 character Comment-string, but in some files(ID3v1.1), this number represents the track number. 
H 1 Genre 
C++ source-code
The ID3 tag is the most supported tag in the mp3 file in terms of read/write access. This part isn't only readable it's writeable also!! Well, lets head over to the header file. #ifndef CID3TAG_H
#define CID3TAG_H#include <windows.h>/* ----------------------------------------------------------
   CId3Tag class is used to retrieve and to save(!!) an
   information from an ID3v1.0/v1.1 tag and load thatinto
   a usable structure.   This code will be well commented, so that everyone can
   understand, as it's made for the public and not for
   private use, although private use is allowed. :)   all functions specified both in the header and .cpp file
   will have explanations in both locations.   everything here by: Gustav "Grim Reaper" Munkby
                       http://home.swipnet.se/grd/
                       [email protected]
   ---------------------------------------------------------- */
class CId3Tag {    public:    // this function takes 128 chars and if it's
    // an ID3 tag structure it'll be read into
    // this usable structure
    BOOL loadTag( char inputtag[128] );    // this function saves the current settings
    // into the 128 chars sent to the function
    BOOL saveTag( char output[128] );    // function to set & get Title info [ char[30] ]
    void  getTitle(char* input);
    void  setTitle(char* input);    // function to set & get Artist info [ char[30] ]
    void  getArtist(char* input);
    void  setArtist(char* input);    // function to set & get Album info [ char[30] ]
    void  getAlbum(char* input);
    void  setAlbum(char* input);    // function to set & get Comment info [ char[30]/char[28] ]
    void  getComment(char* input);
    void  setComment(char* input);    // function to set & get the string for
    // the genre info.
    void  genreString(char* input, BOOL get);    // functions to set & get the integer 
    // for the genre info
    int   getGenreIndex() { return (int)genre; };
    void  setGenreIndex(int input);    // functions to set & get the year info [1000->3000]
    int   getYear() { return year; };
    void  setYear(int input);    // functions to set & get the track number [1->255]
    int  getTrackNumber() { return (version==1.1)?trackNumber:-1; };
    void setTrackNumber(int input); 
    
    // function to get the version [1.0/1.1]
    float getVersion() { return version; };    private:    char  title  [31],
          artist [31],
          album  [31],
          comment[31];
    int   year;
    int   trackNumber; //ID3v1.1 specific
    float version;    UCHAR genre;};#endifThat's quite a large amount of code, but wait until you see the .cpp file :)#include "CId3Tag.h"
#include <stdio.h>
/* ----------------------------------------------------------
   CId3Tag class is used to retrieve and to save(!!) an
   information from an ID3v1.0/v1.1 tag and load thatinto
   a usable structure.   This code will be well commented, so that everyone can
   understand, as it's made for the public and not for
   private use, although private use is allowed. :)   all functions specified both in the header and .cpp file
   will have explanations in both locations.   everything here by: Gustav "Grim Reaper" Munkby
                       http://home.swipnet.se/grd/
                       [email protected]
   ---------------------------------------------------------- */// this function is specially designed to take
// care of ID3 tags generated with spaces instead
// of null characters as they are supposed to.
void gStrCpy( char* dst, char* src, int length ) {    // what this does is that it searches for a
    // the first non-space or non-null from the
    // right side (and while doing so replacing)
    // " " with '\0'
    for ( int i = (length-1); i >= 0; i-- ) {        if ( (src[i] == 0x20) || (src[i] == '\0') ) dst[i] = '\0';        else break;
            
    }    // this should copy the remaining part straight over
    memcpy(dst, src, (i+1) );
    dst[length] = '\0';}// this function loads 128 chars and
// turn them into a readable structure
BOOL CId3Tag::loadTag( char inputtag[128] ) {    // in the ID3 tag the first 3 bytes are always TAG
    // so that you can separate a TAGed file from a
    // non TAGed one
    if ( memcmp(inputtag, "TAG", 3) ) return false;    // using special string-copying routine
    // to copy the title string
    gStrCpy( title, inputtag+3, 30 );    // using special string-copying routine
    // to copy the artist string
    gStrCpy( artist, inputtag+33, 30 );    // using special string-copying routine
    // to copy the title string
    gStrCpy( album, inputtag+63, 30 );    // because I store year as an integer
    // and the ID3 tag stores it as a string
    // the year will be handled like this:
    char yearstr[4];
    memcpy( yearstr, inputtag+93, 4);
    year = atoi( yearstr );    // now lets detect whether it's version 1.1
    // or 1.0 (if there is tracknumber info or not)
    // if there is some tracknumber info, then it's in
    // the last char of the comment field, and the
    // one before is null
    if ( (inputtag[125]=='\0' ) && (inputtag[126] != '\0') ) {        version = (float)1.1;
        trackNumber = (int)inputtag[126];        // using special string-copying routine
        // to copy the comment string
        gStrCpy(comment, inputtag+97, 28);    } else {
        
        version = (float)1.0;        // using special string-copying routine
        // to copy the title string
        gStrCpy(comment, inputtag+97, 30);    }    genre = inputtag[127];    return true;}BOOL CId3Tag::saveTag (char outputtag[128]) {    
    // begin with clearing the values of the memory
    // containing the "id3string", mainly to ensure
    // that any "un-set" chars is 0 and nothing else
    memset(outputtag,0,128);    // first of all, we add the identifier
    memcpy(outputtag, "TAG", 3);    // to append the rest of the strings I'll
    // use my own function gStrCpy specified above    // apending title
    gStrCpy(outputtag+3, title, 30 );
    
    // inserting the artist information
    gStrCpy(outputtag+33, artist, 30 );
    
    // add the album name to the id3 tag
    gStrCpy(outputtag+63, album, 30 );    // this ones got to be 4 chars long, in my code, just to make the code simpler
    // and exactly who's got music recorded older than 1000 years? (and who's got
    // music recorded from the 101th century?)    // turn integer into string
    char yearstring[4];
    _itoa(year,yearstring,10);    // add the four chars describing the year
    memcpy(outputtag + 93, yearstring, 4 );    // add 30 chars of comment
    gStrCpy(outputtag+97, comment, 30 );
    
    if (version==(float)1.1) { // if version equals 1.1 we've got a tracknumber        // make sure comment[28] == '\0' & then set comment[29] to trackNumber
        outputtag[125] = '\0';
        outputtag[126] = (UCHAR)(UINT)trackNumber;    }    // set the char desiding the genre
    outputtag[127] = genre;    return true;
}
// get title info
void CId3Tag::getTitle(char* input) {    strcpy (input, title);}
// set title info
void CId3Tag::setTitle(char* input) {    strcpy (title, input);}// get artist info
void CId3Tag::getArtist(char* input) {    strcpy (input, artist);}
// set artist info
void CId3Tag::setArtist(char* input) {    strcpy (artist, input);}// get album info
void CId3Tag::getAlbum(char* input) {    strcpy (input, album);}
// set album info
void CId3Tag::setAlbum(char* input) {    strcpy (album, input);}// get comment info
void CId3Tag::getComment(char* input) {    strcpy (input, comment);}
// set comment info
void CId3Tag::setComment(char* input) {    strcpy (comment, input);}// get/set genre string
// to use this function to get info
// specify true as second parameter
// if you want to set then make it false
void CId3Tag::genreString(char* input, BOOL get) {    // this table of constant strings will be used in all cases..
    char* genre_table[126] = {"Blues","Classic Rock","Country","Dance","Disco","Funk","Grunge",
                              "Hip-Hop","Jazz","Metal","New Age","Oldies","Other","Pop","R&B",
                              "Rap","Reggae","Rock","Techno","Industrial","Alternative","Ska",
                              "Death Metal","Pranks","Soundtrack","Euro-Techno","Ambient",
                              "Trip-Hop","Vocal","Jazz+Funk","Fusion","Trance","Classical",
                              "Instrumental","Acid","House","Game","Sound Clip","Gospel",
                              "Noise","AlternRock","Bass","Soul","Punk","Space","Meditative",
                              "Instrumental Pop","Instrumental Rock","Ethnic","Gothic",
                              "Darkwave","Techno-Industrial","Electronic","Pop-Folk",
                              "Eurodance","Dream","Southern Rock","Comedy","Cult","Gangsta",
                              "Top 40","Christian Rap","Pop/Funk","Jungle","Native American",
                              "Cabaret","New Wave","Psychadelic","Rave","Showtunes","Trailer",
                              "Lo-Fi","Tribal","Acid Punk","Acid Jazz","Polka","Retro",
                              "Musical","Rock & Roll","Hard Rock","Folk","Folk-Rock",
                              "National Folk","Swing","Fast Fusion","Bebob","Latin","Revival",
                              "Celtic","Bluegrass","Avantgarde","Gothic Rock","Progressive Rock",
                              "Psychedelic Rock","Symphonic Rock","Slow Rock","Big Band",
                              "Chorus","Easy Listening","Acoustic","Humour","Speech","Chanson",
                              "Opera","Chamber Music","Sonata","Symphony","Booty Bass","Primus",
                              "Porn Groove","Satire","Slow Jam","Club","Tango","Samba",
                              "Folklore","Ballad","Power Ballad","Rhythmic Soul","Freestyle",
                              "Duet","Punk Rock","Drum Solo","Acapella","Euro-House","Dance Hall"
                             };    if (get) {        // if get operation then check whether it's supported
        // and if it is set it according table above
        if (genre>=126)    strcpy(input, "not supported");
        else               strcpy (input, table[genre]);    }
    else {        for (int i=0; i<126; i++) {            // search table for match
            if ( !_stricmp(input, table[i]) ) {                genre=(UCHAR)(UINT)i;
                return; // end function            }        }
        // you'll only get here if no match is found        // alert error message
        char buf[200];
        sprintf(buf,"the genre %s couldn't be found\ndo you want to set it to \"not supported\"?",input);
        int ret = MessageBox(0,buf, "MP3Info Example",MB_YESNO | MB_ICONQUESTION);        // from the error message you've got two possibilities
        // 1/ answer no and the genre will remain unchanged
        // 2/ answer yes and the genre will be altered to "not supported"
        // set genre to something unspecified (in this case 255)
        if (ret==IDYES) genre = 255;    }}// set the genre index info
void CId3Tag::setGenreIndex(int input) {    genre = (UCHAR)(input%256);}// set the track number info
// to remove a track number execute this
// function
void CId3Tag::setTrackNumber(int input) {    // no number avaliable
    if (input==-1) { 
        
        version = (float)1.0;
        trackNumber = -1;    } else if (input<0 || input>255) {        // an invalid tracknumber was specified
        MessageBox(0,"The tracknumber, should be between 0 and 255", "MP3Info Example", MB_OK);    } else { // no errors, set the tracknumber        version = (float)1.1;
        trackNumber = input;    }}// set year info
void CId3Tag::setYear(int input) {    // check whether input is out of range
    if (input<1000 || input>3000) {
         
        char mybuf[200];
        strcpy(mybuf, "The way the year is stored, it's best\n");
        strcat(mybuf, "to user a year between 1000 and 3000,\n");
        strcat(mybuf, "personally  I don't think anything else is needed\n\n");        sprintf(mybuf, "%s%d seams like a stupid number",mybuf, input);        MessageBox(0, mybuf, "MP3Info Example", MB_OK|MB_ICONEXCLAMATION);    } else { // everything alright, just set it        year = input;    }}that's all code for the ID3(v1) tags, I hope you satisfy with this, because I don't really know what more to add...Additional information not yet documented
The only part which is missed out here is the information about the new generation of ID3 tags, ID3v2 tags, which are completely different from the ID3 tags presented here. For now information about ID3v2 tags is abaliable here.