1. Trang chủ
  2. » Giáo Dục - Đào Tạo

All about File I/O in C++ ppsx

13 476 18
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 13
Dung lượng 156,59 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Bài viết có 5 phần: 4/ Kiểm tra cờ trạng thái 5/ Xử lí file nhị phân 6/ Một số hàm hữu dụng Tôi post bài này lên không dám qua mặt các “cao thủ”, mà chỉ để nói rằng trong diễn đ àn rất

Trang 1

All about File I/O in C++

( Bài này mình lấy của anh CUONGUYEN ở trên ddth.com, bài này được viết từ năm 2002 Mình thấy khá hay nên tổng hợp lại cho các bạn dễ tham khảo Mình trích nguyên văn, chỉ thêm style thôi

Bài viết có 5 phần:

4/ Kiểm tra cờ trạng thái 5/ Xử lí file nhị phân 6/ Một số hàm hữu dụng

)

Tôi post bài này lên không dám qua mặt các “cao thủ”, mà chỉ để nói rằng trong diễn đ àn rất cần các bài post này để mọi ngư ời cùng học, và t ôi hi vọng là các cao thủ sẽ post các bài của mình lên để cho tôi học hỏi

Bài này sẽ giới thiệu về File I/O

1 Write To File.

Chúng ta cùng xem chương trình đầu tiên nhé:

#include <fstream.h>

void main()

{

ofstream WriteToFile(“first.txt”);

WriteToFile << “Hello World!”;

WriteToFile.close();

}

Chương trình này tạo một file “first.txt” (ở nơi cùng thư mục với file chương trình của bạn), rồi ghi dòng “Hello World!” vào file

Hãy đi từng dòng nhé:

#include <fstream.h> - Thư viện để sử dụng các hàm File I/O

ofstream WriteToFile(“first.txt”):

ofstream là một lớp Dòng này tạo một đối tượng thể hiện lớp ofstream là WriteToFile (hoặc một tên bất kỳ), dùng hàm contructor với tham số “first.txt” Hàm này sẽ tạo ra một file với tên là “first.txt”

Trang 2

WriteToFile << “Hello World!”: ghi chuỗi “Hello World!” vào file.

WriteToFile.close(): đóng file lại Mỗi khi bạn mở một file, sau đó bạn phải đóng nó lại

2 Đọc từ File

Chương trình

#include <fstream.h>

void main(){

ifstream OpenFile("first.txt");

char ch;

while(!OpenFile.eof())

{

OpenFile.get(ch);

cout << ch;

}

OpenFile.close();

}

Chương trình này dùng cách đọc từng ký tự (còn có cách khác là đọc từng từ (word) và đọc từng dòng (line) - sẽ tham khảo sau)

ifstream OpenFile(“first.txt”) – Tạo một đối tượng thể hiện lớp ifstream tên là OpenFile (có thể dùng tên khác tuỳ ý) Hàm contructor với tham số “first.txt”, đây là file mà chúng ta đã tạo ở mục trên Hàm này sẽ mở file “first.txt” để đọc

char ch: dòng này tôi biết rằng các bạn đã quá quen thuộc

while(!OpenFile.eof()) - hàm eof() của lớp ifstream Hàm eof() trả về giá trị 0 khi chưa kết thúc file, ngược lại là 1

OpenFile.get(ch); - get(char &ch) là một hàm của lớp ifstream, hàm này sẽ đọc từng ký tự của file và gán cho biến ch Sau đó sẽ chỉ đến ký tự tiếp theo (do inside-pointer)

Vòng lặp while sẽ lặp cho tới khi kết thúc file, mỗi lần lặp sẽ đọc một ký tự và gán cho biến ch Sau

đó đưa ra màn h ình ký tự đó:

cout<<ch;

Vòng lặp tiếp theo sẽ đọc ký tự tiếp theo sau ký tự trước (do inside-pointer: điều này sẽ được giải

Trang 3

thích ở phần sau) Do đó khi chạy chương trình, sẽ xuất hiện trên màn hình dòng chữ:

“Hello World!”

3 Quản lý Iuồng I/O.

Trong phần này chúng ta sẽ học về một số hàm hữu dụng

Phần trước chúng ta đã tạo một file bằng lệnh:

ofstream File(“filename.txt”);

Chúng ta có một cách khác đó là sử dụng hàm open():

ofstream File;

File.open(“finename.txt”);

Hàm open() nguyên dạng:

void open(char *filename, [int open_mode]);

trong đó tham số open_mode chỉ ra phương thức mở file Nó có thể có các giá trị sau:

+ ios::in -> mở file để đọc

+ ios::out -> mở file để ghi

+ ios::app -> mở file để ghi vào cuối file Nó gọi ios::out (?)

+ ios::ate -> mở file để ghi vào cuối Nó không gọi ios::out (?)

