2013-06-27 31 views
55
ifstream f; 
f.open(fileName); 

if (f.fail()) 
{ 
    // I need error message here, like "File not found" etc. - 
    // the reason of the failure 
} 

Làm thế nào để nhận được thông báo lỗi dưới dạng chuỗi?Cách nhận thông báo lỗi khi ifstream mở không thành công

+2

có thể trùng lặp của [C++ ifstream Error Checking] (http://stackoverflow.com/questions/13446593/c-ifstream-error-checking) –

+1

có thể trùng lặp của [Bạn có thể nhận được một điều kiện lỗi cụ thể khi một dòng C++ mở không?] (http://stackoverflow.com/questions/303966/can-you-get-a-specific-error-condition-when-ac-stream-open-fails) – arne

+3

@Alex Farber: Chắc chắn rồi. 'cerr <<" Mã lỗi: "<< strerror (errno); // Nhận một số thông tin về lý do tại sao' có vẻ liên quan đến câu hỏi. –

Trả lời

42

Mỗi cuộc gọi hệ thống mà không cập nhật giá trị errno.

Vì vậy, bạn có thể có thêm thông tin về những gì xảy ra khi một mở ifstream thất bại bằng cách sử dụng một cái gì đó như:

cerr << "Error: " << strerror(errno); 

Tuy nhiên, vì mọi hệ thống gọi cập nhật các giá trị errno toàn cầu, bạn có thể gặp sự cố trong ứng dụng đa luồng, nếu một cuộc gọi hệ thống khác gây ra lỗi giữa việc thực thi f.open và sử dụng errno.

Trên hệ thống với POSIX tiêu chuẩn:

errno là thread-địa phương; đặt nó trong một chủ đề không ảnh hưởng đến giá trị của nó trong bất kỳ chủ đề nào khác.


Sửa (nhờ Arne Mertz và những người khác trong các ý kiến):

e.what() dường như lúc đầu là một hơn C++ - cách idiomatically đúng thực hiện điều này, tuy nhiên chuỗi trả lại bởi chức năng này phụ thuộc vào việc thực hiện và (ít nhất là trong lib ++ + của G ++) chuỗi này không có thông tin hữu ích về lý do đằng sau lỗi ...

+1

'e .what() 'dường như không cung cấp nhiều thông tin, xem các cập nhật cho câu trả lời của tôi. –

+11

'errno' sử dụng bộ nhớ cục bộ trên hệ điều hành hiện đại. Tuy nhiên, không có gì đảm bảo rằng các hàm 'fstream' sẽ không bị đè nén' errno' sau khi một errno xảy ra. Các hàm bên dưới có thể không đặt 'errno' ở tất cả (gọi hệ thống trực tiếp trên Linux hoặc Win32). Điều này không hoạt động trên nhiều triển khai thực tế trên thế giới. – strcat

+0

Trong MSVC, 'e.what()' luôn in cùng một thông báo "' lỗi dòng iostream' " – rustyx

21

Bạn có thể thử để cho dòng ném một ngoại lệ về thất bại:

std::ifstream f; 
//prepare f to throw if failbit gets set 
std::ios_base::iostate exceptionMask = f.exceptions() | std::ios::failbit; 
f.exceptions(exceptionMask); 

try { 
    f.open(fileName); 
} 
catch (std::ios_base::failure& e) { 
    std::cerr << e.what() << '\n'; 
} 

e.what(), tuy nhiên, dường như không thể rất hữu ích:

  • Tôi đã thử nó trên Win7, Embarcadero RAD Studio 2010, nơi nó cung cấp "ios_base :: failbit set" trong khi strerror(errno) cho "Không có tệp hoặc thư mục như vậy".
  • Trên Ubuntu 13.04, gcc 4.7.3 ngoại trừ nói "basic_ios :: rõ ràng" (nhờ arne)

Nếu e.what() không làm việc cho bạn (tôi không biết những gì nó sẽ cho bạn biết về lỗi, vì đó không phải tiêu chuẩn hóa), hãy thử sử dụng std::make_error_condition (C++ chỉ có 11):

catch (std::ios_base::failure& e) { 
    if (e.code() == std::make_error_condition(std::io_errc::stream)) 
    std::cerr << "Stream error!\n"; 
    else 
    std::cerr << "Unknown failure opening file.\n"; 
} 
+0

Cảm ơn. Tôi đã không kiểm tra điều này bởi vì 'strerror (errno)' được đăng trong các bình luận hoạt động và rất đơn giản để sử dụng. Tôi nghĩ rằng 'e.what' sẽ hoạt động, vì' errno' hoạt động. –

+0

Sau đó, xem các chú giải về đa luồng trong câu trả lời Matthieus - tôi đoán là 'e.what()' sẽ là những gì 'strerror' trả về, theo một cách an toàn. Cả hai có lẽ sẽ phụ thuộc vào nền tảng. –

+0

@AlexFarber: Tôi nghĩ câu trả lời của Arne tốt hơn tôi. Giải pháp của tôi không phải là _C++ - way_ để giải quyết vấn đề của bạn. Tuy nhiên, tôi không tìm thấy thông tin chính thức về cách thư viện C++ ánh xạ các lỗi hệ thống đến 'exception.what()'. Có thể là một cơ hội tốt để đi sâu vào mã nguồn libstdC++ :-) –

13

Theo sau câu trả lời của @Arne Mertz, như C++ 11 std::ios_base::failure được kế thừa từ system_error (xem http://www.cplusplus.com/reference/ios/ios_base/failure/), chứa cả mã lỗi và thông báo strerror(errno) sẽ trả lại.

std::ifstream f; 

// Set exceptions to be thrown on failure 
f.exceptions(std::ifstream::failbit | std::ifstream::badbit); 

try { 
    f.open(fileName); 
} catch (std::system_error& e) { 
    std::cerr << e.code().message() << std::endl; 
} 

Bản in này No such file or directory. nếu fileName không tồn tại.

+5

Đối với tôi trong MSVC 2015 chỉ in' lỗi luồng iostream'. – rustyx

+0

Đối với tôi GCC 6.3 cũng in 'lỗi iostream'. Bạn đã thử nghiệm trình biên dịch này trên trình duyệt nào? Có bất kỳ trình biên dịch thực sự cung cấp một lý do người dùng có thể đọc được cho thất bại? – Ruslan

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