차근차근/C

[C++] 파일 입출력에 관한 모든 것

예쁜꽃이피었으면 2014. 7. 28. 14:42

http://yagi815.tistory.com/112


소개


이 강좌는 파일 입출력의 가장 기본적인 내용으로 시작한다. 나중에 더 고급적인 기법을 이용한 약간의 꽁수와 괜찮은 함수에 대해 설명하겠다.

C++ 에 대해 확실히 이해하고 있지 않다면 이 강좌를 봐도 아무런 도움이 되지 않을 것이다.

 

당신의 가장 첫 프로그램

 

먼저 코드를 쓰고 난 후 줄(line) 별로 설명하겠다.

첫번째 프로그램은 파일을 하나 생성하고, 몇가지 문자를 그 곳에 쓰는 일을 한다.

 

#include <fstream>

using namespace std;

 

int main()

{

ofstream SaveFile("cpp-home.txt");

SaveFile << "Hello World, from www.cpp-home.com and Loobian!";

SaveFile.close();

return 0;

}

 

이것 뿐일까? 그렇다. 이 프로그램은 실행한 곳의 디렉토리에서 cpp-home.txt 파일을 생성하고, "Hello World, fromwww.cpp-home.com and Loobian!" 이라는 문자를 저장한다.

이제 각 줄에 대한 설명을 한다면:


#include <fstream> - 파일 입출력을 위한 C++ 함수를 사용하기 위해 필요하다. 이 파일에는 몇가지 클래스가 선언되어 있으며 istream 및 ostream 로 부터 상속받은 ifstreamofstream 그리고 fstream 을 포함한다.

 

ofstream SaveFile(“cpp-home.txt”);

1)     ofstream 은 "출력 파일 흐름(output file stream)" 을 의미한다. 파일을 쓰기위한 흐름(stream)의 핸들을 생성한다.

2)     SaveFile – 이것은 핸들의 이름이다. 좋아하는 아무것이나 줘도 된다!

3)     (“cpp-home.txt”); - 실행한 프로그램의 디렉토리 위치에서 cpp-home.txt 파일을 연다. 파일이 없을 경우 자동으로 만들어 주므로 걱정할 필요 없다.

약간 더 깊이 들어가 보자. 첫째로, ofstream 은 클래스라는 것에 대해 말하고 싶다. 이로인해, ofstream SaveFile(“cpp-home.txt”); 문장은 이 클래스에서 하나의 객체를 생성하게 된다. 인자로 괄호안에 넘기는 것은 사실 생성자(constructor)로 넘어간다. 파일명이 되는 것이다. 정리해보면, ofstream 로부터 클래스를 하나 생성 한 뒤에 만들 파일명을 생성자의 인자로 넘긴 것이다. 다른 방법도 있다. 일단 넘어가고 나중에 보도록 하자.

 

SaveFile << “Hello World, from www.cpp-home.com and Loobian!”; - “<<” 를 어디서 본 것같다. 그렇다,cout << 에서 봤을 것이다. 이 (“<<”) 는 벌써 정의되어 있는 연산자이다. 어쨌거나, 파일에 문자를 쓰는 역할을 하는 줄이다. 전에 말했듯이, SaveFile 은 열린 파일 흐름의 핸들이다. 따라서, 핸들 이름을 쓴 후 << 다음에 따옴표 안의 문자를 쓴 것이다. 만일 문자열 대신에 변수를 쓰고 싶다면 cout << 을 썼던 방법 그대로 하면 된다. 다음과 같이:

SaveFile << variablename;

이것이다!

 

SaveFile.close(); - 열린 흐름(stream)의 사용이 끝났을 경우에는 닫아야 한다. SaveFile 은 ofstream 클래스의 객체인데, 이 (ofstream) 클래스에는 흐름을 닫는 함수가 있다. close() 함수다. 스트림을 닫으려면 그냥 핸들 이름과 점, close() 만 써주면 된다! 
주의: 파일을 한번 닫으면, 다시 열 때까지 더 이상 접근할 수 없다.

 

파일에 쓰기위한 정말 간단한 프로그램이었다. 정말 쉽다! 하지만 아직 배워야 할 여러 과제가 남아 있다.

 

파일 읽기


