C++ file 입출력

gyubong park·2021년 12월 31일
0

C++ 다양한 방법의 파일 입출력이 있지만 그 중에서 fopen 함수와 이와 관련된 함수를 이용하여 파일 입출력에 대해 간단히 알아보고 예제 프로그램을 작성해보자!

fopen

파일을 여는 함수

#include <cstdio> // c에서는 stdio.h
FILE* fopen(const char* filename, const char* mode);

파일 이름인 filename과 스트림에서 어떠한 입출력 작업이 가능한지를 mode 인자 파라미터로 입력하면 return 값으로 FILE 객체를 가리키는 포인터를 줍니다. 최대 동시에 열수 있는 파일 갯수는 cstio.h의 FOPEN_MAX에 정의되어 있다고 한다.

  • mode에 대한 추가 설명
    • r : 파일을 읽기 형식으로 연다. 이 때, 파일은 반드시 존재해야 한다.
    • w : 파일을 쓰기 형식으로 연다. 만일 동일한 파일이 이미 존재하고 있다면 그 파일의 내용은 모두 지워진 후 새롭게 생긴 빈 파일로 간주하며, 파일이 존재하고 있지 않는다면 빈 파일을 새롭게 생성한다.
    • a : 파일을 덧붙이기(append) 형식으로 연다. 쓰기 작업은 파일 끝에 데이타를 덧붙일 것이다. 만일 파일이 존재하지 않는다면 새로 생성된다.
    • r+ : 파일을 읽기 및 쓰기 형식으로 연다. 이 때, 파일은 반드시 존재해야 한다.
    • w+ : 파일을 읽기 및 쓰기 형식으로 연다. 만일 동일한 파일이 이미 존재하고 있다면 그 파일의 내용은 모두 지워진 후 새롭게 생긴 빈 파일로 간주하며, 파일이 존재하고 있지 않다면 빈 파일을 새로 생성하게 된다.
    • a+ : 파일을 읽기 및 덧붙이기(append) 형식으로 연다. 지정한 파일이 존재하지 않는다면 새롭게 생성된다. 모든 쓰기 작업은 파일의 맨 끝에서 진행되며 기존의 파일 내용들에 덮혀씌여지지 않는다. 여러분은 읽기 작업에서는 fseek이나 rewind함수 등을 이용하여 파일 위치 포인터를 원하는 대로 움직일 수 있지만, 쓰기 작업에서는 위치 포인터를 언제나 파일 맨 끝으로 이동 시킬 것이다.

fclose

#include <cstdio> // c에서는 stdio.h
int fclose (FILE* filePointer)

fopen으로 생성된 파일포인터를 매개변수로 받는다. fclose의 반환타입은 int인데 정상적으로 동작하면 0, 그렇지 않을 때는 EOF(-1)을 반환한다고 한다.
파일을 닫는다

fwrite

스트림에 데이터 블록을 쓴다.

#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 값이 같으면 정상이다.

fflush

스트림을 비운다.

#include <cstdio> // c에서는 stdio.h
int fflush(FILE* stream);

매개변수의 stream이 쓰기 가능하고 마지막 입출력 작업이 쓰기였다면 출력 버퍼에 쓰이지 않고 남아 있던 데이터들은 모두 파일에 쓰이게 된다. 반면 스트림이 읽기 가능하고 마지막 입출력이 입력 작업이면 다음 작업 어떠한 작업인지에 따라 다르다. 이 함수 호출 이후에도 스트림은 열려 있는 상태로 남아있다. 만일 파일이 close하게 되면 이 파일에 해당하는 모든 버퍼들은 자동적으로 비워지게 된다.

리턴은 int로써 0이면 정상수행했다는 뜻이다.

ftell

스트림의 위치 지정자의 현재 위치를 구한다.

#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;
}
profile
초보 개발자

0개의 댓글