+ ios::trunc -> xoá tất cả nội dung đã có

+ ios::nocreate -> nếu file chưa tồn tại, sẽ không mở được

+ ios::noreplace -> nếu file đã tồn tại, cố gắng mở sẽ gây lỗi

+ ios::binary -> mở file binary

Ví dụ 1:

#include <fstream.h>

void main()

{

ofstream WriteToFile(“first.txt”, ios::ate);

WriteToFile<<”\nI love you”;

Trang 4

WriteToFile.close();

}

Kết quả là file “first.txt” (phần trước) có nội dung là:

Hello World!

I love you

Nếu không có tham số ios::ate thì nội dung của file lúc trước sẽ bị xóa

Ví dụ 2:

Nếu chưa có file “non_exit.txt”

#include <fstream.h>

void main()

{

ofstream File(“non_exit.txt”, ios::nocreate);

if(!File) {

cout<<”Error openning.”;

exit(1);

}

File.close();

}

Kết quả: “Error openning.” và không tạo file trong thư mục của bạn Nếu không có tham số

ios::nocreate thì vẫn vô tư, nghĩa là không có dòng thông báo lỗi và vẫn tạo ra file “non_exit.txt”

Ví dụ 3:

#include<fstream.h>

int main()

{

ifstream File(“first.txt”, ios::noreplace);

if(!File) {

cout<<”Error!”;

exit(1);

}

File.close();

return 0;

}

Kết quả: “Error!”, vì file “first.txt” đã tồn tại Tham số ios::noreplace không cho phép mở file đã tồn tại

Nếu bạn muốn có nhiều phương thức mở bạn dùng toán tử OR (|):

Trang 5

ios::ate | ios::binary

Sử dụng open_mode, chúng ta có thể vừa mở file để đọc và để ghi Ví dụ:

#include <fstream.h>

void main()

{

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

File << "Hi! I’m there.";

char ch;

File.seekg(ios::beg);

while(!File.eof())

{

File.get(ch);

cout <<ch;

}

cout<<endl;

File.close();

}

Có cái gì mới mẻ ở đây ấy nhỉ Okay, chúng ta sẽ hiểu ngay thôi

fstream File(“test.txt”, ios::in | ios::out); - vì mở file vừa để đọc và ghi nên chúng ta tạo một đối tượng thuộc lớp fstream (chứ không phải ofstream-để ghi hay ifstream để đọc)

File.seekg (ios::beg); - A đây rồi, cái này có vẻ hơi mới mẻ nhỉ (tất nhiên là với người bắt đầu học)

Để xem tại sao lại phải sử dụng “nó” chúng ta hãy xem khối lệnh:

while(!OpenFile.eof())

{

OpenFile.get(ch);

cout << ch;

}

Khối lệnh này chắc hẳn bạn đã biết Hàm get(ch) sẽ đọc một kí tự của file và gán cho biến ch Vòng lặp sẽ kết thúc khi đến cuối file Để vòng lặp “biết” được khi nào thì kết thúc file thì, khi đọc file có một “con trỏ trong” (inside-pointer) Sau khi get(ch) thực hiện việc gán cho ch kí tự hiện hành thì

“inside-pointer” sẽ chỉ đến kí tự tiếp theo Cứ thế, đến lần lặp sau ch sẽ nhận được giá trị tiếp theo cho đến khi kết thúc file

Quay trở lại hàm seekg() Lý do phải sử dụng hàm này vì sau câu lệnh:

File<<”Hi! I’m there”;

thì “inside-pointer” sẽ trỏ đến cuối file Vì vậy phải dùng câu lệnh:

Trang 6

File.seekg(ios::beg);

để đưa “inside-pointer” về đầu file Bạn có thể sử dụng các tham số cho hàm seekg() như sau: ios::beg – đưa “inside-pointer” về đầu file (có giá trị là 0)

ios::end - đưa “inside-pointer” về cuối file Nhưng tại sao tôi thấy tham số này luôn chỉ đến kí tự thứ

3 thế nhỉ (giá trị 2)?

Hoặc bạn có thể dùng:

File.seekg(4); -> “inside-pointer” chỉ đến kí tự thứ 4 kể từ đầu file (ký tự đầu là 0)

File.seekg(-5,ios::end); -> đưa “inside-pointer” đến cuối file sau đó quay lại 5 kí tự

Ví dụ:

#include<fstream.h>

main()

{

ifstream File(“second.txt”);

char ch;

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

File.get(ch);

cout<<ch;

File.close();

}

Nội dung file “second.txt” là “Hi! I’m there.”

Kết quả được “h”

Như trên đã nói, ngoài cách đọc từng char, ta có thể đọc từng word, hay từng line

Ví dụ:

#include<fstream.h>

void main

