1. 기본 출력
#include <fstream>
int main()
{
std::ofstream ofs;
ofs.open("filename");
if (ofs.is_open() == false)
return 1;
ofs << "I don't drink coffee, I take tea, my dear\n";
ofs.close();
return 0;
}
I don't drink coffee, I take tea, my dear
- ofstream을 이용한다.
- open 멤버함수의 첫 번째 매개변수는 파일 이름이고, 두 번째 매개변수는 생략가능한 옵션이다.
- is_open()은 파일이 잘 열렸는지 판단한다. 성공적이라면 true를 반환한다.
- 열었으면 잘 닫자.
2. 출력 옵션
#include <fstream>
int main()
{
std::ofstream ofs;
ofs.open("filename", std::ofstream::out | std::ofstream::app);
if (ofs.is_open() == false)
return 1;
ofs << "I like my toast done on one side\n";
ofs.close();
return 0;
}
I don't drink coffee, I take tea, my dear
I like my toast done on one side
- 기본값은
std::ofstream::out | std::ofstream::trunc
이다. - app 플래그를 넣으면 기존 파일 맨 끝에서부터 이어서 쓴다.
- 비트연산자 '|'로 플래그를 결합할 수 있다.
플래그 목록
- in
- 읽기 모드로 연다.
- out
- 쓰기 모드로 연다.
- binary
- 텍스트가 아닌 이진파일 모드로 연다
- ate
- "at end"라서 ate다.(네이밍센스가...) 파일포인터가 맨 뒤로 간다.
- app
- append. 파일 뒤에 출력을 추가할 때 쓴다.
- trunc
- truncate. 파일을 비운 후에 시작한다.
궁금한 것들은 대부분 www.cplusplus.com에서 해소 가능하다. 하지만 open의 플래그에 대해서는 설명이 다소 부실하다. 대관절, 출력스트림에 읽기모드는 무슨 의미가 있는 것이며, ate와 app의 차이는 무엇인지 이것만 봐서는 이해하기가 어렵다.
결론부터 이야기 하자면,
- in 플래그는 읽기전용으로 파일을 열게 하는 플래그가 아니다. in 플래그가 없으면 파일이 비워진다.
좀 더 정확하게 이야기 하자면 in 플래그가 있으면 파일이 비워지지 않는다. - ate는 파일포인터를 자유롭게 옮길 수 있다.
- app는 파일포인터가 뒤로 고정된다. 그리고 app는 파일을 비우지 않는다.
몇 가지 테스트를 해보자면
ate와 app의 차이
app
#include <fstream>
int main()
{
std::ofstream ofs;
ofs.open("filename", std::ofstream::trunc);
ofs << "ABCDEFGHIJKLMN";
ofs.close();
ofs.open("filename", std::ofstream::app);
// 파일 열기 실패했을 경우에 대한 오류 헨들링 생략
ofs.seekp(2);
ofs << "[123]";
ofs.close();
return 0;
}
ABCDEFGHIJKLMN[123]
(seekp(long)
는 인자의 위치로 파일포인터를 이동시킨다.)
- 파일이 비워지지 않았고, 파일포인터는 맨 뒤에 있다.
- seekp(2)로 파일 포인터를 시작점으로부터 2만큼 이동시켰다.
- 그러나 아무일도 일어나지 않았다! seekp(2)를 무시하고
[123]
을 파일 맨 뒤에 이어붙였다.
ate
#include <fstream>
int main()
{
// 파일을 매번 열어서 ABCDEFGHJKLMN으로 수정하기 귀찮다
std::ofstream ofs;
ofs.open("filename", std::ofstream::trunc);
ofs << "ABCDEFGHIJKLMN";
ofs.close();
// ate 플래그만 넣어보았다.
ofs.open("filename", std::ofstream::ate);
// 파일 열기 실패했을 경우에 대한 오류 헨들링 생략
ofs.seekp(2);
ofs << "[123]";
ofs.close();
return 0;
}
@@[123]
('@'는 쓰레기값이다.)
- in 플래그가 없어서 파일이 비워졌다.
- seekp(2)가 파일 포인터를 2로 이동시켰다.
[0, 2)
사이에는 쓰레기값이 들어갔다. - 그 자리에
[123]
을 썼다. 만약 seekp가 없었다면 파일의 맨 앞에[123]
을 썼을 것이다.
app와는 달리 seekp함수가 역할을 해냈다는 것이 포인트다.
ate + in
#include <fstream>
int main()
{
// 파일을 매번 열어서 ABCDEFGHJKLMN으로 수정하기 귀찮다
std::ofstream ofs;
ofs.open("filename", std::ofstream::trunc);
ofs << "ABCDEFGHIJKLMN";
ofs.close();
// ate + in
ofs.open("filename", std::ofstream::ate | std::ofstream::in);
// 파일 열기 실패했을 경우에 대한 오류 헨들링 생략
ofs.seekp(2);
ofs << "[123]";
ofs.close();
return 0;
}
AB[123]HIJKLMN
- 이번에는 in 플래그가 있어서 파일이 비워지지 않았다.
- seekp(2)가 잘 작동한 것을 볼 수 있다.
ate + in, seekp 없이
#include <fstream>
int main()
{
// 파일을 매번 열어서 ABCDEFGHJKLMN으로 수정하기 귀찮다
std::ofstream ofs;
ofs.open("filename", std::ofstream::trunc);
ofs << "ABCDEFGHIJKLMN";
ofs.close();
// ate + in
ofs.open("filename", std::ofstream::ate | std::ofstream::in);
// 파일 열기 실패했을 경우에 대한 오류 헨들링 생략
// ofs.seekp(2);
ofs << "[123]";
ofs.close();
return 0;
}
ABCDEFGHIJKLMN[123]
- seekp(2)를 없앴더니 파일포인터가 맨 뒤에 있는 것을 볼 수 있다.
영 좋지 않은 플래그 조합
app + trunc 조합으로 파일을 열려고 하면 실패한다.
app + in 조합도 실패한다.(라고 배웠지만, 내 컴퓨터에서는 된다.)
의외로 in + out 같은 경력있는신입 조합도 (내 컴퓨터에서는) 된다.
'컴퓨터 > C++' 카테고리의 다른 글
const에 관하여 (0) | 2020.12.23 |
---|