0

I want to read a whole file into a string. I am using Embarcadero C++Builder XE.

When I use the below code in my project, it is giving errors:

#include <iostream>
#include <iomanip>
#include <iterator>
#include <fstream>

std::ifstream in(Path);
std::string s((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
[ILINK32 Error] Error: Unresolved external 'std::_Mutex::_Lock()' 
[ILINK32 Error] Error: Unresolved external 'std::_Mutex::_Unlock()' 
[ILINK32 Error] Error: Unresolved external 'std::char_traits::eq_int_type(const int&, const int&)' 
[ILINK32 Error] Error: Unresolved external 'std::char_traits::not_eof(const int&)' 
[ILINK32 Error] Error: Unresolved external 'std::char_traits::to_char_type(const int&)'
[ILINK32 Error] Error: Unresolved external 'std::char_traits::eof()' 
[ILINK32 Error] Error: Unresolved external 'std::char_traits::to_int_type(const char&)' 
[ILINK32 Error] Error: Unresolved external 'std::locale::id::operator unsigned int()' 
[ILINK32 Error] Error: Unresolved external 'std::locale::name() const' 
[ILINK32 Error] Error: Unresolved external 'std::codecvt_base::codecvt_base(unsigned int)' 
[ILINK32 Error] Error: Unresolved external 'std::locale::facet::_Incref()' 
[ILINK32 Error] Error: Unresolved external 'std::ios_base::ios_base()' 
[ILINK32 Error] Error: Unresolved external 'std::ios_base::getloc() const' 
[ILINK32 Error] Error: Unresolved external 'std::ctype::_Getcat(std::locale::facet * *, std::locale *)' 
[ILINK32 Error] Error: Unresolved external 'std::ctype::widen(char) const' 
[ILINK32 Error] Error: Unresolved external 'std::ios_base::rdstate() const' 
[ILINK32 Error] Error: Unable to perform link

Any other solutions for reading a file into a string?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Pratik Mota
  • 73
  • 1
  • 11
  • 1
    Check your library path. Maybe some configuration problem with your standard library. – Devolus Jun 06 '17 at 11:45
  • @Devolus : Intsand of ifstream , Is there any soulution for reading file in Borland C++, RAD XE Embarcadero IDE ? – Pratik Mota Jun 06 '17 at 11:50
  • Your problem is not the standard library functions, it's your setup. As a sidenote, what you posted ist not a proper C++ code anyway, so you should post a full example anyway. – Devolus Jun 06 '17 at 11:51
  • @Devolus : I have Written here code which is giving error. My goal is to create Function which read whole large file data and return file content in to string variable. Project is very large and old, So I can not do major change in configuration/setup at this moment. – Pratik Mota Jun 06 '17 at 12:10
  • You have a linker error clearly showing that your setup is not correct. If you don't want to change it, then you have to live with that error. – Devolus Jun 06 '17 at 12:27
  • @Devolus : Ok, How can i identify which configuration has problem? This is Project Configuration of Project:: [Project Config Photo](http://yourprintscreen.com?m=201706060915445936ab0080957) – Pratik Mota Jun 06 '17 at 13:17
  • 1
    Why using iostream and fstream in VCL? You got `AnsiString` natively in VCL ... `TStrings` and `TMemo->Lines` can load entire text file with simple `LoadFromFile` method. File access is also simple use VCL: `FileOpen/FileCreate, FileSeek, FileRead/FileWrite, FileClose`. But to your errors your project is wrongly configured so may be you got some weird settings or corruption in project file ... sometimes creating new one helps. `Unresolved external` means you have included header but no code nor linked obj/lib/dll where it is – Spektre Jun 07 '17 at 08:25
  • @Spektre : Thank you very much. I am new in C++ VCL (Borland C++). Can you please give me Example in VCL for Reading a File and Save all content of File into String Variable, Please ? – Pratik Mota Jun 07 '17 at 09:09
  • @PratikMota added answer with some examples – Spektre Jun 07 '17 at 11:23
  • @Spektre : Really Thank you very much for your effort. It really helps me. – Pratik Mota Jun 07 '17 at 13:31
  • @PratikMota glad to be of help. Use code insight to find out more functions (also CTRL+F1 context help is good ...) you want to use... most of VCL functions support AnsiString from rendering text to File routines ... If you're new to Borland in case you are using BDS2006 or older take a look at this: [bds 2006 C hidden memory manager conflicts](https://stackoverflow.com/a/18016392/2521214) to avoid future headaches. Using CodeGuard in project options is cool for debugging... – Spektre Jun 07 '17 at 13:38
  • @Spektre : I am using Embarcadero® C++Builder® XE Version . Also Project is using VCL Library. – Pratik Mota Jun 07 '17 at 14:06
  • The code shown works fine for me in XE2. No linker errors. I would have used `std::istream_iterator` instead of `std::istreambuf_iterator`, though. – Remy Lebeau Jun 07 '17 at 19:13

1 Answers1

0

Lets create an empty VCL Form app and add a single TMemo control on it. The IDE will name it Memo1 automatically . The Memo object is a Text editor with 2 important properties:

  1. Memo1->Text

    Text is a System::String (automatically reallocable string class from VCL holding the whole text of the memo. String has a Length() function returning number of characters present, and each character is accessed using the [] operator like this (indexed from 1 !!!):

    String s = _D("123456"); // set some string to s
    int l = s.Length(); // get its length
    for (int i = 1; i <= l; i++) s[i] = '0'; // change all the chars to zeros
    Memo1->Text = s; // feed it to Memo
    

    There are tons of support functions inside String, the most important for you is formatted output:

    Memo1->Text = String().sprintf(_D("float number: %7.3f"), float(123.456));
    

    You can use String as your local variables, too:

    String s = _D("some text");
    Memo1->Text = s;
    

    Also for backward compatibility, if you need a char* for some functions, then just assign the String to an AnsiString and call its c_str() method:

    String s = _D("some text");
    AnsiString as = s;
    char *txt = as.c_str();
    

    But beware not to overwrite unallocated space, or use that pointer after any reallocation inside as, or after as goes out of scope. This is used mainly as input parameter for Win32 API functions, C functions, non-VCL LIBs/DLLs, etc.

  2. Memo1->Lines

    This is a TStrings class, which holds a dynamic array of Strings. In a TMemo, each element represents a line in the Text. You can dynamically add lines to Memo1 like this:

    Memo1->Lines->Add(_D("text 1"));
    Memo1->Lines->Add(_D("text 2"));
    Memo1->Lines->Add(_D("text 3"));
    

    You can load/save the whole Memo contents like this:

    Memo1->Lines->LoadFromFile("file1.txt");
    Memo1->Lines->SaveToFile("file1.txt");
    

    Any change in Memo1->Lines will also change Memo1->Text, and vice versa, as they both represent the same thing. You can have your Memo hidden (invisible) and still use it in case you do not want to show what are you doing ...

You can also load an entire file into a char[] buffer using file access functions without any VCL component, like this:

int hnd = FileOpen("file1.txt", fmOpenRead); // open file hnd>=0 if all OK
int siz = FileSeek(hnd, 2, 0); // point to end of file and return position = file size
FileSeek(hnd, 0, 0); // point back to start of file
char *txt = new char[siz+1] // allocate space for text and null terminator
FileRead(hnd, txt, siz); // load the file into memory at once
FileClose(hnd); // close file as we do not need it anymore

txt[siz] = 0; // add null termination just to be safe (text files do not contains zeros usually)
// do your thing with txt[siz]

delete[] txt;

Or:

TFileStream *strm = new TFileStream("file1.txt", fmOpenRead); // open file
int siz = strm->Size; // file size
char *txt = new char[siz+1] // allocate space for text and null terminator
strm->ReadBuffer(txt, siz); // load the file into memory at once
delete strm; // close file as we do not need it anymore

// do your thing with txt[siz]

delete[] txt;

Or:

TMemoryStream *strm = new TMemoryStream;
strm->LoadFromFile("file1.txt"); // open file

// do your thing with strm->Memory up to strm->Size bytes...

delete strm;

Unlike std::fstream, these will work for any file ... even if holding control codes.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • 1
    "*`Text` is `AnsiString`*" - no, it is not. It is a `System::String`, and in C++Builder 2009 and later, which includes XE, `System::String` is an alias for `System::UnicodeString`, not for `System::AnsiString`. As such, `char *txt = Memo1->Text.c.str();` will not compile (and it is dangerous anyway, as `txt` will be left pointing to invalid memory when the statement is complete). Also, `Memo1->Text[i]='0';` has no effect on the Memo, since it is modifying a temp `String` object returned by the `Text` getter. – Remy Lebeau Jun 07 '17 at 19:07
  • @RemyLebeau it should be `c_str()` of coarse nice catch but yore right `Text` property is not the same as `AnsiString` I am biased by my use of BCB and BDS and no experience with XE. will repair my mistake shortly – Spektre Jun 07 '17 at 20:32
  • "*You can have your Memo hidden (invisible) and still use it in case you do not want to show what are you doing*" - use the `TStringList` class for that instead. Don't use visual controls for non-visual work. – Remy Lebeau Jun 07 '17 at 20:50
  • @RemyLebeau what does `_D("")` ? it is some kind of support macro for `System::String` constants ? or it is to preserve unicode ? – Spektre Jun 08 '17 at 06:25
  • 1
    it is a support macro, yes. It ensures the literal uses the same charset encoding that `System::String` and `System::Char` use (currently UTF-16 in 2009+). It is similar to the `_T()` macro in the C standard lib for `_TCHAR` literals, and the `TEXT()` macro in the Win32 API for `TCHAR` literals. – Remy Lebeau Jun 08 '17 at 06:31