{

ifstream File(“first.txt”, ios::in);

char str[30];//lưu trữ từng từ vào str

while(!File.eof())

{

File >> str;

cout << str<<” “;

}

File.close();

}

File>>str sẽ đọc từng từ và gán cho str Kết quả ta sẽ được “Hello World! I love you.” (không xuống dòng-đây là nhược điểm của phương pháp này)

Trang 7

Bạn có thể đọc từng line Ví dụ:

#include<fstream.h>

void main()

{

ifstream File(“first.txt”);

char line[100]; //lưu trữ toàn bộ dòng vào biến này

while(!File.eof())

{

File.getline(line,100);

cout << line << endl;

}

File.close();

}

Kết quả:

Hello World!

I love you

Như vậy, một điều khuyên cho các bạn đó là sử dụng cách đọc từng char, hoặc từng line Vậy ta có thể đọc file theo 3 cách:

- Đọc từng char: File.get(ch);

- Đọc từng word: File>>ch;

- Đọc từng line: File.getline(ch,dimension);

Bây giờ chúng ta sẽ "check" xem file có mở được hay không:

Cách 1:

ofstream (ifstream) File("somefile.txt");

if(!File) {

}

Cách này đã được sử dụng ở một số ví dụ trước

Cách 2: Sử dụng hàm fail():

ofstream File("somefile.txt");

if(File.fail())

{

}

Hàm fail() trả về giá trị 0 nếu có lỗi (không mở được file) hay 1 nếu không có lỗi

Để kiểm tra xem file đã được mở chưa ta dùng hàm is_open() Hàm trả về 0 nếu file chưa được mở,

1 nếu file đã được mở Ví dụ:

ofstream File;

File.open("file1.txt");

cout << File1.is_open();

Trang 8

sẽ cho giá trị 1

4 Kiểm tra cờ trạng thái I/O (I/O status-flag)

Hệ thống I/O trong C++ nắm giữ các thông tin về kết quả của các toán tử I/O Trạng thái hiện hành được lưu trữ trong một đối tượng kiểu io_state (tương tự open_mode) với những giá trị sau: + ios::goodbit: không có lỗi

+ ios::eofbit: tới cuối file

+ ios::failbit: lỗi không gây hại (non-fatal)

+ ios::badbit: lỗi gây hại (fatal)

Có hai cách để nhận được thông tin về trạng thái I/O Cách thứ nhất là gọi hàm rdstate() Hàm này trả về trạng thái của cờ lỗi Ví dụ, hàm rdstate() sẽ trả về giá trị ios::goobit nếu không có lỗi Cách thứ hai là sử dụng một trong các hàm sau:

bool bad() -> 1 nếu có lỗi badbit

bool eof() -> 1 nếu đến cuối file

bool fail() ->1 nếu có lỗi failbit

bool good() ->1 nếu không có lỗi

Ví dụ:

ofstream File("somefile.txt");

if(File.bad()==1) {

}

Khi một lỗi xảy ra, bạn có thể xoá bỏ lỗi đó (thiết lập lại cờ trạng thái) Để làm việc này bạn dùng hàm clear(arg), với arg là cờ trạng thái mà bạn muốn thiết lập khi có lỗi

Các ví dụ về cờ trạng thái:

Ví dụ 1: Sử dụng hàm rdstate()

ifstream File("somefile.txt");

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

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

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

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

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

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

Trang 9

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

cout << "No errors!\n";

Ví dụ 2: Sử dụng hàm clear()

#include <fstream.h>

void main()

{

ofstream File("love.txt"); //tạo file love.txt

File.close();

//Việc mở file dưới đây sẽ gây lỗi vì sử dụng open_mode là ios::noreplace

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

//Lỗi này là lỗi ios::failbit

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

cout << "Error !\n";

Test.clear(ios::goodbit); //Đặt flag sang trạng thái goodbit

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

cout << "Fine!\n";

Test.clear(ios::eofbit); //Đặt sang trạng thái eofbit

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

cout << "EOF!\n";

Test.close();

}

5 Xử lý file nhị phân

Mặc dù các file với định dạng text rất hữu dụng, nhưng đôi khi bạn cần làm việc với các file nhị phân Các hàm để ghi/đọc với các file này là get() và put() Để đọc một byte, sử dụng hàm get() và để ghi một byte sử dụng hàm put() Cả hai hàm này đều nhận một đối số Lưu ý là các hàm này chỉ ghi/đọc được một byte, nghĩa là một ký tự

Nếu bạn muốn đọc/ghi một khối dữ liệu, bạn có thể sử dụng các hàm read() và write() Nguyên mẫu của chúng là:

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

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

Với hàm read(), buf nên là một mảng ký tự mà khối dữ liệu đọc sẽ được đặt vào

Với hàm write(), buf là một mảng ký tự,là dữ liệu mà bạn muốn ghi vào file

