ifstream f;
f.open(fileName);
if ( f.fail() )
{
// I need error message here, like "File not found" etc. -
// the reason of the failure
}
จะรับข้อความแสดงข้อผิดพลาดเป็นสตริงได้อย่างไร?
ifstream f;
f.open(fileName);
if ( f.fail() )
{
// I need error message here, like "File not found" etc. -
// the reason of the failure
}
จะรับข้อความแสดงข้อผิดพลาดเป็นสตริงได้อย่างไร?
cerr << "Error code: " << strerror(errno); // Get some info as to why
ดูเหมือนจะเกี่ยวข้องกับคำถาม
strerror(errno)
ผล โพสต์นี้เป็นคำตอบฉันจะยอมรับมัน
คำตอบ:
ทุกการเรียกใช้ระบบที่อัปเดตerrno
ค่าไม่สำเร็จ
ดังนั้นคุณสามารถมีข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่เกิดขึ้นเมื่อการifstream
เปิดล้มเหลวโดยใช้สิ่งต่างๆเช่น:
cerr << "Error: " << strerror(errno);
อย่างไรก็ตามเนื่องจากการเรียกระบบทุกครั้งจะอัปเดต errno
ค่าส่วนกลางคุณอาจมีปัญหาในแอปพลิเคชันมัลติเธรดหากการเรียกระบบอื่นทริกเกอร์ข้อผิดพลาดระหว่างการดำเนินการf.open
และการใช้errno
.
บนระบบด้วยมาตรฐาน POSIX:
errno เป็นเธรดท้องถิ่น การตั้งค่าในเธรดเดียวจะไม่มีผลกับค่าในเธรดอื่น
แก้ไข (ขอบคุณ Arne Mertz และคนอื่น ๆ ในความคิดเห็น):
e.what()
ดูเหมือนว่าในตอนแรกจะเป็น C ++ มากขึ้น - วิธีที่ถูกต้องตามหลักการในการใช้สิ่งนี้อย่างไรก็ตามสตริงที่ส่งคืนโดยฟังก์ชันนี้ขึ้นอยู่กับการใช้งานและ (อย่างน้อยใน libstdc ++ ของ G ++) สตริงนี้ไม่มีข้อมูลที่เป็นประโยชน์เกี่ยวกับสาเหตุที่อยู่เบื้องหลังข้อผิดพลาด ...
e.what()
ดูเหมือนจะไม่ให้ข้อมูลมากนักโปรดดูการอัปเดตคำตอบของฉัน
errno
ใช้ที่เก็บเธรดโลคัลบนระบบปฏิบัติการสมัยใหม่ อย่างไรก็ตามไม่มีการรับประกันว่าfstream
ฟังก์ชันต่างๆจะไม่errno
เกิดความผิดพลาดหลังจากเกิดข้อผิดพลาด ฟังก์ชันพื้นฐานอาจไม่ได้ตั้งค่าไว้errno
เลย (เรียกระบบโดยตรงบน Linux หรือ Win32) สิ่งนี้ใช้ไม่ได้กับการใช้งานจริงหลายอย่าง
e.what()
พิมพ์ข้อความเดียวกันเสมอ " iostream stream error
"
warning C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1> C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\string.h(168) : see declaration of 'strerror'
คุณสามารถลองปล่อยให้สตรีมมีข้อยกเว้นเมื่อเกิดความล้มเหลว:
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()
อย่างไรก็ตามดูเหมือนจะไม่มีประโยชน์มากนัก:
strerror(errno)
ให้ "ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว"หากe.what()
ไม่ได้ผลสำหรับคุณ (ฉันไม่รู้ว่าจะบอกอะไรคุณเกี่ยวกับข้อผิดพลาดเนื่องจากไม่ได้มาตรฐาน) ให้ลองใช้std::make_error_condition
(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";
}
strerror(errno)
โพสต์ในความคิดเห็นใช้งานได้และใช้งานง่ายมาก ฉันคิดว่าe.what
จะได้ผลตั้งแต่errno
ทำงาน
e.what()
จะเป็นสิ่งที่strerror
ส่งคืนในวิธีที่ปลอดภัย ทั้งสองอาจขึ้นอยู่กับแพลตฟอร์ม
exception.what()
แผนที่ข้อผิดพลาดของระบบโทรไป อาจเป็นโอกาสที่ดีในการดำดิ่งสู่ซอร์สโค้ด libstdc ++ :-)
basic_ios::clear
ไม่มีอะไรอื่น สิ่งนี้ไม่เป็นประโยชน์จริงๆ นั่นเป็นเหตุผลที่ฉันไม่โพสต์;)
ตามด้วยคำตอบของ @Arne Mertz เนื่องจาก C ++ 11 std::ios_base::failure
สืบทอดมาจากsystem_error
(ดูhttp://www.cplusplus.com/reference/ios/ios_base/failure/ ) ซึ่งมีทั้งรหัสข้อผิดพลาดและข้อความที่strerror(errno)
จะส่งคืน
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;
}
สิ่งนี้จะพิมพ์No such file or directory.
หากfileName
ไม่มีอยู่
iostream stream error
ที่เพิ่งพิมพ์
iostream error
ยังพิมพ์ คุณทดสอบสิ่งนี้กับคอมไพเลอร์ใด คอมไพเลอร์ใด ๆ ให้เหตุผลที่ผู้ใช้สามารถอ่านได้สำหรับความล้มเหลวหรือไม่?
unspecified iostream_category error
MacOS:
f.open(fileName)
พ่นยกเว้นประเภทซึ่งได้มาจากstd::ios_base::failure
std::system_error
ข้อยกเว้นถูกจับโดยบล็อกการจับ ภายในจับบล็อกe.code()
จะเรียกซึ่งจะส่งกลับวัตถุของการพิมพ์std::ios_base::failure::code()
std::error_code
รหัสข้อผิดพลาดที่กำหนดโดยระดับstd::error_code
ที่มีขึ้นอยู่กับแพลตฟอร์ม --ie, e.code().message()
และe.code().value()
ผลตอบแทนทั้งค่าขึ้นอยู่กับแพลตฟอร์ม
คุณยังสามารถโยนได้std::system_error
ดังที่แสดงในรหัสทดสอบด้านล่าง f.exception(...)
วิธีนี้ดูเหมือนว่าจะผลิตออกอ่านได้มากขึ้นกว่า
#include <exception> // <-- requires this
#include <fstream>
#include <iostream>
void process(const std::string& fileName) {
std::ifstream f;
f.open(fileName);
// after open, check f and throw std::system_error with the errno
if (!f)
throw std::system_error(errno, std::system_category(), "failed to open "+fileName);
std::clog << "opened " << fileName << std::endl;
}
int main(int argc, char* argv[]) {
try {
process(argv[1]);
} catch (const std::system_error& e) {
std::clog << e.what() << " (" << e.code() << ")" << std::endl;
}
return 0;
}
ตัวอย่างผลลัพธ์ (Ubuntu w / clang):
$ ./test /root/.profile
failed to open /root/.profile: Permission denied (system:13)
$ ./test missing.txt
failed to open missing.txt: No such file or directory (system:2)
$ ./test ./test
opened ./test
$ ./test $(printf '%0999x')
failed to open 000...000: File name too long (system:36)