sgnaw(李逍遥) 2006-12-04
电脑里 MP3 歌曲比较多, 想写个程序把它管理起来, 方便查询, 纯属个人兴趣爱好. 先从获取文件信息开始. 原以为 GetFileAttributes 可以帮上忙, 可事情没这么简单, 得知 MP3 文件信息放在最后的 128 bytes 里, 遂用 Win32 API 读一下即可.
MP3 最后 128 bytes 组成如下:
标签 | 类型 | 长度 |
Tag | string | 3 |
Name | string | 30 |
Artist | string | 30 |
Album | string | 30 |
Year | string | 4 |
Comment | string | 30 |
Genre | string | 1 |
// 以下是 stdafx.h 头文件内容
#pragma
once

#define
WIN32_LEAN_AND_MEAN
//
从 Windows 头中排除极少使用的资料

#include
<
stdio.h
>
#include
<
tchar.h
>
#include
<
windows.h
>
// 以下是主源文件信息内容 MP3Info.cpp
/**/
/* ---------------------------------------
MP3Info.cpp -- Get MP3 file info
(C)Wang Guofan 2006-11-28 Shenzhen
--------------------------------------- */
#include
"
stdafx.h
"
#include
<
iostream
>

using
namespace
std;

void
ShowAttributes(DWORD attributes)

...
{
#if defined(_UNICODE)
if (attributes & FILE_ATTRIBUTE_ARCHIVE)
wprintf(_T(" archive "));
if (attributes & FILE_ATTRIBUTE_DIRECTORY)
wprintf(_T(" directory "));
if (attributes & FILE_ATTRIBUTE_HIDDEN)
wprintf(_T(" hidden "));
if (attributes & FILE_ATTRIBUTE_NORMAL)
wprintf(_T(" normal "));
if (attributes & FILE_ATTRIBUTE_READONLY)
wprintf(_T(" read only "));
if (attributes & FILE_ATTRIBUTE_SYSTEM)
wprintf(_T(" system "));
if (attributes & FILE_ATTRIBUTE_TEMPORARY)
wprintf(_T(" temporary "));
#else
if (attributes & FILE_ATTRIBUTE_ARCHIVE)
printf(" archive ");
if (attributes & FILE_ATTRIBUTE_DIRECTORY)
printf(" directory ");
if (attributes & FILE_ATTRIBUTE_HIDDEN)
printf(" hidden ");
if (attributes & FILE_ATTRIBUTE_NORMAL)
printf(" normal ");
if (attributes & FILE_ATTRIBUTE_READONLY)
printf(" read only ");
if (attributes & FILE_ATTRIBUTE_SYSTEM)
printf(" system ");
if (attributes & FILE_ATTRIBUTE_TEMPORARY)
printf(" temporary ");
#endif
}

struct
MP3FileInfo

...
{
TCHAR Tag[4];
TCHAR Name[31];
TCHAR Artist[31];
TCHAR Album[31];
TCHAR Year[5];
TCHAR Comment[31];
TCHAR Genre[2];
}
;


int
main()

...
{
TCHAR filename[MAX_PATH] = _T("C:/Music/Superstar.mp3");
DWORD attributes;
WIN32_FILE_ATTRIBUTE_DATA lpFileInfo;

#if defined(_UNICODE)
wprintf(_T("%s "), filename);
#else
printf("%s ", filename);
#endif

attributes = GetFileAttributes(filename);
ShowAttributes(attributes);
BOOL bfile = GetFileAttributesEx(filename, GetFileExInfoStandard, &lpFileInfo);
if (bfile)

...{
#if defined(_UNICODE)
wprintf(_T("Success ex , file length=%d "), lpFileInfo.nFileSizeLow);
#endif
}
else

...{
#if defined(_UNICODE)
wprintf(_T("Failed "));
#endif
return -1;
}
// Read MP3 files
HANDLE fileHandle = CreateFile(filename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
if (fileHandle == INVALID_HANDLE_VALUE)

...{
#if defined(_UNICODE)
wprintf(_T("CreateFile error %d "), GetLastError());
#endif
return -1;
}
#define MP3_INFO_BUF_SIZE 32
TCHAR buffer[MP3_INFO_BUF_SIZE];
struct MP3FileInfo info;
DWORD nBytesRead = 0, nPos;
BOOL bResult;

nPos = SetFilePointer(fileHandle, lpFileInfo.nFileSizeLow - 128, NULL, FILE_BEGIN);
// Tag
memset(&info, 0, sizeof(MP3FileInfo));
bResult = ReadFile(fileHandle, buffer, 3, &nBytesRead, NULL);
_tcsncpy(info.Tag, buffer, 3);
// Name
memset(buffer, 0, MP3_INFO_BUF_SIZE);
ReadFile(fileHandle, buffer, 30, &nBytesRead, NULL);
_tcsncpy(info.Name, buffer, 30);
// Artist
memset(buffer, 0, MP3_INFO_BUF_SIZE);
ReadFile(fileHandle, buffer, 30, &nBytesRead, NULL);
_tcsncpy(info.Artist, buffer, 30);
// Album
memset(buffer, 0, MP3_INFO_BUF_SIZE);
ReadFile(fileHandle, buffer, 30, &nBytesRead, NULL);
_tcsncpy(info.Album, buffer, 30);
// Year
memset(buffer, 0, MP3_INFO_BUF_SIZE);
ReadFile(fileHandle, buffer, 4, &nBytesRead, NULL);
_tcsncpy(info.Year, buffer, 4);
// Comment
memset(buffer, 0, MP3_INFO_BUF_SIZE);
ReadFile(fileHandle, buffer, 30, &nBytesRead, NULL);
_tcsncpy(info.Comment, buffer, 30);
// Genre
memset(buffer, 0, MP3_INFO_BUF_SIZE);
ReadFile(fileHandle, buffer, 1, &nBytesRead, NULL);
_tcsncpy(info.Genre, buffer, 1);
// output for test
OutputDebugString(info.Artist);
// Close file
CloseHandle(fileHandle);
}
好了, 今天先写到这里, 接下来打算用把读到的这些信息放到 Access 文件里, 以成 MP3 文件信息库.
CSDN sgnaw(李逍遥) 2006-12-04