Với cả hai hàm num là một số xác định dữ liệu được đọc/ghi

Nếu bạn đi đến cuối file, trước khi bạn đọc "num" ký tự, bạn có thể thấy bao nhiêu ký tự đọc được bằng cách dùng hàm gcount()

Trang 10

Ví dụ 1: Sử dụng hàm put() và get()

#include <fstream.h>

void main()

{

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

char ch;

ch='o';

File.put(ch); //Đưa nội dung của ch vào file

File.seekg(ios::beg); //đến đầu file

File.get(ch); //đọc một ký tự

cout << ch << endl;

File.close();

}

Ví dụ 2: Sử dụng 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!"); //copy "Hello World!" vào arr

File.write(arr,5); //ghi 5 ký tự đầu vào file- "Hello"

File.seekg(ios::beg); //trở về đầu file

static char read_array[10];

File.read(read_array,3); //Đọc 3 ký tự - "Hel"

cout << read_array << endl;

File.close();

}

6 Một số hàm hữu dụng

+ tellg() – Trả về một giá trị nguyên, cho biết vị trí hiện tại của inside-pointer Hàm này dùng khi đọc file Ví dụ:

#include <fstream.h>

void main()

{

Trang 11

ofstream File("test.txt");

File<<"Hello";

File.close();

ifstream File1("test.txt");

char arr[10];

File1.read(arr,10);

cout << File1.tellg() << endl; //cho giá trị 5

File1.close();

}

+ tellp() – Giống tellg() nhưng được sử dụng khi ghi vào file

+ seekp() – Giống seekg(), được sử dụng khi ghi vào file

+ ignore() – Sử dụng khi đọc file Nếu bạn muốn "ignore" một số ký tự, hãy sử dụng hàm này Thực

ra, bạn có thể sử dụng hàm seekg() thay thế, nhưng hàm ignore() có một ưu điểm, bạnc có thể đặc

tả một quy định giới hạn, nơi hàm ignore() sẽ kết thúc Dạng hàm ignore() là:

istream& ignore( int nCount, delimiter );

Trong đó nCount là số lượng ký tự sẽ được bỏ qua và delimiter là giới hạn nơi hàm ignore() kết thúc

Nó có thể là EOF Ví dụ:

#include <fstream.h>

void main()

{

//Ở trên chúng ta đã có "Hello World" trong file test_file.txt

ifstream File("test_file.txt");

static char arr[10];

//Dừng hàm ignore() nếu gặp ký tự "l"

File.ignore(6,'l');

File.read(arr,10);

cout << arr << endl; //cho "lo World!"

File.close();

}

+ getline() – Hàm này được sử dụng để đọc từng line, nhưng nó còn được thiết lập để ngừng đọc nếu nó gặp một ký tự nào đó Để làm việc này sử dụng dạng sau:

getline(array,array_size,delim);

Trong đó delim là ký tự dùng để kết thúc việc đọc

Ví dụ:

#include <fstream.h>

void main()

Trang 12

{

//Nhớ là chúng ta đã có "Hello World" trong file "test.txt"

ifstream File("test_file.txt");

static char arr[10];

File.getline(arr,10,'o');// Đọc cho tới khi gặp ký tự 'o'

cout << arr << endl; //Cho "Hell"

File.close();

}

+ peek() – Hàm này sẽ cho mã ASCII của ký tự tiếp theo trong một luồng file input Nhưng nó không dịch chuyển inside-pointer Khác với hàm get() là cho ký tự tiếp theo và dịch chuyển inside-pointer Nếu sử dụng hàm này hai lần liền sẽ được cùng một ký tự Ví dụ:

#include <fstream.h>

void main()

{

ifstream File("test_file.txt");

char ch;

File.get(ch);

cout << ch << endl; //cho "H"

cout << char(File.peek()) << endl; //hiển thị "e"

cout << char(File.peek()) << endl; //hiển thị "e"

File.get(ch);

cout << ch << endl; //hiển thị "e"

File.close();

}

+ _unlink() – Xoá toàn bộ file Để sử dụng hàm này hãy "#include<io.h>" trong chương trình của bạn

Ví dụ:

#include <fstream.h>

#include <io.h>

void main()

{

ofstream File;

File.open("delete_test.txt"); //tạo file delete_test.txt

File.close();

_unlink("delete_test.txt"); //xoá file delete_test.txt

File.open("delete_test.txt",ios::nocreate);//mở file đã xoá với open_mode là ios::nocreate sẽ gây //lỗi Lỗi này là ios::failbit

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

cout << "Error !\n";

File.close();

}

+ putback() –Hàm này sẽ cho ký tự đọc lần cuối cùng và sẽ dịch chuyển inside-pointer về trước một

ký tự

Ngày đăng: 29/07/2014, 17:21

TỪ KHÓA LIÊN QUAN