|
한라씩 읽어서 처리해야 하는 파일일 경우 한 라인길이가 일정치 않고 매우 긴 경우도 있습니다.
fgets 등으로 읽었을 경우 설정해놓은 버퍼의 크기를 넘는 줄은 처리하는데 문제가 발생하더라구요.
그래서 메모리맵으로 파일을 한꺼번에 읽어 저장한 후 라인피드를 검색해가며 라인을 읽었습니다.
메모리맵은 Winapi 함수들입니다.
//boyer moore 알고리즘
long Moore(char* pszStr1,char* pszStr2)
{
long i, j, k, len;
static int skip[UCHAR_MAX + 1];
unsigned char c, tail;
if((pszStr1 == NULL) || (strlen(pszStr1) == 0)) return -1;
len = strlen((char*)pszStr2);
if(len == 0) return -1;
tail = pszStr2[len - 1];
if(len == 1)
{
for(i=0; pszStr1 != '\0'; i++)
if(pszStr1[i] == tail) return i;
}
else
{
for(i = 0; i <= UCHAR_MAX; i++)skip[i] = len;
for(i = 0; i< len -1 ; i++)
skip[ pszStr2[i]] = len - 1 - i;
while((c = pszStr1[i]) != '\0'){
if(c == tail){
j = len - 1; k= i;
while(pszStr2[--j] == pszStr1[--k])
if(j == 0) return k;
}
i += skip[c];
}
}
return -1;
}
void Processing(char *path)
{
char *szData = NULL;
long nPtr = 0;
long pos = 0;
DWORD dwFileSize;
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hMapFile = NULL;
hFile = CreateFile(path, GENERIC_READ,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) return;
dwFileSize = ::GetFileSize(hFile, NULL);
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL);
if(hMapFile == NULL){
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
return;
}
szData = (char*)MapViewOfFile(hMapFile, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 0);
if(szData == NULL){
CloseHandle(hFile);
CloseHandle(hMapFile);
hFile = INVALID_HANDLE_VALUE;
hMapFile = NULL;
return;
}
//---------------------------------------------------------------------
//szData 에 담긴 파일을 '\n' 단위로 끊어 읽는다.
while(1)
{
pos = Moore(szData + nPtr, "\n"); //moore 알고리즘 사용하여 검색
if(pos != -1){
//szData + nPtr 부터 pos + 1('\n'의 길이까지) 까지가 한 라인
char *p = malloc(pos + 2);
ZeroMemory(p, pos + 2);
strcpy(p, szData + nPtr, pos + 1);
//처리
free(p);
p = NULL;
nPtr += pos; // 검색할 포인터를 옮기기위해
}
else{
//더이상 '\n' 이 없는것이므로
break;
}
}
//---------------------------------------------------------------------
if (szData){
UnmapViewOfFile((LPCVOID)szData);
szData = NULL;
}
if (hMapFile != NULL){
CloseHandle(hMapFile);
hMapFile = NULL;
}
if (hFile != INVALID_HANDLE_VALUE){
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
}
문제가 있을듯....
허접 답변이었습니다.
권기식.별사랑 님이 쓰신 글 :
: 안녕하세요?
: 요즘 고급프로그래밍 수업을 들으면서 파일 입출력을 매번 쓰고 있습니다.
: C++ 파일 입출력 클래스에서는 getline이라는 것을 썼는데...
: 빌더에서는 그걸 어떻게 쓰는지 통 모르겠네요..
:
: 도움말을 보니 TFileStream이나 THandleStream을 쓰거나..
: FileOpen으로 파일을 열 때 생기는 핸들을 받아서 그 핸들을 이용해서 FileWrite, FileRead 등의 함수를 써서 입출력을 하더군요..
: 이렇게 하면 왠만한 건 해결하겠는데..
: 한 줄을 통째로 읽어드리는게 여간 번거로운 일이 아닌 것 같습니다.
: VCL에 이런 일을 해주는 함수가 제공되는지 궁금합니다.
:
: TStringList를 이용하라는 글도 봤는데..
: 지금 읽어들일 파일이 9000라인이 넘는 엄청난 텍트스파일입니다.
: 그래서 이 클래스를 이용하기에는 무리가 있을 것 같습니다.
:
: 지금은 급한대로 라인을 입력받는 함수를 만들어서 써야할 것 같군요..
: 그런데 파일 끝 체크는 어떻게 하죠? ^^;
: c의 eof() 함수를 써야 하나요?
:
: 이 모든 것들을 쉽게 할 수 있는 방법이 없을까요?
:
: 그리고 일반적으로 윈도우 프로그래밍에서 파일 처리는 C++ 표준 스트림을 이용하는지 아니면 빌더의 클래스를 이용하는지도 살짝 알려주시면 감사하겠습니다. ^^
|