C++ 다양한 방법의 파일 입출력이 있지만 그 중에서 fopen 함수와 이와 관련된 함수를 이용하여 파일 입출력에 대해 간단히 알아보고 예제 프로그램을 작성해보자!
파일을 여는 함수
#include <cstdio> // c에서는 stdio.h
FILE* fopen(const char* filename, const char* mode);
파일 이름인 filename과 스트림에서 어떠한 입출력 작업이 가능한지를 mode 인자 파라미터로 입력하면 return 값으로 FILE 객체를 가리키는 포인터를 줍니다. 최대 동시에 열수 있는 파일 갯수는 cstio.h의 FOPEN_MAX에 정의되어 있다고 한다.
#include <cstdio> // c에서는 stdio.h
int fclose (FILE* filePointer)
fopen으로 생성된 파일포인터를 매개변수로 받는다. fclose의 반환타입은 int인데 정상적으로 동작하면 0, 그렇지 않을 때는 EOF(-1)을 반환한다고 한다.
파일을 닫는다
스트림에 데이터 블록을 쓴다.
#include <cstdio> // c에서는 stdio.h
size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream);
데이트 크기가 size인 개수가 count인 pointer ptr이 가르키는 데이터 블록을 stream에 쓰이게 된다.
리턴은 size_t로써 쓰여진 byte 수와 count 값이 같으면 정상이다.
스트림을 비운다.
#include <cstdio> // c에서는 stdio.h
int fflush(FILE* stream);
매개변수의 stream이 쓰기 가능하고 마지막 입출력 작업이 쓰기였다면 출력 버퍼에 쓰이지 않고 남아 있던 데이터들은 모두 파일에 쓰이게 된다. 반면 스트림이 읽기 가능하고 마지막 입출력이 입력 작업이면 다음 작업 어떠한 작업인지에 따라 다르다. 이 함수 호출 이후에도 스트림은 열려 있는 상태로 남아있다. 만일 파일이 close하게 되면 이 파일에 해당하는 모든 버퍼들은 자동적으로 비워지게 된다.
리턴은 int로써 0이면 정상수행했다는 뜻이다.
스트림의 위치 지정자의 현재 위치를 구한다.
#include <cstdio> // c에서는 stdio.h
long int ftell(FILE* stream);
스트림이 읽거나 써서 이동한 현재 위치 값을 반환한다.
성공적으로 수행했다면 현재의 위치 포인터가 가진 값이 리턴된다. 만일 오류가 발생한다면 리턴값이 NULL이 되고 errno 전역변수의 값이 양수가 된다. strerror_tl(errno)로 값을 확인할 수 있다.
간단히 현재 디렉토리에 logger.log라는 파일을 만들어보는 예제이다.
생성자를 통해 현재 디렉토리에 파일을 생성하고 멤버함수인 logToFile을 통해 매개변수의 string을 그대로 파일에 써준다. 그리고 해당 파일의 크기를 확인해보고 프로그램이 종료되면서 소멸자를 통해 fclose를 한다.
#include <iostream>
#include <string>
#include <cstdio>
class LoggerFile {
public:
LoggerFile(std::string filePath, std::string fileName, std::string fileExtName)
:filePath_(std::move(filePath)), fileName_(fileName), fileExtName_(fileExtName),
filePtr(nullptr)
{
fileFullName_ = filePath_ + fileName_ + fileExtName_;
filePtr = fopen(fileFullName_.c_str(), "a");
}
~LoggerFile(){
if(filePtr) fclose(filePtr);
}
void logToFile(const std::string& log){
if(filePtr) fwrite(log.c_str(), 1, log.size(), filePtr);
}
void flush(){
if(filePtr) fflush(filePtr);
}
long getLength(){
if(filePtr){
return ftell(filePtr);
}
return 0;
}
private:
std::string filePath_;
std::string fileName_;
std::string fileExtName_;
FILE* filePtr;
std::string fileFullName_;
};
int main() {
LoggerFile loggerFile = LoggerFile("{디렉토리 위치}",
"logger", ".log");
loggerFile.logToFile("hello every one");
loggerFile.flush();
std::cout << loggerFile.getLength() << std::endl;
return 0;
}