ifstream fs;
fs.open("test.txt", ios_base::trunc);
char buf[100];
while (true)
{
fs.getline(buf, sizeof(buf));
cout << buf << endl;
if (fs.eof())
{
cout << "[End]" << endl;
break;
}
if (fs.fail())
{
cout << "[Fail]" << endl;
fs.clear();
fs.ignore(LLONG_MAX, '\n');
continue;
}
}
fs.close();
/*
100 200 300 을 읽는다고 가정 할 때 파일 포인터는
V
100 200 300 EOF
V
100 200 300 EOF
V
100 200 300 EOF
V
100 200 300 EOF
순으로 가리킨다.
*/
>>
연산자>>
연산자는 ' '이나 '\n'등을 구분자로 두어 문자열을 읽어 들인다.int number;
fin >> number;
/*
100 '\n' 300
100 읽고 \n 읽어 들이지만 숫자 아니라 값은 못 읽는다.
그 후에 파일 포인터는 300을 가리킨다.
*/
ofstream fs;
fs.open("test.txt");
char buf[100] = "ABCDEF";
fs << buf << " " << "This is My Life";
fs.close();
/*
기존에 파일이 존재할 경우 fs.open("test.txt"); 로 다시 열면 파일에 있는 내용 모두 사라진다.
fstream으로 열면 사라지지 않는다. 그러나 ios_base::out 옵션 주면 사라진다.
*/
//[test.txt]
//
//aaaaaaaaaaaaaaaaaaa
ofstream fs;
fs.open("test.txt", ios_base::in);
char buf[100] = "123";
fs << buf;
fs.close();
/*
결과 :
123aaaaaaaaaaaaaaaa
ios_base::in 속성을 주니까 파일을 삭제하지 않는다.
ios_base::in | ios_base::trunc 속성을 주면 삭제 한다.
*/
fstream fs;
fs.open("test.txt");
if (fs.is_open() == false)
{
cout << "not open" << endl;
return 0;
}
/*
파일 없을 경우 생성하지 않는다.
단 ios_base::out 속성을 주면 생성한다.
*/
//test.txt
//
//aaaaaaaaaaaaaaaaaaa
fstream fs;
fs.open("test.txt");
char buf[100] = "123";
fs << buf;
fs.close();
/*
결과 :
123aaaaaaaaaaaaaaaa
*/
fstream fs;
fs.open("test.txt");
char buf[100];
while (true)
{
fs >> buf;
cout << buf << endl;
if (fs.eof())
{
cout << "[End]" << endl;
break;
}
if (fs.fail())
{
cout << "-Fail-" << endl;
fs.clear();
fs.ignore(LLONG_MAX, '\n');
continue;
}
}
fs.close();
char buf[10];
while (true)
{
fs.get(buf, 10);
cout << buf << " : read => " << fs.tellg() << ", write => " << fs.tellp() << endl;
if (fs.eof())
{
cout << "[End]" << endl;
break;
}
if (fs.fail())
{
cout << "- Fail -" << endl;
fs.clear();
fs.ignore(LLONG_MAX, '\n');
continue;
}
}
fs.close();
/*
결과 :
123aaaaaa : read => 9, write => 9
aaaaaaaaa : read => 18, write => 18
aaaaaa : read => 24, write => 24
: read => -1, write => -1
- Fail -
: read => -1, write => -1
[End]
*/
ifstream에 ios_base::out 을 주어서 읽는 행위를 해보려고 했지만 그럴 수 없었다. 이유는 ifstream에 write를 할 수 있는 함수가 없기 때문이다.
파일 스트림에 <<, >>, 조정자(manipulatior)등도 쓸 수 있음.
FILE *fp;
//읽기 전용으로 파일 오픈
fp = fopen("HelloWorld.txt". "r");
//쓰기 전용으로 파일 오픈(파일 없으면 생성)
fp = fopen("HelloWorld.txt". "w+");
//읽기와 쓰기 범용으로 파일 오픈
fp = fopen("HelloWorld.txt". "r+");
//우선 +가 무슨 뜻인지 직관적이지 않다 또한 rw 이렇게 조합까지 되면 더더욱 이해하기 어렵다
//"r"에다 이상한 문자열을 넣어도 컴파일 에러가 발생하지 않는다.
//(객체 이용)
ifstream fin;
fin.open("HelloWorld.txt");
ofstream fout;
fout.open("HelloWorld.txt");
fstream fs;
fs.open("HelloWorld.txt");
open()
각 스트림마다 open()메서드가 있음
fin.open("hellowWorld.txt", ios_base::in | ios_base::binary);
mode flags
네임스페이스
모든 조합이 유효하지 않음
in : 입력
out : 출력
ate : at the end, 마지막으로 파일 포인터 이동
app : 덧 붙이기
trunc : 파일 읽은 다음에 스트림 플러쉬, 파일이 있으면 해당 파일의 모든 데이터를 지우고 개방함.
binary : 이진
ifstream, ofstream, fstream 모두 플래그를 지정하지 않으면 설정되는 디폴트 플래그 있음
is_open()
close()
C/C++ 플래그 비교
"r" : ios_base::in
"w" : ios_base::out
"w" : ios_base::out | ios_base::trunc
"a" : ios_base::out | ios_base::app
"r+" : ios_base::in | ios_base::out
"w+" : ios_base::in | ios_base::out | ios_base::trunc
C++에서 자주 사용되는 파일 모드 조합
// 반드시 호출해주어야함
FILE *fp
fclose(fp);
// 반드시 호출해줄 필요 없음, fin이 메모리 소멸되면서 자동으로 파일 닫아줌
ifstream fin;
fin.close();
FILE* fp;
fp = fopen("HelloWorld.txt", "r+");
if(fp != NULL)
fstream fs;
fs.open("HelloWorld.txt");
if(fs.is_open())
각 스트림마다 close(), is_open() 함수가 있음
FILE* fp;
fp = fopen("HelloWorld.txt", "r");
char ch;
do
{
ch = getc(fp);
printf("%c", ch);
}while(ch != EOF);
fclose(fp);
ifstream fin;
fin.open("HellowWorld.txt");
char ch;
while(true)
{
fin.get(ch);
if(fin.fail())
{
break;
}
cout << ch;
}
fin.close();
get 함수는 한 문자만 입력 받는 함수가 아니다. 문자열을 읽을 수 있으며 getline과 차이점은 get은 \n을 파일 스트림에 그대로 둔다.
어떤 스트림(cin, istringstream)을 넣어도 동일하게 동작
fin.get(ch);// 파일에서 한 글자 읽음, 그전에 \n 만나면 거기까지 출력
fin.getline(buf, 20); // 파일에서 문자 20개를 읽음, 그전에 \n 만나면 거기까지 출력
getline(fin, line); // 파일에서 한 줄을 읽음
fin >> word;// 파일에서 한 단어를 읽음
ifstream fin;
fin.open("HelloWorld.txt");
string line;
//eofbit : false
//failbit : false
while(!fin.eof())
{
//마지막 라인을 읽고나서 eofbit 가 true로 설정됨
getline(fin, line);//읽을떄 마다 파일 포인터가 읽은 문자열 다음위치를 가리킨다.
cout << line << endl;
}
find.close();
//eofbit : false
//failbit : false
while(!fin.eof())
{
//빈 파일이기에 line에 아무것도 안들어간다, 그러나 출력을 한다.
getline(fin, line);
cout << line << endl;
}
//"ABCD 12000"
ifstream fin;
fin.open("HelloWorld.txt");
string name;
float balance;
while(!fin.eof())
{
fin >> name >> balance
cout << name << ": $" << balance << endl;
}
find.close();
//"100 200 300"
ifstream fin;
fin.open("HelloWorld.txt");
float number;
while(!fin.eof())
{
fin >> number;
cout << number << endl;
}
find.close();
//"100 200 300\n"
while(!fin.eof())
{
// 300 읽고 난후 파일 포인터는 \n을 가리키고 있는 상태
fin >> number;
// \n 부터 한문자씩 차례대로 읽는 과정에서 eof가 있다는 것을 확인.
// eof를 읽었기에 eofbit 설정
// \n 도 공백과 같은 구분 문자로서 역할을 한다고 생각하면 된다.
// \n 을 읽을때 숫자가 아니기에 failbit 설정된다.
// number는 아까 읽었던 300을 한번더 출력
cout << number << endl;
}
/*
OUTPUT >
100
200
300
300
*/
//"100 C++ 300"
while(!fin.eof())
{
// 100 읽고 난후 파일 포인터는 C++을 가리킴
fin >> number;
// C++를 읽으면서 파일포인터가 eof 에 도달하지 못함, 왜냐하면 뒤에 공백까지만 읽기 때문에
// eof를 못 읽었기에 eofbit가 설정되지 않음
// C++를 읽을때 숫자가 아니기에 failbit 설정된다.
// number는 아까 읽었던 100을 한번더 출력
cout << number << endl;
}
/*
OUTPUT >
100
100
100
100
:
*/
while(!fin.eof())
{
fin >> number;
if(!fin.fail())// 제대로 읽은 건지 출력
{
cout << number << endl;
}
}
// 그러나 EX 4는 해결하지 못함, 왜?? 파일 포인터가 다음 문자열로 넘어가지 않으니까
while(!fin.eof())
{
fin >> number;
if(fin.fail()) // 제대로 못 읽은 경우 넘어가도록 처리
{
// 상태 원상복구
fin.clear();
// 다음 문자까지 파일 포인터 건너 뜀(다음 문자까지 구분은 ' '으로 지정)
fin.ignore(LLONG_MAX, ' ');
}
else
{
cout << number << endl;
}
}
/*
그런데 \t와 스페이스 둘다 있는 경우는 제대로 동작하지 않음
"100 C++\t300" 이면 C++이후 300 문자열들을 다 버림, \t를 ' '으로 인식하지 않아서
C++\t300채로 버린다.
*/
string trash;
while(!fin.eof())
{
fin >> number;
if(fin.fail())
{
fin.clear();
// 숫자가 아닌 경우 문자열로 읽어버려 trash에다 버리게 된다.
fin >> trash;
}
else
{
cout << number << endl;
}
}
string trash;
while(!fin.eof())
{
fin >> number;
if(fin.fail())
{
//"100 200 C++"
//fin.clear() 위치가 바뀌면 문제가 된다.
fin >> trash;
// C++ 문자열 읽은 다음에 failbit가 설정되어서 파일 포인터가 다음으로 넘어가질 못한다.
// 즉, fin >> 이 정상 동작을 못한다.
//fail bit를 초기화 하기위해 여기서 clear를 하면
//eof bit도 같이 초기화 되어 더 입력을 받기위해 대기
fin.clear();
}
else
{
cout << number << endl;
}
}
FILE* fp;
fp = fopen("HelloWorld", "w");
char line[512];
if(fgets(line, 512, stdin) != NULL)
{
fprintf(fp, "%s\n", line);
}
fclose(fp);
ofstream fout;
fout.open("HellowWorld.txt");
string line;
getline(cin, line);
if(!cin.fail())
{
fout << line << endl;
// "endl은 \n 과 조금 다르다"
// "enel은 뉴 라인 한 다음에 버퍼를 플러시를 한다."
// "fluah()라는 함수가 있다."
// "* 단 C에서는 \n을 만나면 플러시를 한다. "
}
fin.close();
put()
<<
FILE* fp;
fp = fopen("studentRecord.dat", "rb");
if(fp != NULL)
{
Record record;
fread(&record, sizeof(Record), 1(1개 읽어라), fp);
}
fclose(fp);
ifstream fin("studentRecord.dat", ios_bas::in | ios_base::binary);
if(fin.is_open())
{
Recordd record;
fin.read((char*)&record, sizeof(Record));
}
fin.close();
FILE* fp;
fp = fopen("studentRecord.dat", "w");
if(fp != NULL)
{
char buffer[2] = "Pope kim";
fwrite(buffer, 20, 1(1번 써라), fp)
}
fclose(fp);
ofstream fout("studentRecords.dat", ios_base::out | ios_base::binary);
if(fout.is_open())
{
char buffer[20] = "Pope kim";
fout.write(buffer, 20);
}
fout.close();
FILE* fp;
fp = fopen("studentRecords.dat", "w");
if(fp != NULL)
{
if(fseek(fp, 20, SEEK_SET) == 0)
{
// 21번째 위치에서부터 덮어쓰기
}
}
fstream fs("HellowWorld.dat", ios_base::in | ios_bse::out | ios_base::binary)
if(fs.is_open())
{
fs.seekp(20, ios_base::beg);//시작부터 20번째
if(!fs.fail())
{
// 21번째 위치에서부터 덮어쓰기
}
}
탐색(seek) 유형
절대적
상대적
파일 [쓰기] 위치 읽기 및 변경
tellp():쓰기 포인터의 위치를 구함
seekp()
파일 [읽기] 위치 읽기 및 변경
tellg():읽기 포인터의 위치를 구함
seekg()
text.txt
1234567890
1234567890[ ]
| |
beg end
EX
fstream fs;
fs.open("test.txt");
fs.seekg(0, ios_base::end);
fs << "abc";
fs.close();
=> 1234567890abc
fs.seekg(0, ios_base::beg);
=> abc4567890
- EX
fs.seekg(4, ios_base::beg);
=> 1234abc890
beg에서부터 4칸 이동
fs.seekg(4, ios_base::end);
=> 1234567890 abc
fs.seekg(-4, ios_base::end);
=> 123456abc0
fstream fs;
fs.open("test.txt", ios_base::app);
cout << fs.tellg() << endl;
=> 0
fs << "abc";
cout << fs.tellg() << endl;
=> 13
fs.close();
=> 123456789abc
fstream fs;
fs.open("test.txt", ios_base::app | ios_base::ate);
cout << fs.tellg() << endl;
=> 10
fs << "abc";
cout << fs.tellg() << endl;
=> 13
fs.close();
=> 123456789abc
를 getline()과 같이 쓰지 말 것
// 입력:1 \n
// Cheerios
cin >> number; // 1
getline(cin, line);// 위에서 \n이 버퍼에 남아서 line에 \n 넣고 넘어가버림.
cin >> number;
cin >> ws; ==> \n을 버림
getline(cin, line);