Copy file.

J

Jason Heyes

Is this all it takes to copy a file in C++? Is there any error handling
missing in this function?

bool copy_file(std::string first, std::string second)
{
std::ifstream in(first.c_str());
if (!in.is_open())
return false;

std::eek:fstream out(second.c_str());
if (!out.is_open())
return false;

return out << in.rdbuf();
}

Thanks.
 
V

Victor Bazarov

Jason said:
Is this all it takes to copy a file in C++? Is there any error handling
missing in this function?

bool copy_file(std::string first, std::string second)

I'd probably still pass the arguments by ref to const.
{
std::ifstream in(first.c_str());
if (!in.is_open())
return false;

std::eek:fstream out(second.c_str());
if (!out.is_open())
return false;

return out << in.rdbuf();
}

Seems fine. Of course, returning 'false' gives no idea what has gone
wrong, only that something did go wrong.

V
 
R

Rolf Magnus

Victor said:
I'd probably still pass the arguments by ref to const.


Seems fine. Of course, returning 'false' gives no idea what has gone
wrong, only that something did go wrong.

Well, the standard streams don't provide much more anyway, other than
"failed" and "bad".
 
R

red floyd

Rolf said:
Victor Bazarov wrote:




Well, the standard streams don't provide much more anyway, other than
"failed" and "bad".

Yeah, but with failed and bad, you know what stream failed. With the
OP's code, you don't know whether you couldn't open the source or the
target stream.
 
R

red floyd

red said:
Yeah, but with failed and bad, you know what stream failed. With the
OP's code, you don't know whether you couldn't open the source or the
target stream.

Assuming we don't use exceptions, but are using return codes for success:

// assume necessary #includes
int myfunc(const std::string& first, const std::string& second)
{
std::ifstream in(first.c_str());
if (!in.is_open())
return 1;

std::eek:fstream out(second.c_str());
if (!out.is_open())
return 2;

return (out << in.rdbuf()) ? 0 : 3;
}

Then 0 is success, or the non-zero tells exactly where the error was
(though not *what* it was)
 
R

Rolf Magnus

red said:
Assuming we don't use exceptions, but are using return codes for success:

// assume necessary #includes
int myfunc(const std::string& first, const std::string& second)
{
std::ifstream in(first.c_str());
if (!in.is_open())
return 1;

std::eek:fstream out(second.c_str());
if (!out.is_open())
return 2;

return (out << in.rdbuf()) ? 0 : 3;
}

Then 0 is success, or the non-zero tells exactly where the error was
(though not *what* it was)

Instead of int and magic numbers, I'd use something like:

enum IOError
{
NoError,
CantOpenInput,
CantOpenOutput,
CantRead,
CantWrite
//... maybe other possible errors
};
 
P

Panjandrum

Victor said:
Seems fine. Of course, returning 'false' gives no idea what has gone
wrong, only that something did go wrong.

Does 'return out << in.rdbuf();' report a read error at all??
 
V

Victor Bazarov

Panjandrum said:
Does 'return out << in.rdbuf();' report a read error at all??

Yes. 'out << in.rdbuf()' will fail if extraction can't happen. That will
set the 'failbit' in 'out', which will cause the operator to return the
object with 'failbit' set, which when converted to 'bool' (through void*)
will give 'false'. IIRC that's the standard sequence of things happening.

V
 
J

Jason Heyes

Panjandrum said:
Does 'return out << in.rdbuf();' report a read error at all??

Come to think of it, no. When a read error occurs, the function treats it as
eof and stops. This is at least what I think it does. To report all errors I
would do this:

char c;
while (in.get(c))
out.put(c);

return in.eof() && out.good();
 
J

Jason Heyes

Victor Bazarov said:
Yes. 'out << in.rdbuf()' will fail if extraction can't happen. That will
set the 'failbit' in 'out', which will cause the operator to return the
object with 'failbit' set, which when converted to 'bool' (through void*)
will give 'false'. IIRC that's the standard sequence of things happening.

Oops. This contradicts what I just wrote. :p
 
V

Victor Bazarov

