আইফ্রিম ওপেন ব্যর্থ হলে কীভাবে ত্রুটি বার্তা পাবেন get


101
ifstream f;
f.open(fileName);

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

স্ট্রিং হিসাবে ত্রুটি বার্তা কিভাবে পাবেন?




4
@ অ্যালেক্স ফারবার: অবশ্যই cerr << "Error code: " << strerror(errno); // Get some info as to whyপ্রশ্নের সাথে প্রাসঙ্গিক বলে মনে হচ্ছে
— ম্যাথিউ রাউজেট

@ ম্যাথিউরউজেট: আমি পোস্ট করা সম্ভাব্য সদৃশটি পরীক্ষা করে দেখুন - মনে হয় এটি কেবল জিসিসি দ্বারা প্রয়োগ করা হয় না।
— আরে

4
@ ম্যাথিউরউজেট: strerror(errno)কাজ করে। উত্তর হিসাবে পোস্ট করুন, আমি এটি গ্রহণ করব।
— অ্যালেক্স এফ

উত্তর:


75

প্রতিটি সিস্টেম কল যা ব্যর্থ হয় আপডেট করে errno হয় মান ।

সুতরাং, ifstreamখোলা ব্যর্থতার মতো কিছু ব্যবহার করে ব্যর্থ হলে কী হয় সে সম্পর্কে আপনার আরও তথ্য থাকতে পারে:

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

যাইহোক, যে সিস্টেম কল বিশ্বব্যাপী আপডেট errnoমান, আপনি সমস্যাগুলির একটি মাল্টি অ্যাপ্লিকেশনে আরেকটি সিস্টেম কল সঞ্চালনের মধ্যে একটি ত্রুটি আরম্ভ করে যদি থাকতে পারে f.openএবং ব্যবহার errno।

POSIX মান সহ সিস্টেমে:

ত্রুটি-স্থানীয় হয়; এটি একটি থ্রেডে সেট করা অন্য কোনও থ্রেডের মানকে প্রভাবিত করে না।


সম্পাদনা করুন (মন্তব্যগুলিতে আর্নে মের্টজ এবং অন্যান্য লোককে ধন্যবাদ):

e.what() এটি প্রথমে আরও C ++ বলে মনে হয়েছিল - এটি প্রয়োগের আইডিয়োম্যাটিক্যালি সঠিক উপায়, তবে এই ফাংশনটি দিয়ে আসা স্ট্রিংটি বাস্তবায়ন নির্ভর এবং (কমপক্ষে জি ++ এর লিবিস্টডিসি ++ তে) এই স্ট্রিংটির ত্রুটির পিছনে কারণ সম্পর্কে কোনও কার্যকর তথ্য নেই ...


4
e.what()খুব বেশি তথ্য দেবে বলে মনে হচ্ছে না, আমার উত্তরের আপডেট দেখুন।
— আরনে মের্টজ

17
errnoআধুনিক অপারেটিং সিস্টেমগুলিতে থ্রেড-লোকাল স্টোরেজ ব্যবহার করে। যাইহোক, কোনও গ্যারান্টি নেই যে কোনও ত্রুটি হওয়ার পরে fstreamফাংশনগুলি errnoক্লোবার হবে না । অন্তর্নিহিত ফাংশনগুলি একেবারে সেট নাও করা যেতে পারে errno(লিনাক্স, অথবা উইন 32 এ সরাসরি সিস্টেম কল)। এটি বাস্তবের অনেকগুলি বাস্তবায়নে কাজ করে না।
— strcat

4
এমএসভিসিতে, 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'
— সার্জিওল

4
@sergiol- এগুলি মিথ্যা। এগুলি উপেক্ষা করুন বা সতর্কতাটি অক্ষম করুন।
— এসএস অ্যানি

30

আপনি ব্যর্থতার উপরে স্ট্রিমটিকে একটি ব্যতিক্রম ছুঁড়ে দেওয়ার চেষ্টা করতে পারেন:

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()তবে, এটি খুব সহায়ক বলে মনে হচ্ছে না:

  • আমি এটি উইন 7, এম্বারকাডেরো আরএডি স্টুডিও 2010 এ চেষ্টা করেছি যেখানে এটি "আইওএস_বেস :: ফেলবিট সেট" দেয় যেখানে strerror(errno) দেয় "এই জাতীয় কোনও ফাইল বা ডিরেক্টরি নেই" gives
  • উবুন্টু ১৩.০৪-তে, জিসিসি ৪.7.৩ ব্যতিক্রমটি "বেসিক_আইএসস :: ক্লিয়ার" বলেছেন ( আরিনকে ধন্যবাদ )

