안녕하세요 만해입니다 ^^
제가 대용량 텍스트 파일 처리를 자주 하다 보니깐
java의 BufferedReader 같은 객체가 있었으면 했었는데..
C++에서는 없더라고요..
그래서 시간내서 만들었습니다 ^^
너무 너무 간단해서 굳이 설명은 필요 없을거라고 생각 됩니다.
이 소스는 BDS2006 Turbo에서 정상 동작 하고요..
아마 RAD 2009 이상에서는 테스트를 안해봐서 잘 모르겠지만,
Ansi 문서에서는 정상 동작 할것으로 판단됩니다. ^^
//---------------------------------------------------------------------------
bool __fastcall TBufferedReader::ReadMore(void)
{
if ( fp->Position == fp->Size )
return false;
ZeroMemory(pBuffer, iBufSize+1);
pSeg = 0;
iNextPos = 0;
int iReadSize = fp->Read(pBuffer, iBufSize);
if ( iReadSize == 0 )
{
ZeroMemory(pBuffer, iBufSize);
return false;
}
else
iBufLen = iReadSize;
int iSkipLen = 0;
if ( iReadSum + iBufLen < fp->Size )
{
while ( pBuffer[iBufLen-iSkipLen] != '\n' ) iSkipLen++;
fp->Seek(((iSkipLen-1)*-1), soFromCurrent);
iBufLen = iBufLen - iSkipLen+1;
iReadSum += iBufLen;
ZeroMemory(pBuffer+iBufLen, iBufSize-iBufLen);
pBuffer[iBufLen] = '\n';
}
else
pBuffer[iBufLen+1] = '\n';
for ( int i = iBufLen+1 ; i > -1 ; i -- )
{
if ( pBuffer[i] == '\n')
{
pBuffer[i] = NULL;
posList.push_back(i+1);
}
}
posList.push_back(0);
return true;
}
//---------------------------------------------------------------------------
char* __fastcall TBufferedReader::GetNextLine(void)
{
while ( 1 )
{
if ( posList.size() == 0)
if ( ReadMore() == false )
return NULL;
pSeg = posList[posList.size()-1];
posList.pop_back();
if ( strlen(pBuffer+pSeg) > 0 )
break;
}
return pBuffer+pSeg;
}
//---------------------------------------------------------------------------
코드에서의 핵심은 ReadMore() 함수이고요
저 함수에서 단위 용량 크기만큼만 File에 있는것을 버퍼로 읽어 들입니다.
그리고 그 버퍼에서 \n 부분을 NULL로 변환 시킨후 문장 단위로 쪼개서
GetNextLine()의 반환값으로 보내 줍니다.
사용 예제는 다음과 같습니다.
TBufferedReader * br = NULL;
try
{
try
{
br = new TBufferedReader(FileName, fmOpenRead, 1);
char* pBuf = NULL;
AnsiString str;
__int64 xpos=0;
__int64 ypos=0;
__int64 value=0;
while ( (pBuf = br->GetNextLine()) != NULL )
{
str = AnsiString(pBuf);
xpos = StrToInt(str.SubString(0,str.Pos(":")-1));
ypos = StrToInt(str.SubString(str.Pos(":")+1,str.Pos("\t")-str.Pos(":")-1 ) );
value = StrToInt(str.SubString(str.Pos("\t")+1, str.Length() - str.Pos("\t")).Trim());
freqMap[xpos] += value;
freqMap[ypos] += value;
}
map<__int64, int>::iterator itr;
for ( itr = freqMap.begin() ; itr != freqMap.end() ; itr ++ )
cout << itr->first << "\t" << itr->second << endl;
}
catch (Exception &E)
{
cout << "Not Enought Memory.... T_T" << endl;
}
}
__finally
{
delete br;
}
|