파일에 어떻게 쓰는지 알아 봤다. 이제 cpp-home.txt 파일이 생겼는데 그걸 읽어서 화면에 뿌려보도록 하자.
먼저, 파일을 읽는 방법이 몇가지 있다는걸 말하고 싶다. (내가 아는 한) 그 모든 방법은 나중에 가르쳐 주도록 하고 지금은 그냥 맘대로 최선의 방법 한가지를 보여 주겠다.

벌써 사용한 것이지만- 코드를 먼저 쓰고나서 자세한 설명을 하겠다.


#include <fstream.h>

 

void main() //여기에서 프로그램이 시작된다

{

       ifstream OpenFile("cpp-home.txt");

 

       char ch;

       while(!OpenFile.eof())

       {

             OpenFile.get(ch);

             cout << ch;

       }

       OpenFile.close();

}

 

첫번째 줄은 뭘 하는건지 이미 알 것이다. 나머지를 설명해 보면,

 

ifstream OpenFile(“cpp-home.txt”) – 이건 약간 더 눈에 잘 들어 올 것 같다! ifstream 은 입력 파일 흐름(input file stream)을 의미한다. 이전 프로그램에서는 출력 파일 흐름(output file stream)을 의미하는 ofstream 이었는데, 파일에 쓰기를 했으므로 출력(output)이 되는 것이다. 하지만 이번 프로그램은 파일에서 읽어들이는데 그것이 바로 입력(input)이 되는 이유이다. 나머지 코드는 쉬울 것이다. OpenFile 은 입력 파일 흐름을 조정하는 ifstream 클래스 객체이다. 그리고, 인자로 들어간 문자열은 파일명이 된다.

파일이 존재하지 않을 경우를 주의해야 하는데, 나중에 그것을 체크하는 방법을 보여 주겠다!

 

char ch; char 형 배열하나를 선언한다. - 다시 생각해 보면, ASCII 문자표에서 하나의 표시만을 가질 수 있는 배열도 있다.

 

while(!OpenFile.eof()) – eof() 함수는 파일의 끝에 도달할 경우 0 이 아닌 값을 돌려 준다. 그로 인해 파일 끝을 읽을 때까지 루프를 돌게 되어 전체 내용을 읽게 되는 것이다.

 

OpenFile.get(ch); - OpenFile 은 ifstream 클래스 객체이다. 이 클래스는 get() 함수를 가지고 있는데, 객체가 살아있는 동안은 이 함수를 사용할 수 있다. get() 함수는 흐름으로 부터 하나의 문자를 가져와서 되돌려 준다. 예제에서는 get() 함수가 하나의 인자(읽은 문자를 저장할 변수명)를 가지고 있다. 따라서, OpenFile.get(ch) 를 호출하면 OpenFile 흐름으로부터 하나의 문자를 읽고, ch 변수에 넘기게 된다.

주의: 이 함수를 두번 호출하면 다음 문자를 읽지만 같은 것은 아니다. 이런 일이 발생하는 이유는 다음에 배우게 될 것이다!

이것이 파일의 끝까지 반복한 이유이다! 반복할 때 마다 한 문자를 ch 에 값을 넘기게 된다.

 

cout <<  ch; - 읽은 문자가 있는 ch 를 표시한다.

 

File.close(); - 파일 흐름을 열었으니 닫아 주어야 한다. 닫으려면 close() 함수를 사용하면 된다.예전의 프로그램과 같이!

주의: 파일을 닫고 난 후에는 다시 열 때까지 더이상 접근할 수 없다.


이것이 끝이다! 이해 했기를 빈다! 이 프로그램을 컴파일하고 실행하면 다음과 같은 결과가 나오게 된다:

“Hello World, from www.cpp-home.com and Loobian!”

 

 

입출력 흐름 관리

이번에는 쓸만한 함수에 대해서 알아 보겠다. 또한 읽기와 쓰기가 동시에 가능하게 파일을 여는 방법을 보여 주겠다. 다른 방법으로 파일을 여는 방법도 함께; 파일이 잘 열렸는지 아닌지도 함께. 자, 보자!

 

지금까지, 하나의 파일을 열어서 읽고 쓰는 것을 봤다. 하지만 다른 방법으로 파일을 열 수도 있다. 다음 방법을 알고있었을 테지만:

 

ifstream OpenFile(“cpp-home.txt”);

 

음, 이것만이 길은 아니다! 이전에 말했듯이, 위의 코드는 ifstream 클래스로부터 객체 하나를 생성한다. 하지만 하나 이상의 인자를 받을 수 있는 여러 생성자가 존재한다. 또한,open() 함수가 같은 일을 할 수 있다. 아래에 open() 함수를 사용해서 같은 일을 하는 예제가 있다.

 

ifstream OpenFile;

OpenFile.open(“cpp-home.txt”);

 

뭐가 다를까? 몇가지 테스트를 해본 결과 차이점은 없었다. 파일 핸들을 만들 때 반드시 파일명을 바로 적어 줄 필요는 없다. 나중에 open 함수를 사용해서 파일명을 줄 수 있다. 하지만 open() 함수의 다른 용도가 있다. 일단 파일을 열고 사용한 후에 다른 파일을 열고자 한다면 open() 함수가 필요하다. 
다음 예제를 보면:

 

#include <fstream.h>

 

void read(ifstream &T) // 함수로 파일 흐름을 넘긴다

{     

// 예전에 봤던 파일을 읽는 법이다

       char ch;

 

       while(!T.eof())

       {

             T.get(ch);

             cout << ch;

       }

      

       cout << endl << "--------" << endl;

}

 

void main()

{

       ifstream T("file1.txt");

       read(T);

       T.close();

 

       T.open("file2.txt");

       read(T);

       T.close();

}

 

문자가 들어있는 file1.txt 와 file2.txt 파일이 존재한다면 내용을 볼 수 있을 것이다. 

이제 
open() 함수나 생성자(같은말이다)에 파일명만 인자로 넘기지 않아도 되는 것을 보겠다.
다음 선언을 살펴보자:

 

ifstream OpenFile(char *filename, int open_mode);

 

You should know that filename is the name of the file (a string). The new here is the open mode. The value of open_modedefines how to be opened the file. Here is a table of the open modes:

 

이름

설명

ios::in

파일을 읽기로 연다

ios::out

파일을 쓰기로 연다

ios::app

All the date you write, is put at the end of the file. It calls ios::out

ios::ate

All the date you write, is put at the end of the file. It does not call ios::out

ios::trunc

파일에 들어있는 이전 내용을 모두 지운다. (파일을 비운다)

ios::nocreate

If the file does not exists, opening it with the open() function gets impossible.

ios::noreplace

파일이 존재하면, open() 함수로 열기 시도를 하고 에러를 리턴한다.

ios::binary

이진 모드로 파일을 연다.


사실 여기 모든 값은 열거형(enum)인 int 상수이다. 하지만 쉽게 기억하기 위해 표에 있는데로 사용하는게 좋겠다.

다음은 열기 모드를 사용하는 예제이다:

#include <fstream.h>

 

void main()

{

       ofstream SaveFile("file1.txt", ios::ate);

 

       SaveFile << "That's new!\\n";

 

       SaveFile.close();

}

 

As you see in the table, using ios::ate will write at the end of the file. If I didn’t use it, the file will be overwritten, but as I use it, I just add text to it. So, if file1.txt has this text:

 

Hi! This is test from www.cpp-home.com!


Running the above code, will add “
That’s new!” to it, so it will look this way:

 

Hi! This is test from www.cpp-home.com!That’s new!

 

If you want to set more than one open mode, just use the OR operator- |. This way:

 

ios::ate | ios::binary

 

I hope you now understand what open modes are!

Now, it’s time to show you something really useful! I bet you didn’t know that you could create a file stream handle, which you can use to read/write file, in the same time! Here is how it works:

 

fstream File(“cpp-home.txt”,ios::in | ios::out);


In fact, that is only the declaration. I will show you a code example, just several lines bellow. But I first want to mention some things you should know.
The code line above, creates a file stream handle, named “
File”. As you know, this is an object from class fstream. When using fstream, you should specify ios::in and ios::out as open modes. This way, you can read from the file, and write in it, in the same time, without creating new file handles. Well, of course, you can only read or write. Then you should use eitherios::in either ios::out, but if you are going to do it this way, why don’t you do it either with ifstream, either with ofstream
?
Here is the code example:

 

#include <fstream.h>

 

void main()
{

       fstream File("test.txt",ios::in | ios::out);

 

       File << "Hi!"; //put “Hi!” in the file

      

       static char str[10]; //when using static, the array is automatically

                             //initialized, and very cell NULLed

       File.seekg(ios::beg); //get back to the beginning of the file

                               //this function is explained a bit later

       File >> str;

       cout << str << endl;

 

       File.close();
}

 

Okay, there are some new things here, so I will explain line by line:

 

fstream File(“test.txt”, ios::in | ios::out); This line, creates an object from class fstream. At the time of execution, the program opens the file test.txt in read/write mode. This means, that you can read from the file, and put data into it, at the same time.

 

File << “Hi!”; - I beg you know what this is!


static char str[10]; This makes a char array with 10 cells. I suppose static may be unfamiliar to you. If so- ignore it. It just initializes the array when at the time of creation.

 

File.seekg(ios::beg); - Okay, I want you to understand what this really do, so I will start with something a bit off-topic, but important.
Remember that? :

while(!OpenFile.eof())

       {

             OpenFile.get(ch);

             cout << ch;

       }


Did you ever wonder what really happens there? Yes or no, I will explain you. This is a while loop, that will loop until you reach the end of the file. But how do the loop know if the end of the file is reached? Well, when you read the file, there is something like an inside-pointer, that shows where you are up to, with the reading (and writing, too). It is like the cursor in Notepad. And every time you call OpenFile.get(ch) it returns the current character to the ch variable, and moves the inside-pointer one character after that, so that the next time this function is called, it will return the next character. And this repeats, until you reach the end of the file.

So, let’s get back to the code line. The function seekg()  will put the inside-pointer to a specific place (specified by you). You can use:

ios::beg  – to put it in the beginning of the file

ios::end  - to put it at the end of the file

Or you can also set the number of characters to go back or after. For example, if you want to go 5 characters back, you should write:

 

File.seekg(-5);

 

If you want to go 40 character after, just write:

 

File.seekg(40);

I also have to mention, that the seekg() function is overloaded, and it can take two parameters, too. The other version is this one:

 

File.seekg(-5,ios::end);

 

In this example, you will be able to read the last 4 characters of the text, because:

1)     You go to the end (ios::end)

2)     You go 5 characters before the end (-5)

Why you will read 4 but not 5 characters? Well, just assume that one is lost, because the last thing in the file is not a character nor white space. It is just position.


You now may be wondering why did I use this function? Well, after I put “Hi!” in the file, the inside-pointer was set after it… at the end of the file. And as I want to read the file, I have nothing to read after the end, so I have to put the inside-pointer at the beginning. And that is exactly what this function does.

 

File >> str; That’s new, too! Well, I believe this line reminds you of cin >> . I fact, it has much to do with it. This line reads one word from the file, and puts it into the specified array.
For example, if the file has this text:

 

Hi! Do you know me?

Using File >> str, will put just “Hi!” to the str array. You should have noticed, that it actually reads until it meets a white space.

And as what I put in the file was “Hi!” I don’t need to do a while loop, that takes more time to code. That’s why I used this way. By the way, in the while loop for reading, that I used so far, the program reads the file, char by char. But you can read it word by word, this way:

 

       char str[30]; //the word can’t be more than 30 characters long

while(!OpenFile.eof())

       {

             OpenFile >> str;

             cout << str;

       }


You can also read it line by line, this way:

 

char line[100]; //a whole line will be stored here
while(!OpenFile.eof())
{

OpenFile.getline(line,100); //where 100 is the size of the array

cout << line << endl;
}

 

You now might be wondering which way to use? Well, I’d recommend you to use the line-by-line one, or the first that I mentioned- the one which reads char-by-char. The one that reads word-by-word is not good idea, because it won’t read the new line. So if you have new line in the file, it will not display it as a new line, but will append the text to the existing one. But using getline() or get() will show you the file, just as it is!

 


Now, I will show you how to check if the file opening was successful or not. In fact, there are few good ways to check for that, and I will mention them. Notice that where there is X, it can be either “o”, either “i” either nothing (it will then be fstream object).


Example 1: The most usual way

Xfstream File(“cpp-home.txt”);

if (!File)
{

cout << “Error opening the file! Aborting…\\n”;

exit(1);
}

 

Example 2: If the file is created, return an error

 

ofstream File("unexisting.txt", ios::nocreate);

 

if(!File)

{

cout << “Error opening the file! Aborting…\\n”;

exit(1);

}


