|
Prev: realloc's design
Next: SHA1
From: Paul Rosen on 17 Nov 2005 19:09 I have some old code (that works just fine!), but it uses FILE* and CString to read the contents of a relatively small file to a string in a single call. Its signature is: bool ReadFileToString(const CString& csFilename, CString& csContents); I'd like to change that, though, to use std::string and std:ifstream. The routine should be as efficient as possible with little copying of data. I'd like the signature of the routine to be: bool ReadFileToString(const std::string& strFilename, std::string& strContents); The approach that occurs to me is: 0) open the file in binary mode 1) seek to the end of the file to get the length 2) resize a stack variable of type std::vector<char> to the length 3) seek back to the beginning 4) read that many characters into the vector 5) copy the contents of the vector into strContents, translating \r\n into \n There has got to be a better way, particularly since the companion routine was so easy. void WriteStringToFile(const std::string& strFilename, const std::string& strContents) { std::ifstream ifs(strFilename); ifs << strContents; } Any suggestions? [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Carl Barron on 18 Nov 2005 05:28 In article <l63ff.1310$wf.1155(a)newsread3.news.atl.earthlink.net>, Paul Rosen <prosen(a)fte.com> wrote: > I have some old code (that works just fine!), but it uses FILE* and > CString to read the contents of a relatively small file to a string in a > single call. Its signature is: > > bool ReadFileToString(const CString& csFilename, CString& csContents); > > I'd like to change that, though, to use std::string and std:ifstream. > The routine should be as efficient as possible with little copying of data. > > I'd like the signature of the routine to be: > > bool ReadFileToString(const std::string& strFilename, std::string& > strContents); > > The approach that occurs to me is: > > 0) open the file in binary mode > 1) seek to the end of the file to get the length > 2) resize a stack variable of type std::vector<char> to the length > 3) seek back to the beginning > 4) read that many characters into the vector > 5) copy the contents of the vector into strContents, translating \r\n > into \n > > There has got to be a better way, particularly since the companion > routine was so easy. > > void WriteStringToFile(const std::string& strFilename, const > std::string& strContents) > { > std::ifstream ifs(strFilename); > ifs << strContents; > } quickest to write: inline void file_to_string(std::istream &in,std::string &out) { std::copy ( std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::back_inserter(out) ); } [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Pramod on 18 Nov 2005 08:26 Try this void WriteStringToFile(const std::string& strFilename, const std::string& strContents) { std::ifstream ifs(strFilename); strFilename = std::string ( std::istreambuf_iterator<char>( ifs ), std::istreambuf_iterator<char>( ) ); } [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Yuri Khan on 18 Nov 2005 08:25 Paul Rosen wrote: > I have some old code (that works just fine!), but it uses FILE* and > CString to read the contents of a relatively small file to a string in a > single call. Its signature is: > I'd like the signature of the routine to be: > > bool ReadFileToString(const std::string& strFilename, std::string& > strContents); > > The approach that occurs to me is: > > 0) open the file in binary mode > 1) seek to the end of the file to get the length > 2) resize a stack variable of type std::vector<char> to the length > 3) seek back to the beginning > 4) read that many characters into the vector > 5) copy the contents of the vector into strContents, translating \r\n > into \n > > There has got to be a better way, particularly since the companion > routine was so easy. If you can live with the fact that the target string will be reallocated several times (usually log(N) times, where N is the file size), you might want to try std::getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str, charT delim), passing in a delimiter character that is guaranteed not to occur in the file. Seeing as you want to translate \r\n into \n, I assume your file is text, so the NUL character (0x00) will probably suit you. [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: G.J. Giezeman on 18 Nov 2005 08:24
Paul Rosen wrote: > I have some old code (that works just fine!), but it uses FILE* and > CString to read the contents of a relatively small file to a string in a > single call. Its signature is: > > bool ReadFileToString(const CString& csFilename, CString& csContents); > > I'd like to change that, though, to use std::string and std:ifstream. > The routine should be as efficient as possible with little copying of data. > > I'd like the signature of the routine to be: > > bool ReadFileToString(const std::string& strFilename, std::string& > strContents); My suggestion: use the istreambuf_iterator. #include <fstream> #include <string> #include <iterator> bool ReadFileToString(const std::string& strFilename, std::string& strContents) { typedef std::istreambuf_iterator<char> stream_iter; std::ifstream is(strFilename.c_str()); if (!is) return false; strContents.assign(stream_iter(is),stream_iter()); return true; } > There has got to be a better way, particularly since the companion > routine was so easy. > > void WriteStringToFile(const std::string& strFilename, const > std::string& strContents) > { > std::ifstream ifs(strFilename); > ifs << strContents; > } I guess you meant using an ofstream here. [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |