C++에서 파일 입출력
헤더 파일
<fstream>
: 파일 입출력 작업을 위한 헤더 파일.ifstream
: 파일에서 읽기 위한 입력 파일 스트림.ofstream
: 파일에 쓰기 위한 출력 파일 스트림.fstream
: 읽기와 쓰기 모두를 위한 파일 스트림.- 파일 스트림은
<<
,>>
, 조정자(manipulator) 등을 지원한다.
파일 열기
open()
메서드
fin.open("HelloWorld.txt", ios_base::in | ios_base::binary);
모드 플래그
in
,out
,ate
(끝에서),app
(덧붙이기),trunc
(재설정 및 쓰기),binary
.
파일 닫기
ifstream fin;
/* 코드 */
fin.close();
스트림 상태 확인
close()
: 각 스트림마다 사용 가능한 닫기 메서드.is_open()
: 파일이 열려 있는지 확인.
if (fs.is_open() == true) {...} // 파일이 열려 있음.
파일에서 문자 하나씩 읽기
get()
, getline()
, >>
활용
- 어떤 스트림(cin, instringstream 등)을 사용하더라도 동일하게 작동.
fin.get(character); // 문자 하나 읽기
fin.getline(name, 20); // 문자 20개 읽기
getline(fin, line); // 한 줄 읽기
fin >> word; // 한 단어 읽기
파일에서 한 줄 읽기
while(fin.eof() == false)
{
getline(fin, line);
cout << line << endl;
}
- 빈 파일을 읽었을 때,
eof
비트가 켜지고,line
은 아무것도 받아오지 못했지만,endl
을 만나서 개행 출력을 해준다.
파일에서 한 단어씩 읽기
ifstream fin;
fin.open("test.txt");
string name;
float balance;
while (fin.eof() == false)
{
fin >> name >> balance;
cout << name, ": $" << balance << endl;
}
fin.close();
잘못된 입력 처리
- 제대로 읽은 경우만 출력
if (!fin.fail())
코드를 추가.- 파일 오프셋은 변경되지 않으므로 무한 루프를 피할 수 없다.
- 다음 구분 문자까지 건너뛰기
if (fin.fail()) { fin.clear(); fin.ignore(LLONG_MAX, ' '); } else { cout << number << endl; }
- 숫자만 읽기문자는 담아주고, 나머지는 읽어서 비워버린다.
#include <iostream> #include <fstream> int main() { std::ifstream fin; std::string trash; int number; while (true) { if (!fin.fail()) { fin >> number; std::cout << number << std::endl; continue; } if (fin.eof()) { break; } fin.clear(); fin >> trash; } fin.close(); }
- 주의점
fail 비트가 켜져 있는 경우 뒤의 문자를 읽을 수 없다.
clear로 비워주더라도 offset이 변경되는 것이 아니기 때문에 무한루프에 빠질 수 있다.
EOF 처리
- 입출력 연산은 스트림 상태 비트를 변경하므로 EOF를 정확히 처리해야 함.
- EOF를 잘못 처리하면 무한 반복이 발생할 수 있다.
clear()
를 사용할 때 두 번 생각하기.
파싱 문제
- 업계에서 흔한 문제이며, 자체 스트림 리더를 만들기도 함.
테스트 케이스
파일에 쓰기
std::endl
vs.‘\n’
‘\n’
은 스트림을flush()
하지 않음.std::endl
은 스트림을flush()
함.
put()
, <<
를 이용한 파일에 문자 쓰기
fout.put(character);
fout << line << endl;
바이너리 파일 읽기
ifstream::read()
read(char *, streamsize)
fin.read(&name, 20);
// 파일로부터 문자 20개를 읽어 name에 저장.
바이너리 파일 쓰기
ofstream::write()
write(const char *, streamsize)
fout.write(name, 20);
파일 안에서의 탐색
seekp(seek put)
: 쓰기 포인터.fs.seekp(20, ios_base::beg)
: 처음 위치로부터 20바이트 뒤로 이동.
탐색 유형
- 절대적: 특정 위치로 이동. 보통
tellp()
/tellg()
를 사용하여 기억한 위치로 돌아갈 때 사용. - 상대적: 파일 끝에서부터의 이동.
{beg / cur / end}
가 있다.
tellp()
- 쓰기 포인터의 위치를 구한다.
ios::pos_type pos = fout.tellp();
seekp()
- 절대적
fout.seekp(0); // 처음 위치로 이동
- 상대적
fout.seekp(20, ios_base::cur); // 현재 위치로부터 20 바이트 뒤로 이동
주의사항
>>
와getline()
을 함께 사용하지 말 것.
/*
[입력 값]
1
Cheerios
*/
cin >> number;
getline(cin, line); // cin에서 공백을 꺼내감.
cin >> number
에서 1을 읽는다.- 파일은 아직
\n
이 남아 있어서getline
에서 개행만 읽는다.
개선된 코드
cin >> number;
cin >> ws; // 공백을 읽어서 버린다.
getline(cin, line);
'Language > C++' 카테고리의 다른 글
[C++] 8.Unmanaged Programming: Instance 생성 (0) | 2024.01.23 |
---|---|
[C++] 7.Unmanaged Programming: Class (0) | 2024.01.23 |
[C++] 5.Unmanaged Programming: 문자열(string) (0) | 2024.01.21 |
[C++] 4.Unmanaged Programming: 참조(Reference) (0) | 2024.01.21 |
[C++] 3.Unmanaged Programming: 입력 스트림(Input Stream) (1) | 2024.01.21 |