⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpafilestream.cpp

📁 获取mp3信息, Xing header, ID3 tag, APE tag, VBR header
💻 CPP
字号:
#include "StdAfx.h"
#include "MPAFileStream.h"
#include "mpaexception.h"
#include "mpaendoffileexception.h"

// 1KB is inital buffersize
const DWORD CMPAFileStream::INIT_BUFFERSIZE = 1024;	

CMPAFileStream::CMPAFileStream(LPCTSTR szFilename) :
	CMPAStream(szFilename), m_dwOffset(0)
{
	// open with CreateFile (no limitation of 128byte filename length, like in mmioOpen)
	m_hFile = ::CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, 
										    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (m_hFile == INVALID_HANDLE_VALUE)
	{
		// throw error
		throw CMPAException(CMPAException::ErrOpenFile, szFilename, _T("CreateFile"), true);
	}
	Init();
}

CMPAFileStream::CMPAFileStream(LPCTSTR szFilename, HANDLE hFile) :
	CMPAStream(szFilename), m_hFile(hFile)
{
	Init();
}


void CMPAFileStream::Init() 
{
	m_dwBufferSize = INIT_BUFFERSIZE;
	// fill buffer for first time
	m_pBuffer = new BYTE[m_dwBufferSize];
	FillBuffer(m_dwOffset, m_dwBufferSize, false);
}

CMPAFileStream::~CMPAFileStream(void)
{
	if (m_pBuffer)
		delete[] m_pBuffer;
	
	// close file
	if (m_bMustReleaseFile)
		::CloseHandle(m_hFile);	
}

// VC++6 doesn't contain this definition
#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif

// set file position
void CMPAFileStream::SetPosition(DWORD dwOffset) const
{
	// convert from unsigned DWORD to signed 64bit long
	DWORD result = ::SetFilePointer(m_hFile, dwOffset, NULL, FILE_BEGIN); 
	if (result == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
	{ 
		// != NO_ERROR
		// throw error
		throw CMPAException(CMPAException::ErrSetPosition, m_szFile, _T("SetFilePointer"), true);
	}
}


BYTE* CMPAFileStream::ReadBytes(DWORD dwSize, DWORD& dwOffset, bool bMoveOffset, bool bReverse) const
{
	// enough bytes in buffer, otherwise read from file
	if (m_dwOffset > dwOffset || ( ((int)((m_dwOffset + m_dwBufferSize) - dwOffset)) < (int)dwSize))
	{
		if (!FillBuffer(dwOffset, dwSize, bReverse)) 
		{
			throw CMPAEndOfFileException(m_szFile);
		}
	}

	BYTE* pBuffer = m_pBuffer + (dwOffset-m_dwOffset);
	if (bMoveOffset)
		dwOffset += dwSize;
	
	return pBuffer;
}

DWORD CMPAFileStream::GetSize() const
{
	DWORD dwSize = ::GetFileSize(m_hFile, NULL);
	if (dwSize == INVALID_FILE_SIZE)
		throw CMPAException(CMPAException::ErrReadFile, m_szFile, _T("GetFileSize"), true);
	return dwSize;
}

// fills internal buffer, returns false if EOF is reached, otherwise true. Throws exceptions
bool CMPAFileStream::FillBuffer(DWORD dwOffset, DWORD dwSize, bool bReverse) const
{
	// calc new buffer size
	if (dwSize > m_dwBufferSize)
	{
        m_dwBufferSize = dwSize;
		
		// release old buffer 
		delete[] m_pBuffer;

		// reserve new buffer
		m_pBuffer = new BYTE[m_dwBufferSize];
	}	

	if (bReverse)
	{
		if (dwOffset + dwSize < m_dwBufferSize)
			dwOffset = 0;
		else
			dwOffset = dwOffset + dwSize - m_dwBufferSize;
	}

	// read <m_dwBufferSize> bytes from offset <dwOffset>
	m_dwBufferSize = Read(m_pBuffer, dwOffset, m_dwBufferSize);

	// set new offset
	m_dwOffset = dwOffset;

	if (m_dwBufferSize < dwSize)
		return false;

	return true;
}

// read from file, return number of bytes read
DWORD CMPAFileStream::Read(LPVOID pData, DWORD dwOffset, DWORD dwSize) const
{
	DWORD dwBytesRead = 0;
	
	// set position first
	SetPosition(dwOffset);

	if (!::ReadFile(m_hFile, pData, dwSize, &dwBytesRead, NULL))
		throw CMPAException(CMPAException::ErrReadFile, m_szFile, _T("ReadFile"), true);
	
	return dwBytesRead;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -