2012年2月20日 星期一

C++ File I/O


Class/Template Descriptions

basic_ifstream<>    class template derived from basic_istream<>. Defines file streams used for input.

    ifstream    basic_ifstream class for char type
    wifstream    basic_ifstream class for wchar type


basic_ofstream<>    class template derived from basic_ostream<>. Defines file streams used for output.

    ofstream    basic_ofstream class for char type
    wofstream    basic_ofstream class for wchar type


basic_fstream<>    class template derived from basic_iostream<>. Defines file streams used for both input and output.

    fstream    basic_fstream class for char type
    wfstream    basic_fstream class for wchar type

basic_ifstream<> members

basic_ifstream();

explicit basic_ifstream(const char* filename, ios_base::openmode mode = ios_base::in);

void close();

bool is_open();

void open(const char* filename, ios_base::openmode mode = ios_base::in);

basic_ofstream<> members

basic_ofstream();

explicit basic_ofstream(const char* filename, ios_base::openmode mode = ios_base::out);

void close();

bool is_open();

void open(const char* filename, ios_base::openmode mode = ios_base::out);

basic_fstream<> members

basic_fstream();

explicit
basic_fstream(const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out);

void close();

bool is_open();

void open(const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out);

Example 8-9 - Simple File I/O

1      // File: ex8-9.cpp
2     
3      #include <iostream>
4      #include <fstream>
5      #include <cstdlib>
6      using namespace std;
7     
8      int main(void)
9      {
10          ifstream f1("ex8-9.cpp");
11          ifstream f2("nofile");
12         
13          ofstream f3("file.one");
14          fstream f4("iofile");
15         
16          char buff[80];
17         
18          if (!f1) {
19              cout << "Hey, I can't find the \"ex8-9.cpp\" file\n";
20              exit(1);
21          }
22     
23          cout << boolalpha;  // turn on "true"/"false" for cout's bools
24     
25          cout << "f2.rdstate()=" << f2.rdstate() << endl;
26          cout << "f2.fail()=" << f2.fail() << endl;
27          cout << "f2.bad()=" << f2.bad() << endl;
28          if (f2.fail())
29              cout << "Hey, I can't find \"nofile\", but who cares\n";
30          if (f3)
31              cout << "Hey, I've decided to create a \"file.one\" file\n";
32     
33          f1 >> buff;
34          cout << buff << endl;
35          f3 << "Have a nice day\n" << endl;
36     
37          // did f4 get opened?
38          cout << "f4.is_open()=" << f4.is_open()<<endl;
39          cout << "f4.good()=" << f4.good()<<endl;
40          cout << "f4.bad()=" << f4.bad()<<endl;
41          cout << "f4.fail()=" << f4.fail()<<endl;
42         
43          // try to write using the f4 stream
44          f4 << buff << endl;
45     
46          // recheck f4's status
47          cout << "f4.is_open()=" << f4.is_open()<<endl;
48          cout << "f4.good()=" << f4.good()<<endl;
49          cout << "f4.bad()=" << f4.bad()<<endl;
50          cout << "f4.fail()=" << f4.fail()<<endl;
51          return 0;
52      }


******  Output  - MS Visual C++ 2008 ******

f2.rdstate()=2
f2.fail()=true
f2.bad()=false
Hey, I can't find "nofile", but who cares
Hey, I've decided to create a "file.one" file
//
f4.is_open()=false
f4.good()=false
f4.bad()=false
f4.fail()=true
f4.is_open()=false
f4.good()=false
f4.bad()=true
f4.fail()=true

******  Output  - gnu version 4.32b ******

f2.rdstate()=4
f2.fail()=true
f2.bad()=false
Hey, I can't find "nofile", but who cares
Hey, I've decided to create a "file.one" file
//
f4.is_open()=false
f4.good()=false
f4.bad()=false
f4.fail()=true
f4.is_open()=false
f4.good()=false
f4.bad()=false
f4.fail()=true

More I/O Members and Types
ios_base class
typedefs
typedef T3 openmode;       

constants
Open mode constants
These constants are used to assign a value to an openmode value. They represent the mode for opening a stream.

app        position to the end of the stream before each write operation.
ate        position to the end of the stream when the stream is opened.
binary        open the stream in binary mode (newlines are 1 byte).
in        open for input.
out        open for output
trunc        delete an existing file when opening.

Positioning constants
These constants are used to assign a value to a seekdir value. They used for relative positioning in a file stream with the seekg() and seekp() functions.

beg        position is relative to the beginning of a file stream.
cur        position is relative to the current position in a file stream.
end        position is relative to the end of a file stream.

More basic_istream members

istream& seekg(ios_base::pos_type pos);    positions to the location indicated by pos in a file stream.  pos_type is the type returned by the tellg() function.

istream& seekg(ios_base::pos_type pos, ios_base::seekdir dir);
    seeks to the position pos characters from dir in a file stream.

pos_type tellg();    returns the character position in the file stream. If the stream state is non-zero, then the function returns pos_type (-1).

More basic_ostream members

ostream& seekp(ios_base::pos_type pos);    positions to the location indicated by pos in a file stream.  pos_type is the type returned by the tellp() function.

ostream& seekp(ios_base::pos_type pos, ios_base::seekdir dir);
    seeks to the position pos characters from dir in a file stream.

pos_type tellp();    returns the character position in the file stream.  If the stream state is non-zero, then the function returns pos_type (-1).

Example 8-10 – File I/O – positioning in a file

1      // File ex8-10.cpp - file I/O
2     
3      #include <fstream>
4      #include <iostream>
5      #include <cstdlib>
6      #include <cstring>
7      using namespace std;
8     
9      int main()
10      {
11          int ch, i;
12     
13          // Open a file for output
14          ofstream fout("da_file");
15         
16          // Check file open
17          if (!fout) {
18              cerr << "I can't open \"da_file\"\n";
19              exit(EXIT_FAILURE);        // EXIT_FAILURE signifies failure
20          }
21     
22          // Write 4 lines into the file
23          fout << "Have a nice day\n";
24          fout << 7 << endl;
25          fout << 3.14159 << endl;
26          fout << hex << 123 << ' ' << oct << 123 << endl;
27         
28          // Close the file
29          fout.close();
30         
31          // Open the file for input
32          ifstream fin("da_file");
33         
34          // Check input file open
35          if (!fin) {
36              cerr << "I can't open \"da_file\"\n";
37              exit(EXIT_FAILURE);
38          }
39         
40          char buff[80];
41     
42          // Read each line from the file
43          while (!fin.getline(buff,80).eof()) {
44              // Print the length of the line and its contents
45              cout << strlen(buff) << '\t' << buff << endl;
46          }
47         
48          // Print the current position in the file
49          cout << fin.tellg() << endl;
50         
51          // Move to byte 7 (the 8th byte) in the file
52          fin.seekg(7,ios_base::beg);
53         
54          // Print the current position in the file
55          cout << fin.tellg() << endl;
56     
57          // Set the boooalpha flag for cout
58          cout.setf(ios_base::boolalpha);
59         
60          // Print the file's stream state and state bits
61          cout << "fin.rdstate()=" << fin.rdstate();
62          cout << " fin.bad()=" << fin.bad();
63          cout << " fin.fail()=" << fin.fail();
64          cout << " fin.eof()=" << fin.eof() <<endl;
65         
66          // Clear the stream state
67          fin.clear();
68         
69          // Print the file's stream state and state bits
70          cout << "fin.rdstate()=" << fin.rdstate();
71          cout << " fin.bad()=" << fin.bad();
72          cout << " fin.fail()=" << fin.fail();
73          cout << " fin.eof()=" << fin.eof() <<endl;
74         
75          // Move to byte 7 (the 8th byte) in the file
76          fin.seekg(7,ios_base::beg);
77         
78          // Print the current position in the file
79          cout << fin.tellg() << endl;
80         
81          // Read the next "word" from the file
82          fin >> buff;
83         
84          // Print the "word"
85          cout << buff << endl;
86         
87          // Print the current position in the file
88          cout << fin.tellg() << endl;
89         
90          // Read the next 10 characters
91          for (i = 0; i < 10; i++) {
92              ch = fin.get();
93              // Print counter, char (as int), char, and stream position
94              cout << i << '\t' << ch << '\t' << (char) ch << '\t'
95                  << fin.tellg() << endl;
96          }
97     
98          return 0;
99      }


******  Output (MS Visual C++ 2008)  ******

15      Have a nice day
1       7
7       3.14159
6       7b 173
-1
37
fin.rdstate()=0 fin.bad()=false fin.fail()=false fin.eof()=false
fin.rdstate()=0 fin.bad()=false fin.fail()=false fin.eof()=false
7
nice
11
0       32              12
1       100     d       13
2       97      a       14
3       121     y       15
4       10
        17
5       55      7       18
6       10
        20
7       51      3       21
8       46      .       22
9       49      1       23

******  Output (GNU 4.32b)  ******

15    Have a nice day
1    7
7    3.14159
6    7b 173
-1
-1
fin.rdstate()=6 fin.bad()=false fin.fail()=true fin.eof()=true
fin.rdstate()=0 fin.bad()=false fin.fail()=false fin.eof()=false
7
nice
11
0    32         12
1    100    d    13
2    97    a    14
3    121    y    15
4    10   
    16
5    55    7    17
6    10   
    18
7    51    3    19
8    46    .    20
9    49    1    21

What's the difference between the two outputs?  Why?

Example 8-11 - File I/O – positioning, modes, and stream state

1      // File ex8-ll.cpp – positioning, modes, and stream state
2     
3      #include <fstream>
4      #include <iostream>
5      #include <cstdlib>
6      using namespace std;
7     
8      void print_file(istream&);
9     
10      int main() {
11     
12          // Declare and open an output file stream
13          ofstream fout("da_file");
14         
15          // Check the file open
16          if (!fout) {
17              cerr << "I can't open \"da_file\"\n";
18              exit (EXIT_FAILURE);
19          }
20         
21          // write 3 lines into a new file
22          fout << "Have a nice day.\n";   
23          fout << "Have a great day.\n";
24          fout << "Have a totally excellent day.\n";
25         
26          // close the file                Why?
27          fout.close();                       
28         
29          // re-open the file as an fstream object for input and output
30          fstream finout("da_file",ios_base::in|ios_base::out);
31         
32          print_file(finout);
33         
34          // clear the EOF bit
35          finout.clear();
36         
37          // position to byte 7 in the file
38          finout.seekp(7,ios::beg);
39         
40          // Are the get and put pointers the same?
41          cout<< "finout.tellg()=" << finout.tellg()<< endl;
42          cout<< "finout.tellp()=" << finout.tellp()<< endl;
43         
44          // replace "nice" with "fine"
45          finout<< "fine";
46         
47          // Are the get and put pointers still the same?
48          cout<< "finout.tellg()="<< finout.tellg()<< endl;
49          cout << "finout.tellp()=" << finout.tellp () << endl;
50         
51          print_file(finout);
52         
53          // close the file
54          finout.close();
55         
56          // reopen the file in input/output/binary mode
57          finout.open("da_file",ios_base::in|ios_base::out|ios::binary);
58         
59          // write hey into the file
60          finout<< "hey";
61         
62          print_file(finout);
63         
64          // try again to write hey into the file
65          finout.seekp(0,ios::beg);
66          finout<< "hey";
67          print_file(finout);
68     
69          // try app mode
70          finout.clear();
71          finout.close();
72          finout.open("da_file",ios_base::in|ios_base::out|ios::app);
73          finout<< "hey";
74     
75          print_file(finout);
76     
77          return 0;
78      }
79     
80     
81      void print_file(istream& file)
82      {
83          cout<< "file.rdstate="<< file.rdstate() << endl;
84          char buffer[80];
85          file.seekg(0,ios::beg);
86          while (file.getline(buffer,sizeof(buffer))) {
87              cout<< buffer << endl;
88          }
89          cout << endl;
90      }


******  Output  (MS Visual C++ 2008)  ******

file.rdstate=0                        (32)
Have a nice day.
Have a great day.
Have a totally excellent day.

finout.tellg()=7                        (41)
finout.tellp()=7                        (42)
finout.tellg()=11                    (48)
finout.tellp()=11                    (49)
file.rdstate=0                        (51)
Have a fine day.
Have a great day.
Have a totally excellent day.

file.rdstate=7                        (62)
Have a fine day.
Have a great day.
Have a totally excellent day.

file.rdstate=7                        (67)

file.rdstate=0                        (75)
Have a fine day.
Have a great day.
Have a totally excellent day.
hey


******  Output  (GNU g++ 4.32)  ******

file.rdstate=0
Have a nice day.
Have a great day.
Have a totally excellent day.

finout.tellg()=7
finout.tellp()=7
finout.tellg()=11
finout.tellp()=11
file.rdstate=0                        (51)
Have a fine day.
Have a great day.
Have a totally excellent day.