যদি আপনার e.what()পক্ষে কাজ না করে (ত্রুটি সম্পর্কে এটি আপনাকে কী বলবে আমি জানি না, যেহেতু এটি মানক নয়), std::make_error_condition(কেবলমাত্র সি ++ 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কাজ করে।
— অ্যালেক্স এফ

তারপর Matthieus উত্তরে multithreading সম্পর্কে annotaions দেখুন - আমার অনুমান যে e.what()কি হবে strerror, আয় একটি threadsafe উপায়। উভয়ই সম্ভবত প্ল্যাটফর্ম নির্ভর।
— আরনে মের্টজ

4
@ অ্যালেক্সফারবার: আমার কাছে মনে হয় যে অ্যানির উত্তর আমার চেয়ে ভাল। আমার সমাধানটি আপনার সমস্যা সমাধানের উপায় সি ++ নয় । তবে, সি ++ গ্রন্থাগার মানচিত্রের সিস্টেমটিতে কীভাবে ত্রুটি কল করা হয় সে সম্পর্কে আমি অফিসিয়াল তথ্য পাইনি exception.what()। Libstdc ++ উত্স কোডে ডুব দেওয়ার জন্য একটি ভাল সুযোগ হতে পারে :-)
— ম্যাথিউ রাউজেট

আমি এটি চেষ্টা করে দেখলাম: একটি অস্তিত্বহীন ফাইল খোলার চেষ্টা করেছি এবং ব্যতিক্রম বার্তাটি পড়তে হবে basic_ios::clear, অন্য কিছুই নয়। এটি সত্যই সহায়ক নয়। এজন্য আমি পোস্ট করি নি;)
— আরনে

@ আরনে উইচ প্ল্যাটফর্ম, সংকলক, ওএস?
— আরনে মের্টজ

23

@ আর্নে মের্টজের উত্তর অনুসরণ করে সি ++ 11 অনুসারে std::ios_base::failureউত্তরাধিকার সূত্রে প্রাপ্ত system_error( http://www.cplsplus.com/references/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অস্তিত্ব নেই।


9
আমার জন্য এমএসভিসি ২০১৫ যা কেবল প্রিন্ট করে iostream stream error।
— rustx

4
আমার জন্য জিসিসি 6.3 প্রিন্টও করে iostream error। আপনি কোন সংকলকটিতে এটি পরীক্ষা করেছেন? কোনও সংকলক আসলে ব্যর্থতার জন্য কোনও ব্যবহারকারী-পঠনযোগ্য কারণ সরবরাহ করে?
— Ruslan

4
ম্যাকোজে লাইবসি +++ এ ঝনঝন unspecified iostream_category error।
— আকীম

ম্যাকওএস 10.14.x এ এক্সকোড 10.2.1 (কলঙ্ক) / লাইবসি ++ (সি ++ 17): "অনির্ধারিত আইওস্ট্রিম_ক্যাটরি ত্রুটি"। এই অধিকার পাওয়ার একমাত্র উপায় হ'ল স্ট্রিরর (এর্ন) এসইএমএস। আমি মনে করি আমি প্রথমে স্টাড :: ফাইল সিস্টেম জিজ্ঞাসা করে এটি ধরতে পারলাম যদি पथ.এক্সেস্ট থাকে (), এবং এসটিডি :: ত্রুটি_কোডটি ফিরে আসে কিনা তা পরীক্ষা করে।
— এসএমগ্রিনফিল্ড

উদাহরণস্বরূপ প্রোগ্রামে, বিবৃতিটি 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()উভয় রিটার্ন প্ল্যাটফর্ম-নির্ভরশীল মান।
— জিম ফিশার

9

আপনি 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;
}

উদাহরণ আউটপুট (উবুন্টু ডাব্লু / ঝাঁকুনি):

$ ./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)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.