Example 3: Using the fail() function

ofstream File("filer.txt", ios::nocreate);

 

if(File.fail())

{

cout << “Error opening the file! Aborting…\\n”;

exit(1);

}

The new in 
Example 3, is the fail() function. It returns a nonzero value if any I/O error (not end of file) has occurred.

 

I would also like to mention about something , that I find to be very useful! For example, if you have created a file stream, but you haven’t opened a file. This way:

 

ifstream File; //it could also be ofstream


This way, we have a handle, but we still have not opened the file. If you want to open it later, it can be done with the 
open()function, which I already covered in this tutorial. But if anywhere in your program, you need to know if currently there is an opened file, you can check it with the function is_open(). It retunrs 0 (false) if a file is not opened, and 1 (true) if there is an opened file. For example:

 

ofstream File1;

File1.open("file1.txt");

cout << File1.is_open() << endl;


The code above, will return 1, as we open a file (on line 2). But the code bellow will return 0, because we don’t open a file, but just create a file stream handle:

 

ofstream File1;

cout << File1.is_open() << endl;


Okay, enough on this topic.

 

입출력 상태확인- 플래그

 

I won’t be explaining what flags are. But even if you don’t know about them, reading this chapter to the end may give you some idea, and I believe you will understand the theory. Even so, if you don’t know about the flags in C++, I recommend you to find some reading on this subject.
Okay, let’s start!


The Input/Output  system in C++, holds information about the result of every I/O operation. The current status is kept in an object from type 
io_state, which is an enumerated type (just like open_mode)  that has the following values:

godbit

No errors.

eofbit

End of file has been reached

failbit

Non-fatal I/O error

badbit

Fatal I/O error

 

There are two ways, to receive information about the I/O status. One of them is by calling the function rdstate(). It returns the current status of the error-flags (the above mentioned). For example, the rdstate() function will return goodbit if there were no errors.

The other way to check the I/O status is by using any of the following function:

 

bool bad();

bool eof(); //remember this one? “Read until the end of the file has been reached!”

bool fail(); //and this one, too… Check if the file opening was successfull

bool good();

 

The function bad() returns true, if the badbit flag is up. The fail() function returns true if the failbit flag is up. The good()function returns true if there were no errors (the goodbit flag is up). And the eof() function returns true if the end of the file has been reached (the eofbit flag is up).

If an error occurred, you will have to clear it if you want your program to continue properly. To do so, use the clear()function, which takes one parameter. The parameter should be the flag you want to put to be the current status. If you want your program to continue “on clear”, just put ios::goodbit as parameter. But notice that the clear() function can take any flag as parameter. You will see that in the code examples bellow.

I will now show you some example code that will confirm your knowledge.


Example 1: Simple status check

          

           //Replace FileStream with the name of the file stream handle

       if(FileStream.rdstate() == ios::eofbit)

             cout << "End of file!\\n";

       if(FileStream.rdstate() == ios::badbit)

             cout << "Fatal I/O error!\\n";

       if(FileStream.rdstate() == ios::failbit)

             cout << "Non-fatal I/O error!\\n";

       if(FileStream.rdstate() == ios::goodbit)

             cout << "No errors!\\n";



Example 2: The clear() function

 

#include <fstream.h>

 

void main()

{

       ofstream File1("file2.txt"); //create file2.txt

       File1.close();

 

       //this bellow, will return error, because I use the ios::noreplace

       //open_mode, which returns error if the file already exists.

       ofstream Test("file2.txt",ios::noreplace);

 

       //The error that the last line returned is ios::failbit, so let’s show it

       if(Test.rdstate() == ios::failbit)

             cout << "Error...!\\n";

 

       Test.clear(ios::goodbit); //set the current status to ios::goodbit

 

       if(Test.rdstate() == ios::goodbit) //check if it was set correctly

             cout << "Fine!\\n";

 

       Test.clear(ios::eofbit); //set it to ios::eofbit. Useless.

 

       if(Test.rdstate() == ios::eofbit) //and check again if it is this flag indeed

             cout << "EOF!\\n";

 

       Test.close();

      

}

 

Instead using flags, you can use a function that actually does the same- checks if specific flag is up. The functions were mentioned before, so I won’t mention them again. If you are not sure how to use them, just check out the place of the tutorial, where I showed few ways to check if file opening was successful or not. There, I used the fail() function.

 


