2012-03-06 24 views
7

Trong chương trình C++, sử dụng std :: ifstream, tôi đang cố mở một tệp do người dùng chỉ định - cho đến nay rất tốt. Tuy nhiên, tôi vô tình nhập tên tệp thực sự là một thư mục và tôi khá ngạc nhiên khi thấy rằng cố gắng mở() thư mục đó không tạo ra bất kỳ lỗi nào.Ifstream open() không đặt bit lỗi khi đối số là một thư mục

Dưới đây là một ví dụ nhỏ:

std::ifstream f; 
f.open(".."); 
if(!f.is_open() || !f.good() || f.bad() || f.fail()) { 
    std::cout << "error bit set on open" << std::endl; 
    return 1; 
} 

Không có dấu hiệu của lỗi ở đây. Nếu tôi tiếp tục và cố gắng để getline(), getline() thiết lập một bit lỗi tất cả các quyền.

std::string str; 
getline(f, str); 

if(f.eof()) std::cout << "getline set eofbit" << std::endl; 
else if(f.bad()) std::cout << "getline set badbit" << std::endl; 
else if(f.fail()) std::cout << "getline set failbit" << std::endl; 

Kết quả này "getline set badbit", điều này là hợp lý. Sử dụng toán tử >> đưa ra một ngoại lệ tràn, điều này cũng ổn.

Bây giờ, câu hỏi của tôi là, làm thế nào tôi có thể phát hiện ra rằng người dùng đã nhập tên thư mục thay vì tên tệp thích hợp? Có cách nào để làm điều đó? Bắt và không đặt byte từ luồng dường như tẻ nhạt và dễ bị lỗi.

Ngoài ra, tại sao lại như vậy? Tôi nhận ra rằng đó là tất cả chỉ là cùng một dữ liệu từ quan điểm của chương trình, nhưng tôi cho rằng hệ điều hành cũng sẽ gửi một số "hey, đây là một thư mục" loại tin nhắn.

+0

Bạn đang nhận hành vi này trên nền tảng nào? –

+0

C++ không có khái niệm "thư mục". Bạn cần một số thư viện nền tảng cụ thể (như Posix hoặc Windows). –

+0

Ồ, Ubuntu 10.04, trình biên dịch là gcc 4.4.3. –

Trả lời

3

Bạn không nói hệ thống của mình là gì, do đó, khó có thể nói, nhưng nói chung, filebuf::open sẽ chỉ trả lại lỗi nếu mức hệ thống của bạn mở không thành công. Và tôi đã làm việc trên các hệ thống Unix nơi bạn có thể open() một thư mục ; Tôi thậm chí đã làm việc trên một số nơi bạn có thể đọc nó sau khi mở (ít nhất là nếu nó là một hệ thống tập tin được gắn cục bộ).

Để biết phải làm gì về điều đó: về tất cả những gì tôi có thể nghĩ là cố gắng get ký tự đầu tiên, sau đó đặt lại. Nhưng điều này không thành công nếu tệp là trống, vì vậy nó không thực sự là một giải pháp. Ở cấp độ hệ thống (và từ quan điểm QoI, tôi mong đợi filebuf::open để thực hiện điều này nếu hệ thống cho phép mở thư mục), bạn có thể sử dụng cuộc gọi cấp hệ thống (stat trong Unix) để xác định xem tập tin là một thư mục hay không. (Dĩ nhiên, có một điều kiện chủng tộc: giữa thời điểm bạn phát hiện đó là tệp bình thường và thời điểm bạn mở, một quy trình khác có thể xóa tệp và tạo thư mục. Có thể không phải là thường xuyên xảy ra, tuy nhiên.)

+0

Ồ, vì vậy nó là nền tảng cụ thể, sau khi tất cả, tôi có thể đoán. Cảm ơn lời giải thích. Có, đây là trên Linux (Ubuntu, cùng xảy ra trên Debian, không ngạc nhiên). Vì tôi chỉ cố gắng đảm bảo rằng đó là một đoạn phim hợp lệ và có thể đọc được mà từ đó tôi có thể đọc được nội dung, nhận được và đặt cược là hợp lý, mặc dù tôi hy vọng có một giải pháp sạch hơn. Phụ thuộc và các cuộc gọi hệ thống có vẻ như quá mức cần thiết. Ý tôi là, tôi có thể sống với lỗi, nhưng, um, nó trông có vẻ kỳ lạ. –

+1

@ SáT: Tôi cũng đoán nó là cụ thể cho hệ thống tệp cơ bản được sử dụng trên phần cứng (lưu ý: một số hệ điều hành cho phép bạn chọn hệ thống tệp được sử dụng trên đĩa). –

+1

@LokiAstari Tôi nghĩ vậy. IIRC (nó đã được một thời gian kể từ khi tôi đã thử nó), theo Solaris, 'mở' trên một thư mục làm việc trên đĩa được gắn cục bộ (UFS), nhưng không phải nếu hệ thống tập tin là NFS. –

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