|
아래는 파일 입출력 클래스 간단히 라인단위로 읽어 올수 있도록 만들어본
랩퍼 클래스
//선언부
class TLineFile
{
private:
THandle lffile;
public:
TLineFile();
~TLineFile();
int FileOpen(const AnsiString FileName, unsigned Mode);
int Open(const AnsiString FileName, unsigned Mode);
int FileRead(void *Buffer, unsigned Count);
int Read(void *Buffer, unsigned Count);
int FileWrite(const void *Buffer, unsigned Count);
int Write(const void *Buffer, unsigned Count);
int FileReadLn(void *Buffer, unsigned Count);
int ReadLn(void *Buffer, unsigned Count);
int FileSeek(int Offset, int Origin);
int Seek(int Offset, int Origin);
bool FEof();
void FileClose();
void Close();
};
//정의부
TLineFile::TLineFile()
{
this->lffile = 0;
}
TLineFile::~TLineFile()
{
if(this->lffile != 0) {
this->FileClose();
}
}
int TLineFile::FileOpen(const AnsiString FileName, unsigned Mode)
{
lffile = ::FileOpen(FileName, Mode);
return lffile;
}
int TLineFile::Open(const AnsiString FileName, unsigned Mode)
{
return this->FileOpen(FileName, Mode);
}
int TLineFile::FileRead(void *Buffer, unsigned Count)
{
::ZeroMemory(Buffer, Count);
return ::FileRead(this->lffile, Buffer, Count);
}
int TLineFile::Read(void *Buffer, unsigned Count)
{
::ZeroMemory(Buffer, Count);
return this->FileRead(Buffer, Count);
}
int TLineFile::FileWrite(const void *Buffer, unsigned Count)
{
return ::FileWrite(this->lffile, Buffer, Count);
}
int TLineFile::Write(const void *Buffer, unsigned Count)
{
return this->FileWrite(Buffer, Count);
}
int TLineFile::FileReadLn(void *Buffer, unsigned Count)
{
int oseek = this->FileSeek(0, 1);
int ret = this->FileRead(Buffer, Count);
char * cpos = StrPos((char*)Buffer, "\r\n");
if(cpos != NULL) {
ret = cpos-(char*)Buffer;
this->FileSeek(oseek+ret+2, 0);
::ZeroMemory(cpos, Count-ret);
}
return ret;
}
int TLineFile::ReadLn(void *Buffer, unsigned Count)
{
return FileReadLn(Buffer, Count);
}
int TLineFile::FileSeek(int Offset, int Origin)
{
return ::FileSeek(this->lffile, Offset, Origin);
}
int TLineFile::Seek(int Offset, int Origin)
{
return this->FileSeek(Offset, Origin);
}
bool TLineFile::FEof()
{
int cp = this->FileSeek(0, 1);
int ceof = this->FileSeek(0, 2);
this->FileSeek(cp, 0);
return (cp >= ceof);
}
void TLineFile::FileClose()
{
::FileClose(this->lffile);
this->lffile = 0;
}
void TLineFile::Close()
{
this->FileClose();
}
// 여기가 끝
// 사용법
// 90000만건 정도가 1.5초 정도
// 라인단위로 읽는 방법은 블럭 단위로 읽어서
// 개행문자를 추출한 후 그 위치 + 2 가 다음 파일 위치고
// 뒷문자는 클리어 하는 방식임
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int count;
char Buffer[151];
AnsiString fname = ExtractFilePath(Application->ExeName) + "linefile.txt";
TLineFile *lfile = new TLineFile();
lfile->FileOpen(fname, fmOpenRead);
int nFirst = GetTickCount();
while(true) {
if(lfile->FEof()) break;
lfile->FileReadLn(Buffer, 150);
}
Caption = IntToStr(GetTickCount()-nFirst);
lfile->~TLineFile();
}
태즈 님이 쓰신 글 :
: 10000 * 5 = 5만라인 정도의 내용을 가지는 텍스트를 읽어서 데이타를 뽑으려 합니다.
: 각라인에는 7개의 float 변수값이 표시되어있습니다.
:
: 이걸 RichEdit 로 읽어온뒤에,
: for( n = 0 ; n < max ; n ++ ) {
: sscanf( RichEdit1->Lines->Strings[ n ].c_str(), " %f %f %f %f %f %f %f ", &x, &y, &z, &r, &g, &b, &a ) ;
:
: //-- 읽어온 데이터들 처리루틴..
: ~~~
: ~~~
: }
:
: 이러한 방식으로 7개 변수값을 추출하고 있습니다.
: 6만라인을 처리하는데 생각보다 너무 많은 시간이 걸리네요.
: 요부분을 빼고 연산하는 부분만 6만번 돌리는 데는 시간이 별로 안 걸리더군요.
: 그래서 '아마도' 이 부분에서 시간을 많이 잡아먹는 것 같은데..
:
: 이걸 빠르게 구현하려면 어떻게 해야할까요..
:
: ---------------------------------------
:
: 추가적으로 몇가지 테스트를 해보았습니다.
: 테스트할 파일의 길이를 달리하여 테스트한 것입니다.
: 라인수 증가에 따라서 걸리는 시간이 일차적으로 비례하지 않고 있네요.
: 테스트 벡터의 내용은 거의 비슷하기에, 연산량의 차이는 없다고 보고요.
:
: 5000 라인 : 1초미만
: 10000 라인 : 1.5초정도.
: 20000 라인 : 10초정도.
: 30000 라인 : 23초정도
: 40000 라인 : 41초정도.
:
: 60000 라인 : 110초.
:
: 어찌해야할까요...
: --------------------------------------------
:
: 여전한 극초보 태즈였습니다.
: 감사합니다.
|