2011-01-26 27 views
6

Tôi đang sử dụng một FileManager cho một dự án để đọc và viết ít rắc rối hơn cho tôi. Hoặc sẽ là, nếu tôi không dành tất cả thời gian này gỡ lỗi nó. Vì vậy, lớp học tiện nghi này thực sự đã gây ra cho tôi sự căng thẳng và thời gian. Tuyệt vời.Fstream không tạo được tập tin mới

Sự cố có vẻ là fstream. Trước khi tiếp tục, đây là cấu trúc của lớp FileManager của tôi.

class FileManager : Utility::Uncopyable 
{ 
public: 
    FileManager(); 

    void open(std::string const& filename); 
    void close(); 

    void read(std::string& buffer); 
    void write(std::string const& data); 

private: 
    std::fstream stream_; 
}; 

Rất đơn giản. Bộ đệm được nạp với dữ liệu trong hàm đọc, tham số dữ liệu là những gì được ghi vào tệp. Trước khi đọc và viết, bạn phải mở tập tin hoặc rủi ro nhận được một ngoại lệ lớn, chất béo trong khuôn mặt của bạn. Loại như tôi đang nhận được bây giờ.

Tình huống: Đăng ký dòng lệnh đơn giản của người dùng, sau đó ghi dữ liệu vào tệp. Tôi yêu cầu tên và mật khẩu. Tên được sao chép và nối với .txt (tên tệp). Vì vậy, có vẻ như sau:

void SessionManager::writeToFile(std::string const& name, 
           std::string const& password) 
{ 
    std::string filename = name + ".txt"; 
    std::string data; 
    data += name +", " +password; 

    try 
    { 
     fileManager_->open(filename); 
     fileManager_->write(data); 
     fileManager_->close(); 
    } 
    catch(FileException& exception) 
    { 
     /* Clean it up. */ 
     std::cerr << exception.what() << "\n"; 
     throw; 
    } 
} 

Sự cố: mở không thành công. Tệp không bao giờ được tạo và trong quá trình viết, tôi nhận được ngoại lệ vì không có tệp mở.

FileManager :: open() chức năng:

void FileManager::open(std::string const& filename) 
{ 
    if(stream_.is_open()) 
     stream_.close(); 

    stream_.open(filename.c_str()); 
} 

và viết

void FileManager::write(std::string const& data) 
{ 
    if(stream_.is_open()) 
     stream_ << data; 
    else 
     throw FileException("Error. No file opened.\n"); 
} 

Tuy nhiên, nếu tôi có thể tạo các tập tin trước, sau đó nó không có rắc rối mở tập tin. Tuy nhiên, khi tôi kiểm tra, mặc định std::ios::openmodestd::ios::in | std::ios::out. Tôi có thể tạo tệp chỉ tốt khi tôi chỉ gắn thẻ std::ios::out, nhưng tôi muốn giữ luồng ở trạng thái đọc/ghi.

Tôi làm cách nào để thực hiện việc này?

Trả lời

7

phương pháp tốt nhất:

void FileManager::open(std::string const& filename) 
{ 
    using std::ios_base; 
    if(stream_.is_open()) 
     stream_.close(); 

    stream_.open(filename.c_str()); // ...try existing file 
    if(!stream_.is_open()) // ...else, create new file... 
     stream_.open(filename.c_str(), ios_base::in | ios_base::out | ios_base::trunc); 
} 

Vì vậy, các bài kiểm tra mã cho một tập tin hiện có, và nếu không, tạo ra nó.

2

Đó là cách thư viện hoạt động: std::ios::in | std::ios::out mở nó trong tương đương với stdio 's "r+", nghĩa là nó sẽ chỉ mở tệp hiện có. Tôi không tin rằng có một chế độ sẽ làm những gì bạn muốn, bạn sẽ phải gọi cho chúng tôi một hệ điều hành cụ thể hoặc kiểm tra tệp để tồn tại (một lần nữa, sử dụng một cuộc gọi cụ thể cho hệ điều hành) và mở nó trong một chế độ hoặc khác tùy thuộc vào việc nó đã tồn tại chưa.

Chỉnh sửa: Tôi cho rằng bạn không muốn tệp bị cắt bớt nếu tệp đã tồn tại. Như những người khác đã lưu ý, nếu bạn sẵn sàng cắt bớt bất kỳ tệp hiện có nào thì in | out | trunc là một tùy chọn.

3

Bạn không thể sử dụng std::ios::in trên một tệp không tồn tại. Sử dụng

std::ios::in | std::ios::out | std::ios::trunc 

thay vào đó (nhưng đảm bảo không tồn tại hoặc nó sẽ bị cắt bớt thành 0 byte).

3

Bạn phải gọi fstream::open với một openmode lập luận rõ ràng của

ios_base::in | ios_base::out | ios_base::trunc 

Nếu không open sẽ thất bại do ENOENT.

Bảng 95 của dự thảo tiêu chuẩn C++ liệt kê các chế độ mở tệp có thể có và phương thức tương đương của chúng trong stdio.Giá trị mặc định, ios_base::out | ios_base::inr+. Cái tôi liệt kê ở trên tương đương với w+. ios_base::out | ios_base::app tương đương với a. Tất cả các kết hợp khác liên quan đến ios_base::app không hợp lệ.

(Tại nguy cơ bị chế giễu tại địa chỉ:. Bạn có thể chuyển sang stdio và sử dụng chế độ tập tin a+, mà đọc từ đầu và gắn thêm ở cuối)

+0

Vì C++ 11, 'ios_base :: app' được cho phép và tương đương với" a ". Xem Bảng 132 trong C++ 11 hoặc C++ 14 cho bảng đã cập nhật. –

3

Làm thế nào tôi có thể thực hiện điều này?

std::ofstream file("file.txt"); 
file << data; 

Đơn giản hơn không?

+0

"nhưng tôi muốn giữ luồng ở trạng thái đọc/ghi". –

+0

Tôi thừa nhận rằng tôi không thấy điểm trong lớp 'FileManager' này, nhưng OP muốn một luồng đọc/ghi. –

1

Chỉ cần có được chức năng của bạn để mở

void FileManager::open(std::string const& filename) 
{ 
    using std::ios_base; 
    if(stream_.is_open()) 
     stream_.close(); 

    stream_.open(filename.c_str(), ios_base::in | ios_base::out | ios_base::trunc); 
} 

nếu đó là chế độ mà bạn yêu cầu.

Không có cách kỳ diệu để mở tệp để đọc/ghi tạo tệp nếu nó không tồn tại nhưng không cắt bớt nó (xóa nội dung của nó) nếu có. Bạn phải làm điều đó trong nhiều bước.

Các vấn đề liên quan