티스토리 뷰

C, C++

C++ fstream 간단한 사용법(파일입출력)

꿀벌의달콤한여행 2020. 6. 27. 09:22
인터넷을 돌아다니다 보니, 파일입출력은 기본 중에 기본이라고 한다.

C++를 주로 사용하고 있지만 파일입출력을 할 줄 몰랐다.

그래서 정리한다.

(내용출처 : http://www.cplusplus.com/doc/tutorial/files/ )




<fstream>

 C++는 <fstream> 이라는 Stream class를 지원한다. '파일에서 읽어오거나 파일에 쓰는 클래스' 라고 한다. istream과 ostream의 파생클래스이다(자식임).
 <fstream>에서 주로 쓰는 두 가지는 ofstream 과 ifstream 이다.




ofstream

 ofstream은 'output file stream'이다. output이라길래 파일의 내용을 읽어오는 줄 알았는데 내 생각과 반대로 파일에 적는 친구다.

ofstream에는 멤버함수 open이 있다. 사용법은 평소에 쓰던 cin, cout 과 비슷하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
    // 파일 열기
    ofstream myfile;
    myfile.open("example.txt");
    
    // 파일에 쓰기
    myfile << "Wow.\n";
    myfile << "Writing this to a file.\n";
    
    // 파일 닫기
    myfile.close();
    
    system("pause");
    return 0;
}
cs

 위의 코드를 실행하면 "example.txt" 파일을 읽어(없을 경우 생성함)
그곳에
"
Wow.
Writing this to a file
"
을 적고 파일을 닫는다. 다음과 같은 결과물이 나온다.




"<< 방향으로 내용을 몰아서 넣는다" 정도로 이해하고 있다.



1
2
ofstream.open(filename);
ofstream.open(filename, mode);
cs

 멤버함수 open은 파일이 외에도 인자를 받을 수도 있다. ios namespace 안의 in, out, binary, ate, app, trunc 을 받을 수 있고 이것들을 동시에 여러개 받을 수 있다고도 한다.
하지만 놀랍게도 iostream도 잘 몰라 정리할 능력이 안된다. 나중에 새로운 글에 적어보겠다.


1
2
3
4
5
6
7
// 얘를
ofstream myfile;
myfile.open("example.txt");
// 이렇게 줄여쓸 수도 있다. 역할은 같음
ofstream myfile("example.txt");
cs

한편 코드를 줄여 쓸 수도 있다. 위의 두 코드는 역할이 같다.




ifstream

 ifstream은 'input file stream'의 약자이다. input이라길래 적는 건 줄 알았지만, 반대로 읽어오는 친구이다. 사용법 역시 cin, cout과 비슷하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(void)
{
    string line;
    ifstream myfile;
    myfile.open("example.txt");
    if(myfile.is_open())
    {
        while(getline(myfile, line))
        {
            cout << line << "\n";
        }
        myfile.close();
    }
    else cout << "Unable to open file\n";
    
    system("pause");
    return 0;
}
cs

example.txt 파일을 열고

열린경우, 한줄씩 읽어 출력하고 다 읽으면 닫는다.
못 연 경우(파일이 없음), 준비된 문구를 출력한다.

헷갈린다면 꺽쇠에 주목하자. 결국 꺽쇠방향으로 몰아준다는 것은 똑같다.
(여기서는 string 형식의 데이터를 읽어오기 위해 string::getline()을 사용해서 꺽쇠 몰아주는 느낌이 없지만, numeric data를 읽을 때는 꺽쇠 방향으로 몰아준다고 생각하면 된다.
int a;
myfile >> a; // myfile에 있는 numeric data를 읽어서 a에 저장하는 것

while( myfile >> a ){} // 위의 getline처럼 활용할 수도 있다. EOF까지 파일을 읽어오는 것
)
ofstream과 큰차이가 없지만 파일을 읽어오기 위해 <string>을 사용했고 새로운 멤버함수인 is_open() 이 있다.


1
2
ofstream.is_open();
ifstream.is_open()
cs

is_open() 는 파일이 열린 경우 true를 반환, 열지 못한 경우 false를 반환한다.


    if(myfile.is_open())
    {
        while(getline(myfile, line))
        {
            cout << line << "\n";
        }
        myfile.close();
    }

위의 코드는 파일이 열린 경우 getline을 사용해 line 변수에 읽어들이고, 그것을 한줄씩 출력하는 역할을 한다.

getline함수는 myfile을 한줄씩 읽어오는데, EOF을 발견하면(파일의 끝) false를 반환한다.




file.close()

 코드들을 눈여겨봤다면 알 수 있겠지만 항상 파일을 열고 마지막엔 file.close() 을 이용해 파일을 닫아줬다. 만약 닫지 않는다면?

 닫지 않았을 경우 생기는 문제는 두 가지 정도 있는 것 같다. 쉬운 것부터 말하자면, 해당 객체로 새로운 파일을 열 수 없다는 것이다. 다음 코드를 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
    ofstream myfile;
    myfile.open("example.txt");
    myfile << "Wow.\n";
    myfile << "Writing this to a file.\n";
    //myfile.close();
    myfile.open("example2.txt");
    myfile << "not good\n";
    myfile << "I said, not gooood\n";
    system("pause");
    return 0;
}
cs


이 코드를 실행하면 example2.txt는 열리지 않는다. 그 이유는 앞서 example.txt를 열고 닫아주지 않았기 때문이다. 열어 놓은 걸 닫지 않고 또 열려고 하니 못여는 것이다.


(두 번째 이유는 불확실한 정보이다. 그냥 내 추측을 적었다)
 파일을 닫지 않아 생길 수 있는 두 번째 문제는 파일에 적었다고 생각한 내용이 적용되지 않을 수 있다는 것이다. 우리가 파일을 열고, '물리적인 파일'에 내용물을 적었다고 생각하지만, 사실 streambuf 타입의 buffer에 적은 것이다.(buffer는 임시 저장소라고 생각하면 된다) buffer에 적어두었다가 파일이 닫히면 그제서야 파일에 적기 시작하는데, 만약 파일을 닫아주지 않는다면 실제 파일에 적지 못할 수도 있는 것이다.

 하지만 위의 두 번째 문제는 실제로 일어나지 않는다(내수준에선). 크고 정교한 프로그램이라면 문제가 생길 여지가 있겠지만, fstream을 알고리즘문제 푸는 데에만 가끔 쓰는 나는 좋은 컴파일러가 알아서 해결해주고 있다. 실제로 위의 코드를 실행시키면 example.txt에는 내용이 잘 적힌다.



 그러나 닫아야할 파일도 닫지 않는다면 좋은 프로그래머가 될 수 없을 것이다. 그러니 파일을 열고 볼 일이 다 끝났다면 꼭 close() 멤버함수를 호출해 파일을 닫아주도록 하자.

( 만약 닫지 않더라도 파일과 연관된 오브젝트가 파괴될 때 destructor가 자동으로 file.close() 를 불러서 닫아준다고 한다. 그래도 아무튼 닫자. 아무튼 닫아야함)

'C, C++' 카테고리의 다른 글

C 파일입출력 정리  (0) 2020.06.27
댓글