Jason said:
Oops. This contradicts what I just wrote. :p

Eh... I may not be entirely correct there either. Read 27.6.2.5.3 for me,
will you? It says (and I quote):
~~~~~
basic_ostream<charT,traits>& operator<<
(basic_streambuf<charT,traits>* sb);

6 Effects: If sb is null calls setstate(badbit) (which may throw
ios_base::failure).

7 Gets characters from sb and inserts them in *this. Characters are
read from sb and inserted until any of the following occurs:
— end-of-file occurs on the input sequence;
— inserting in the output sequence fails (in which case the character
to be inserted is not extracted);
— an exception occurs while getting a character from sb.

8 If the function inserts no characters, it calls setstate(failbit)
(which may throw ios_base::failure (27.4.4.3)). If an exception was
thrown while extracting a character, the function set failbit in
error state, and if failbit is on in exceptions() the caught
exception is rethrown.

9 Returns: *this.
~~~~~

Now, I think what I said about failing to read falls under the last bullet
item in paragraph 7. But if no exception is thrown, and the buffer goes
bad after reading and inserting several characters, the operation will be
flagged as successful, I guess.

That's where I'm wrong, probably. You still need to test 'in' when
returning the flag. Or not. Depending on what you consider a failure.

V
 
J

Jason Heyes

Victor Bazarov said:
Eh... I may not be entirely correct there either. Read 27.6.2.5.3 for me,
will you? It says (and I quote):
~~~~~
basic_ostream<charT,traits>& operator<<
(basic_streambuf<charT,traits>* sb);

6 Effects: If sb is null calls setstate(badbit) (which may throw
ios_base::failure).

7 Gets characters from sb and inserts them in *this. Characters are
read from sb and inserted until any of the following occurs:
— end-of-file occurs on the input sequence;
— inserting in the output sequence fails (in which case the character
to be inserted is not extracted);
— an exception occurs while getting a character from sb.

8 If the function inserts no characters, it calls setstate(failbit)
(which may throw ios_base::failure (27.4.4.3)). If an exception was
thrown while extracting a character, the function set failbit in
error state, and if failbit is on in exceptions() the caught
exception is rethrown.

9 Returns: *this.
~~~~~

Now, I think what I said about failing to read falls under the last bullet
item in paragraph 7. But if no exception is thrown, and the buffer goes
bad after reading and inserting several characters, the operation will be
flagged as successful, I guess.

That's where I'm wrong, probably. You still need to test 'in' when
returning the flag. Or not. Depending on what you consider a failure.

Also read paragraph 8. It says that if an exception is thrown while
extracting a character, the function sets failbit in error state. Since a
buffer only goes bad by throwing an exception, the function sets failbit on
a bad read. It looks like you were right.

Since 'out << in.rdbuf()' fails on all errors, we need not test 'in'.
 
V

Victor Bazarov

Jason said:
Victor Bazarov said:
[...]
8 If the function inserts no characters, it calls setstate(failbit)
(which may throw ios_base::failure (27.4.4.3)). If an exception was
thrown while extracting a character, the function set failbit in
error state, and if failbit is on in exceptions() the caught
exception is rethrown.

9 Returns: *this.
~~~~~

Now, I think what I said about failing to read falls under the last bullet
item in paragraph 7. But if no exception is thrown, and the buffer goes
bad after reading and inserting several characters, the operation will be
flagged as successful, I guess.

That's where I'm wrong, probably. You still need to test 'in' when
returning the flag. Or not. Depending on what you consider a failure.


Also read paragraph 8. It says that if an exception is thrown while
extracting a character, the function sets failbit in error state. Since a
buffer only goes bad by throwing an exception,

Is that guaranteed? I didn't see it. Where is it defined?
the function sets failbit on
a bad read. It looks like you were right.

Since 'out << in.rdbuf()' fails on all errors, we need not test 'in'.

I'll take your word for it, if you substantiate it with a quote from the
Standard :)

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
474,296
Messages
2,571,535
Members
48,279
Latest member
RedaBruno6

Latest Threads

Top