이진 파일과 주고받기

 

Although, the files with formatted text (all that I talked about so far) are very useful, sometimes you may need to work with unformatted files- binary files. They have the same look as your program itself, and it is much different from what comes after using the << and >> operators. The functions that give you the possibility to write/read unformatted files are get()and put(). To read a byte, you can use get() and to write a byte, use put().  You should remember of get()… I have already used it before. You wonder why even using it, the file looks formatted? Well, it is because I used the << and >> operators, I suppose.
get() and put() both take one parameter- a char
 variable or character. 
If you want to read/write whole blocks of data, then you can use the 
read() and write() functions. Their prototypes are:

 

istream &read(char *buf, streamsize num);

ostream &write(const char *buf, streamsize num);


For the 
read() function, buf should be an array of chars, where the read block of data will be put. For the write() function, bufis an array of chars, where is the data you want to save in the file. For the both functions, num is a number, that defines the amount of data (in symbols) to be read/written.

If you reach the end of the file, before you have read “
num” symbols, you can see how many symbols were read by calling the function gcount()
. This function returns the number of read symbols for the last unformatted input operation.
And before going to the code examples, I have to add, that if you want to open a file for binary read/write, you should pass
ios::binary
 as an open mode.

Now, let me give you some code examples, so that you can see how stuff works.


Example 1: Using get() and put()

 

#include <fstream.h>

 

void main()

{

       fstream File("test_file.txt",ios::out | ios::in | ios::binary);

 

       char ch;

       ch='o';

 

       File.put(ch); //put the content of ch to the file

 

       File.seekg(ios::beg); //go to the beginning of the file

 

       File.get(ch); //read one character

 

       cout << ch << endl; //display it

 

       File.close();

}

 

Example 2: Using read() and write()

 

#include <fstream.h>

#include <string.h>

 

void main()

{

       fstream File("test_file.txt",ios::out | ios::in | ios::binary);

 

       char arr[13];

       strcpy(arr,"Hello World!"); //put Hello World! into the array

 

       File.write(arr,5); //put the first 5 symbols into the file- "Hello"

 

       File.seekg(ios::beg); //go to the beginning of the file

 

       static char read_array[10]; //I will put the read data, here

 

       File.read(read_array,3); //read the first 3 symbols- "Hel"

 

       cout << read_array << endl; //display them   

 

       File.close();

}

 

 

유용한 몇가지 함수들

 

tellg() – Retunrs an int type, that shows the current position of the inside-pointer. This one works only when you read a file. Example:

 

#include <fstream.h>

 

void main()

{

       //if we have "Hello" in test_file.txt

       ifstream File("test_file.txt");

 

       char arr[10];

 

       File.read(arr,10);

      

       //this should return 5, as Hello is 5 characters long

       cout << File.tellg() << endl;

 

       File.close();

}

 

tellp() – The same as tellg() but used when we write in a file. To summarize: when we read a file, and we want to get the current position of the inside-pointer, we should use tellg(). When we write in a file, and we want to get the current position of the inside-pointer, we should use tellp(). I won’t show a code example for tellp() as it works absolutely the same way astellg().

 

seekp() – Remember seekg()? I used it, when I was reading a file, and I wanted to go to specified position. seekp() is the same, but it is used when you write in a file. For example, if I read a file, and I want to get 3 characters back from the current position, I should call FileHandle.seekg(-3). But if I write in a file, and for example, I want to overwrite the last 5 characters, I have to go back 5 characters. Then, I should use FileHandle.seekp(-5).

 

ignore() – Used when reading a file. If you want to ignore certain amount of characters, just use this function. In fact, you can use seekg() instead, but the ignore() function has one advantage- you can specify a delimiter rule, where the ignore()function will stop. The prototype is:

 

istream& ignore( int nCount, delimiter );

 

Where nCount is the amount of characters to be ignored and delimiter is what its name says. It can be EOF if you want to stop at the end of the file. This way, this function is the same as seekg(). But it can also be ‘\\n’ for example, which will stop on the first new line. Here is example:

 

#include <fstream.h>

 

void main()

