আইফ্রিম ওপেন ব্যর্থ হলে কীভাবে ত্রুটি বার্তা পাবেন 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.