ifstream f;
f.open(fileName);
if ( f.fail() )
{
// I need error message here, like "File not found" etc. -
// the reason of the failure
}
How to get error message as string?
László Papp
51.1k39 gold badges110 silver badges135 bronze badges
asked Jun 27, 2013 at 7:51
5
Every system call that fails update the errno
value.
Thus, you can have more information about what happens when a ifstream
open fails by using something like :
cerr << "Error: " << strerror(errno);
However, since every system call updates the global errno
value, you may have issues in a multithreaded application, if another system call triggers an error between the execution of the f.open
and use of errno
.
On system with POSIX standard:
errno is thread-local; setting it in one thread does not affect its
value in any other thread.
Edit (thanks to Arne Mertz and other people in the comments):
e.what()
seemed at first to be a more C++-idiomatically correct way of implementing this, however the string returned by this function is implementation-dependant and (at least in G++’s libstdc++) this string has no useful information about the reason behind the error…
S.R
2,1911 gold badge21 silver badges32 bronze badges
answered Jun 27, 2013 at 9:02
5
You could try letting the stream throw an exception on failure:
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()
, however, does not seem to be very helpful:
- I tried it on Win7, Embarcadero RAD Studio 2010 where it gives «ios_base::failbit set» whereas
strerror(errno)
gives «No such file or directory.» - On Ubuntu 13.04, gcc 4.7.3 the exception says «basic_ios::clear» (thanks to arne)
If e.what()
does not work for you (I don’t know what it will tell you about the error, since that’s not standardized), try using std::make_error_condition
(C++11 only):
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";
}
answered Jun 27, 2013 at 8:19
Arne MertzArne Mertz
23.9k2 gold badges51 silver badges89 bronze badges
9
Following on @Arne Mertz’s answer, as of C++11 std::ios_base::failure
inherits from system_error
(see http://www.cplusplus.com/reference/ios/ios_base/failure/), which contains both the error code and message that strerror(errno)
would return.
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;
}
This prints No such file or directory.
if fileName
doesn’t exist.
answered Apr 14, 2016 at 4:35
rthurrthur
1,4361 gold badge15 silver badges15 bronze badges
5
You can also throw a std::system_error
as shown in the test code below. This method seems to produce more readable output than 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;
}
Example output (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)
answered Jun 30, 2018 at 22:27
ɲeuroburɳɲeuroburɳ
6,9103 gold badges23 silver badges22 bronze badges
The std::system_error
example above is slightly incorrect. std::system_category()
will map the error codes from system’s native error code facility. For *nix, this is errno
. For Win32, it is GetLastError()
. ie, on Windows, the above example will print
failed to open C:pathtoforbidden: The data is invalid
because EACCES is 13 which is the Win32 error code ERROR_INVALID_DATA
To fix it, either use the system’s native error code facility, eg on Win32
throw new std::system_error(GetLastError(), std::system_category(), "failed to open"+ filename);
Or use errno and std::generic_category()
, eg
throw new std::system_error(errno, std::generic_category(), "failed to open"+ filename);
answered Feb 16, 2021 at 17:54
void open( const char* filename, |
(1) | |
void open( const std::filesystem::path::value_type* filename, |
(2) | (since C++17) |
void open( const std::string& filename, |
(3) | (since C++11) |
void open( const std::filesystem::path& filename, |
(4) | (since C++17) |
Opens and associates the file with name filename with the file stream.
Calls clear() on success. Calls setstate(failbit) on failure.
1,2) Effectively calls rdbuf()—>open(filename, mode) (see std::basic_filebuf::open for the details on the effects of that call). Overload (2) is only provided if std::filesystem::path::value_type
is not char. (since C++17)
3,4) Effectively calls (1,2) as if by open(filename.c_str(), mode).
[edit] Parameters
filename | — | the name of the file to be opened | ||||||||||||||||
mode | — | specifies stream open mode. It is a BitmaskType, the following constants are defined:
|
[edit] Return value
(none)
[edit] Example
#include <string> #include <fstream> #include <iostream> int main() { std::string filename = "example.123"; std::fstream fs; fs.open(filename); if (!fs.is_open()) { fs.clear(); fs.open(filename, std::ios::out); // create file fs.close(); fs.open(filename); } std::cout << std::boolalpha; std::cout << "fs.is_open() = " << fs.is_open() << 'n'; std::cout << "fs.good() = " << fs.good() << 'n'; }
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 22 | C++98 | it was unclear how error state changes upon a successful open | the error state is unchanged |
LWG 409 | C++98 | the error state was unchanged upon a successful open | it is cleared[1] |
- ↑ The resolution of LWG issue #22 is overriden.
[edit] See also
checks if the stream has an associated file (public member function) [edit] |
|
closes the associated file (public member function) [edit] |
|
opens a file and configures it as the associated character sequence (public member function of std::basic_filebuf<CharT,Traits> ) [edit]
|
It’s quite common that errors may occur during file operations. There may have different reasons for arising errors while working with files. The following are the common problems that lead to errors during file operations.
- When trying to open a file for reading might not exist.
- When trying to read from a file beyond its total number of characters.
- When trying to perform a read operation from a file that has opened in write mode.
- When trying to perform a write operation on a file that has opened in reading mode.
- When trying to operate on a file that has not been open.
During the file operations in C++, the status of the current file stream stores in an integer flag defined in ios class. The following are the file stream flag states with meaning.
Flag Bit | Meaning |
---|---|
badbit | 1 when a fatal I/O error has occurred, 0 otherwise. |
failbit | 1 when a non-fatal I/O error has occurred, 0 otherwise |
goodbit | 1 when no error has occurred, 0 otherwise |
eofbit | 1 when end-of-file is encountered, 0 otherwise. |
We use the above flag bits to handle the errors during the file operations.
Error Handling During the File Operations in C++
The C++ programming language provides several built-in functions to handle errors during file operations. The file error handling
The following are the built-in functions to handle file errors.
Function | Return Value |
---|---|
int bad() | It returns a non-zero (true) value if an invalid operation is attempted or an unrecoverable error has occurred. Returns zero if it may be possible to recover from any other error reported and continue operations. |
int fail( ) | It returns a non-zero (true) value when an input or output operation has failed. |
int good() | It returns a non-zero (true) value when no error has occurred; otherwise returns zero (false). |
int eof( ) | It returns a non-zero (true) value when end-of-file is encountered while reading; otherwise returns zero (false). |
int bad( )
The bad( ) function returns a non-zero (true) value if an invalid operation is attempted or an unrecoverable error has occurred. Returns zero if it may be possible to recover from any other error reported and continue operations.
Let’s look at the following code.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream file;
file.open("my_file.txt", ios::out);
string data;
file >> data;
if(!file.bad()){
cout << "Operation not success!!!" << endl;
cout << "Status of the badbit: " << file.bad() << endl;
}
else {
cout << "Data read from file - " << data << endl;
}
return 0;
}
int fail( )
The fail( ) function returns a non-zero value when an input or output operation has failed.
Let’s look at the following code.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream file;
file.open("my_file.txt", ios::out);
string data;
file >> data;
if(file.fail()){
cout << "Operation not success!!!" << endl;
cout << "Status of the failbit: " << file.fail() << endl;
}
else {
cout << "Data read from file - " << data << endl;
}
return 0;
}
int eof( )
The eof( ) function returns a non-zero (true) value when end-of-file is encountered while reading; otherwise returns zero (false).
Let’s look at the following code.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream file;
file.open("my_file.txt", ios::in);
string data;
while(!file.eof()){
file >> data;
cout << "data read: " << data << " | eofbit: " << file.eof() << endl;
}
return 0;
}
int good( )
The good( ) function returns a non-zero (true) value when no error has occurred; otherwise returns zero (false).
Let’s look at the following code.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream file;
file.open("my_file.txt", ios::in);
cout << "goodbit: " << file.good() << endl;
string data;
cout << endl << "Data read from file:" << endl;
while(!file.eof()){
file >> data;
cout << data << " ";
}
cout << endl;
return 0;
}
int clear( )
The clear( ) function used to reset the error state so that further operations can be attempted.
Использование Visual Studio 2012 & со свойствами проекта:
- Свойства конфигурации: Общие: Проект по умолчанию: Набор символов:
Не установлен - Свойства конфигурации: C ++: Язык: обрабатывать WChar_t как встроенный
Тип: нет
Я использую ofstream со следующим фрагментом кода:
Примечание: путь «C: data» действителен для этого примера
ofstream fexp;
fexp.open("c:datatest.txt", ios::out|ios::binary|ios::app);
fexp << "writing some text to file with append in binary" << endl;
fexp.flush();
fexp.close();
Если файл отсутствует в каталоге, файл будет открыт, текст будет записан и т. Д. Если файл уже существовал, файл не открывается, не записывается и т. Д. Не возникло никаких исключений и не был найден код ошибки (в errno ). При отладке внутреннего метода open () я обнаружил некоторое внутреннее открытие
звонки пытались скопировать строку имени файла в тип wchar_t и закрылись с внутренней ошибкой 13 (поиск констант MS = Open Aborted).
MBCS устарела, поэтому я не хочу устанавливать это. Единственный другой вариант — это Unicode, который нарушает половину моих изменений. Почему я не могу использовать библиотеку std io ?? !!!
Что еще страннее, у меня была некоторая часть этой работы со вторым переключателем на нет с 1-м набором MBCS. Несмотря на то, что код работал во многих местах, связанных с графическими интерфейсами, такими как CEdit, у меня было много лишнего кода для преобразования из CString в строку, если бы мне пришлось. Если в сущности представление CString представляет собой const char *, что несколько близко к LPCTSTR (не совсем). Это «ДОЛЖЕН«быть несколько»ПРОСТО«конвертировать из CString в строку. Это не потому, что ненужный осложнения переключений между UTF-8 и UTF-16, которыми я не занимаюсь. Я хочу, чтобы мой символ был СТРОГО 1 БАЙТ.
Какой самый близкий путь через это безумие? Должен ли я вернуться обратно к MBCS (хотя и устарел) и изменить все методы контейнера с
GetWindowText () для GetWindowTextA () например или отказаться от использования потоков в Visual Studio, или что ???
Пожалуйста, посоветуйте, если можете … Любая помощь будет принята с благодарностью. Благодарю.
Бешеный пес
ps: Пожалуйста, не беспокойтесь, чтобы превратить меня в полную среду Wide в моем коде, когда мой продукт не будет продаваться в Азии или Аравии.
pps: последнее замечание, которое я получил, потому что я заметил, что моя первоначальная установка Visual Studio 2012 по умолчанию установлена на MBCS.
0
Решение
Как уже отмечали другие, ваша проблема вызвана побегом ,
"c:datatest.txt"
Должно быть
"c:\data\test.txt"
Вы можете узнать больше о escape-последовательностях Вот.
Чтобы избежать путаницы, вы можете использовать /
вместо в ваших файловых путях.
"C:/data/test.txt"
1
Другие решения
Тем, кто все еще следит за этим, через два с половиной дня я понял, что происходит. Извините за задержку в публикации этого. На самом деле, я полностью забыл об этом.
Это был случай разрешения доступа к родительскому каталогу. Не просто регулярное отрицание. Я имею в виду особый отказ в открытии файла, чтобы добавить к нему (открыть с добавлением). Обычно вы даже не видите эти настройки, если не перейдете в расширенный режим на вкладке безопасности окна свойств файла или каталогов. Даже тогда вы должны сделать пару дополнительных шагов. Поэтому в каталоге над каталогом, в котором находился мой файл, был установлен этот параметр (по какой-то невероятной причине). Тем не менее, я
проверил все три метода работы сейчас (fopen()
, CFile.open()
, stream.open()
).
Спасибо за все идеи, я многому научился, чего раньше не знал. Некоторые идеи были великолепны.
Бешеный пес
0