{

       //if we have "Hello World" in test_file.txt

       ifstream File("test_file.txt");

 

       static char arr[10];

 

       //stop on the 6th symbol, if you don't meet "l"

       //in case you meet "l"- stop there

       File.ignore(6,'l');

 

       File.read(arr,10);

 

       cout << arr << endl; //it should display "lo World!"

 

       File.close();

 

}

 

getline() – I have already mentioned about this one. But there is something I didn’t tell you about. This function can be used to read line-by-line, but it can be set to stop reading if it met a certain symbol. Here is how you should pass the parameters to it:

 

getline(array,array_size,delim);


And here is a code example:

 

#include <fstream.h>

 

void main()

{

       //if we have "Hello World" in test_file.txt

       ifstream File("test_file.txt");

 

       static char arr[10];

 

       /*read, until one of these happens:

             1) You have read 10

             2) You met the letter "o"

             3) There is new line

       */

       File.getline(arr,10,'o');

 

       cout << arr << endl; //it should display "Hell"

       File.close();

}

 

peek() – This function will return the next character from an input file stream, but it won’t move the inside-pointer. I hope you remember, that get() for example, returns the next character in the stream, and after that, it moves the inside-pointer, so that the next time you call the get() function, it will return the next character, but not the same one. Well, using peek() will return a character, but it won’t move the cursor. So, if you call the peek() function, two times in succession, it will return a same character. Consider the following code example:

 

#include <fstream.h>

 

void main()

{

       //if we have "Hello World" in test_file.txt

       ifstream File("test_file.txt");

 

       char ch;

 

       File.get(ch);

       cout << ch << endl; //should display "H"

 

       cout <<      <;/SPAN>char(File.peek()) << endl; //should display "e"

       cout <<      char(File.peek()) << endl; //should display "e" again

 

       File.get(ch);

       cout << ch << endl; //should display "e" again


       File.close();

      

}

 

And by the way, I forgot to mention- the peek() function actually returns the ASCII code of the char, but not the char itself. So, if you want to see the character itself, you have to call it the way I did, in the example.

 


_unlink() – Deletes a file. Include 
io.h in your program, if you are going to use this function. Here is a code example:

 

#include <fstream.h>

#include <io.h>

 

void main()

{

       ofstream File;

 

       File.open("delete_test.txt"); //creates the file

       File.close();

 

       _unlink("delete_test.txt"); //deletes the file

 

       //tries to open the file, but if it does not exists

       //the function will rreturn error ios::failbit

       File.open("delete_test.txt",ios::nocreate);

 

       //see if it returned it

       if(File.rdstate() == ios::failbit)

             cout << "Error...!\\n"; //yup,it did


       
File.close();

 

}

 

putback() – This function will return the last read character, and will move the inside-pointer, one with –1 char. In other words, if you use get() to read a char, then use putback(), it will show you the same character, but it will set the inside-pointer with –1 char, so the next time you call get() again, it will again show you the same character. Here is a code example:

 

#include <fstream.h>

 

void main()

{

       //test_file.txt should have this text- "Hello World"

       ifstream File("test_file.txt");

      

       char ch;

 

       File.get(ch);

 

       cout << ch << endl; //it will display "H"

 

       File.putback(ch);

       cout << ch << endl; //it will again display "H"

      

       File.get(ch);

       cout << ch << endl; //it will display "H" again

 

       File.close();

}

 

flush() – When dealing with the output file stream, the date you save in the file, is not actually immediately saved in it. There is a buffer, where it is kept, and when the buffer gets filled, then the data is put in the real file (on your disk). Then the buffer is emptied, and so on. 
But if you want to save the data from the buffer, even if the buffer is still not full, use the 
flush() function. Just call it this way-FileHandle.flush()
. And the data from the buffer will be put in the physical file, and the buffer will be emptied.
And something in addition (advanced)- The 
flush() function calls the sync() function of the associated streambuf. (The last sentence is from MSDN).



마치며

 

Well, I hope you can now do your File I/O programs! I covered everything I remembered of! I think it is more than enough for most of you! Even so, there are things I didn’t cover… but things I think you will never need. So, if you need even more advanced information on specific topic, search the web. Try google.com for example! But don’t ask me! I won’t answer any e-mails, asking me how to do certain program or else.


If you liked this tutorial, or not, I would be very happy to see your comments, so feel free to drop me a line at loobian@cpp-home.com

For more C++ tutorials, visit www.cpp-home.com

반응형