64,646
社区成员
发帖
与我相关
我的任务
分享
#include "Lyric.h"
#include <iostream>
using namespace std;
BOOL StrToLong(const WCHAR* pStr, int NumberOfChars, LONG* pTime);
int _tmain()
{
const WCHAR* const pFileName = L"E:\\黄磊 - 我想我是海.lrc";
HANDLE hFile = ::CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr, OPEN_EXISTING, 0, nullptr);
if (INVALID_HANDLE_VALUE == hFile)
{
cout << "打开歌词文件失败" << endl;
exit(1);
}
else
{
cout << "打开文件: " << "E:\\黄磊 - 我想我是海.lrc" << endl << endl;
::CloseHandle(hFile);
hFile = nullptr;
}
CLyric Lyric;
bool Result = Lyric.LoadLyric(pFileName, 0);
if (Result)
{
cout << "载入歌词成功" << endl;
}
else
{
cout << "载入歌词失败" << endl;
}
return 0;
}
#include "Lyric.h"
#include <iostream>
using namespace std;
BOOL StrToLong(const WCHAR* pStr, int NumberOfElements, LONG* pTime);
WCHAR CLyric::s_FileBuffer[] = {};
CLyric::CLyric() :
m_fValid(false),
m_CharNumber(0)
{
memset(m_FileName, 0, sizeof(m_FileName));
}
CLyric::~CLyric()
{
m_fValid = false;
}
bool CLyric::LoadLyric(PCWSTR pFileName, LONG /*CurrentTime*/)
{
if (!LoadFileToBuffer(pFileName))
{
return false;
}
int X = 0;
int Y = 0;
static bool fFirstLeft = true;
static bool fFirstRight = true;
bool fShouldAnalysis = false; // 应该解析时间吗?
bool fTextShouldAnalysis = false; // 应该解析文本吗?
int k = 0;
// 0 表示还没有遇到过 [ 或 ]
// 1 表示上一个括号是 [
// 2 表示上一个括号是 ]
for (int i = 0; i < m_CharNumber; i++)
{
switch (s_FileBuffer[i])
{
case L'[':
if (fFirstLeft)
{
fFirstLeft = false;
X = i;
k = 1;
fTextShouldAnalysis = false;
}
else if (k == 1) // 第 n>=2 次遇到 [ ,且上一个括号是 [
{
fTextShouldAnalysis = false;
}
else // 第 n>=2 次 [ ,且上一个括号是 ]
{
X = i;
k = 1;
fTextShouldAnalysis = true;
}
break;
case L']':
if (fFirstRight)
{
if (k == 1)
{
fFirstRight = false;
Y = i;
k = 2;
fShouldAnalysis = true;
}
}
else if (k == 1) // 第 n>=2 次遇到 ] ,且上一个括号是 [
{
Y = i;
k = 2;
fShouldAnalysis = true;
}
else // 第 n>=2 次遇到 ] ,且上一个括号是 ]
{
fShouldAnalysis = false;
}
// 提取时间标签:
if (fShouldAnalysis)
{
LONG Time = 0;
if (StrToLong(s_FileBuffer + X + 1, Y - X - 1, &Time))
{
cout << Time << endl;
}
else
{
cout << "转换失败" << endl;
}
}
break;
default:
break;
}
}
return true;
}
bool CLyric::LoadFileToBuffer(PCWSTR pFileName)
{
HANDLE hFile = ::CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr, OPEN_EXISTING, 0, nullptr);
if (INVALID_HANDLE_VALUE == hFile)
{
return false;
}
LARGE_INTEGER liFileSize = {};
if (!::GetFileSizeEx(hFile, &liFileSize))
{
::CloseHandle(hFile);
return false;
}
if (liFileSize.QuadPart > (LONGLONG)MAX_FILE_SIZE)
{
::CloseHandle(hFile);
return false;
}
WORD bom = 0;
DWORD dwNumberOfBytesRead = 0;
::ReadFile(hFile, &bom, 2, &dwNumberOfBytesRead, nullptr);
if (dwNumberOfBytesRead != 2 || bom != 0xFEFF) // utf16-le 的前两个字节是 FF FE
{
::CloseHandle(hFile);
return false;
}
// 现在文件指针已经移动到了 2
int FileSize = (int)(liFileSize.QuadPart);
FileSize -= 2; // 字节序的字节数
int CharNumber = FileSize / 2; // 保留偶数
// 现在,只剩下了 CharNumber 个WCHAR,要把它们读入 s_FileBuffer
memset(s_FileBuffer, 0, sizeof(s_FileBuffer));
if (!::ReadFile(hFile, (PVOID)s_FileBuffer, (DWORD)(sizeof(WCHAR) * CharNumber), &dwNumberOfBytesRead, nullptr))
{
::CloseHandle(hFile);
return false;
}
m_CharNumber = CharNumber;
::CloseHandle(hFile);
return true;
}
#include "PublicGo.h"
class CTextLine
{
private:
enum :int32 { MAX_LINE_LEN = 200 };
private:
int32 Time;
WCHAR sText[MAX_LINE_LEN];
friend class CLyric;
};
class CLyric
{
private:
enum :int32
{
MAX_FILE_SIZE = 1048576L, // 1 MB
MAX_CHAR_NUMBER = MAX_FILE_SIZE / 2
};
public:
CLyric();
~CLyric();
private:
CLyric(const CLyric&) = delete;
CLyric& operator = (const CLyric&) = delete;
public:
bool LoadLyric(PCWSTR pFileName, int32 CurrentTime);
bool TimeTo(int32 CurrentTime);
public:
bool LoadFileToBuffer(PCWSTR pFileName);
private:
bool m_fValid;
int m_CharNumber;
WCHAR m_FileName[MAX_PATH]; // 维护文件名,而不是文件句柄
static WCHAR s_FileBuffer[MAX_CHAR_NUMBER];
};