file.rdstate=0                        (62)
heye a fine day.
Have a great day.
Have a totally excellent day.

file.rdstate=6                        (67)

file.rdstate=0                        (75)
heye a fine day.
Have a great day.
Have a totally excellent day.
hey

The following example illustrates binary file I/O. The example is a bit hokey, but it demonstrates input-output techniques that might be useful in a database application.

Example 8-12 – File I/O – read() and write()

1      // File: ex8-12.cpp - File I/O read() and write()
2     
3      #include <fstream>
4      #include <iostream>
5      #include <iomanip>
6      #include <cstdlib>
7      #include <cstring>
8      #include <string>
9      using namespace std;
10     
11      class Employee
12      {
13      public:
14          Employee() : age(0), salary(0.f) {}
15      private:
16          char empno[8];
17          char name[32];
18          unsigned short age;
19          float salary;
20          friend istream& operator>>(istream&, Employee&);
21          friend ostream& operator<<(ostream&, const Employee&);
22      };
23     
24      istream& operator>>(istream& in, Employee& E)
25      {
26          in >> E.empno >> E.name >> E.age >> E.salary;
27          return in;
28      }
29     
30      ostream& operator<<(ostream& out, const Employee& E)
31      {
32          out << setprecision(2) << fixed << showpoint << left;
33          out << setw(8) << E.empno
34              << setw(13) << E.name
35              << right << setw(3) << E.age
36              << setw(10) << E.salary;
37          return out;
38      }
39      class EmployeeFile
40      {
41      public:   
42          EmployeeFile(string filename = "empfile");
43          void print();                      // Why isn’t this const?
44          void open_for_read_write();
45          void close() { File.close(); }
46          bool operator!() const { return !File.rdstate(); }
47      private:
48          string Filename;
49          fstream File;
50          friend EmployeeFile& operator>>(EmployeeFile&, Employee&);
51          friend EmployeeFile& operator<<(EmployeeFile&, const Employee&);
52      };
53     
54      // constructor opens file in output/binary mode
55      EmployeeFile::EmployeeFile(string filename)
56      : Filename(filename), File(filename.c_str(),ios::out|ios::binary)
57      {
58      }
59     
60      void EmployeeFile::print()
61      {
62          Employee temp;
63     
64          // position to the beginning of the file
65          File.seekg(0,ios_base::beg);
66     
67          // read data from the file and print out each Employee record
68          while (!(*this>>temp)) {
69              cout << temp << endl;
70          }
71     
72          // clear the File stream state (after reading EOF)
73          File.clear();
74      }
75     
76      void EmployeeFile::open_for_read_write()
77      {
78          File.open(Filename.c_str(),ios::in | ios::out | ios::binary);   
79     
80          if (File.fail() ) {
81            cerr << "Unable to open Employee file: " << Filename << endl;
82            exit(-1);
83          }
84      }
85     
86      EmployeeFile& operator>>(EmployeeFile& EF, Employee& E)
87      {
88          EF.File.read((char*) &E, sizeof E);
89          return EF;
90      }
91      EmployeeFile& operator<<(EmployeeFile& EF, const Employee& E)
92      {
93          EF.File.write((char*) &E, sizeof E);
94          return EF;
95      }
96     
97      int main()
98      {
99          Employee temp;
100          EmployeeFile EmpFile("employee.dat");
101         
102          for (int i = 0; i<4; ++i) {
103              cout << "Enter empno name age salary\n";
104              cin >> temp;
105              EmpFile << temp;
106          }
107     
108          // close the file and reopen it in read-write mode
109          EmpFile.close();
110          EmpFile.open_for_read_write();
111     
112          EmpFile.print();
113          return 0;
114      }


******  Sample Run  ******

Enter empno name age salary
654321 Joe 35 80000
Enter empno name age salary
642731 Jim 55 85000
Enter empno name age salary
615787 Helen 60 90000
Enter empno name age salary
J00787 Susan 47 50000
654321  Joe           35  80000.00
642731  Jim           55  85000.00
615787  Helen         60  90000.00
J00787  Susan         47  50000.00

What is the purpose of the char* cast in the file.read() above?

Why is the EmployeeFile File stream opened by the constructor in write mode, then later closed and re-opened in read-write mode?

Example 8-13 - A DOS grep command

The following example is used to create a grep command for DOS. The UNIX grep command is used to search a file, or a list of files for the existence of a desired target string. This example was written for DOS, not UNIX. It demonstrates conditional compilation to allow for compiler differences.

After the program listing, sample compile commands are demonstrated and there is a note about executing the program under Windows XP.

1      // File: ex8-13.cpp - A grep command for DOS
2     
3      #include <fstream>
4      #include <iostream>
5      #include <cstdlib>
6      #include <cstring>
7      using namespace std;
8     
9      // The macro __GNUG__ is set for GNU C++
10      #ifdef __GNUG__
11      #include <unistd.h>        // for access()
12      #else
13      #include <io.h>         // for _access()
14      #endif
15     
16      int main(int argc, char* argv[])
17      {
18          char        filename[64],
19                      buffer[1024],
20                      command[128],
21                      tempFilename[9];
22          int            lineno,   
23                      hits = 0,
24                      files = 0,
25                      system_command_status;
26          ifstream    fin1,
27                      fin2;
28     
29          // Check command-line syntax
30          if (argc != 3) {
31              cerr << "Syntax error\ngrep [target text] [target file(s)]
32                   \n";
33              exit (-1);
34          }
35         
36          // create a temporary file to hold the filenames to be searched
37          strcpy(tempFilename,"tempa");        // first possible filename
38         
39          // The access() or _access() functions are used to status the
40           // existence of a file
41         
42          // If you're not using a GNU C++ compiler, use _access()
43      #ifdef __GNUG__
44          while (access(tempFilename,0) == 0 && tempFilename[4] <= 'z')
45          // If you're not using a GNU C++ compiler, use _access()
46      #else
47          while (_access(tempFilename,0) == 0 && tempFilename[4] <= 'z')
48      #endif
49              tempFilename[4]++;
50     
51          // If you've tried all filenames from "tempa" to "tempz",
52           // then give up
53          if (tempFilename[4] > 'z') {
54              cerr << "Unable to create a temp* file.  Please cleanup\n";
55              exit (-2);
56          }
57     
58          // Create the command:  "dir /b [filename(s)] > [tempfilename]
59          strcpy(command,"dir /b ");
60          strcat(command,argv[2]);
61          strcat(command," > ");
62          strcat(command,tempFilename);
63     
64          // system() allows you to issue operating system commands
65          system_command_status = system(command);
66     
67          // check the status of the system command
68          if (system_command_status == -1) {
69              cerr << "Error with system command: " << command << endl;
70              exit(-3);
71          }
72         
73          // open temporary file (containing names of files to be searched)
74          fin1.open(tempFilename);
75         
76          // Make sure the tempFilename is not empty
77          if (fin1.peek() == EOF) {
78              cerr << "Error: target file(s) do(es) not exist, dummy\n";
79              exit (-4);
80          }
81         
82          // for each file in tempFilename, search for the target string
83          while (fin1.getline(filename,sizeof(filename))) {
84     
85              // open the next file to be searched
86              fin2.open(filename);
87     
88              // increment file count
89              files++;
90     
91              // initialize line counter
92              lineno = 0;
93     
94              // clear errors in fin2 stream
95              fin2.clear();
96     
97              // position at the beginning of the file to be searched
98              fin2.seekg(0L, ios:: beg);
99     
100              // read each line from the file into buffer
101              while (fin2.getline(buffer,sizeof(buffer))) {
102     
103                  // increment line counter
104                  lineno++;
105     
106                  // does buffer contains the target string?
107                  if (strstr(buffer,argv[1])) {
108     
109                      // If so, increment hit counter
110                      hits++;
111     
112                      // display filename, line count, contents of line
113                      cout << filename << '[' << lineno << "] "
114                            << buffer << '\n';
115                  }
116              }
117     
118              // close the file to be searched
119              fin2.close();
120          }
121     
122          // close the temporary file
123          fin1.close();
124     
125          // Print summary information
126          cout << "Found " << hits << " occurrence(s) in " << files
127            << " file(s)\n";
128     
129          // create the DOS command to erase the tempFilename
130          strcpy(command,"erase ");
131          strcat(command,tempFilename);
132     
133          // Issue system erase command
134          system_command_status = system(command);
135     
136          // status system command
137          if (system_command_status == -1) {
138              cerr << "Error with system command: " << command << endl;
139              exit(-5);
140          }
141     
142          return 0;
143      }

沒有留言:

張貼留言