【问题标题】:Getting Error when reading file in string using C++Builder Project使用 C++Builder 项目读取字符串中的文件时出错
【发布时间】:2017-11-07 09:46:47
【问题描述】:

我想将整个文件读入一个字符串。我正在使用 Embarcadero C++Builder XE。

当我在我的项目中使用下面的代码时,它给出了错误:

#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 错误] 错误:未解析的外部 'std::_Mutex::_Lock()' [ILINK32 错误] 错误:未解析的外部 'std::_Mutex::_Unlock()' [ILINK32 错误] 错误:未解析的外部 'std::char_traits::eq_int_type(const int&, const int&)' [ILINK32 错误] 错误:未解析的外部 'std::char_traits::not_eof(const int&)' [ILINK32 错误] 错误:未解析的外部 'std::char_traits::to_char_type(const int&)' [ILINK32 错误] 错误:未解析的外部 'std::char_traits::eof()' [ILINK32 错误] 错误:未解析的外部 'std::char_traits::to_int_type(const char&)' [ILINK32 错误] 错误:未解析的外部 'std::locale::id::operator unsigned int()' [ILINK32 错误] 错误:未解析的外部 'std::locale::name() const' [ILINK32 错误] 错误:未解析的外部 'std::codecvt_base::codecvt_base(unsigned int)' [ILINK32 错误] 错误:未解析的外部 'std::locale::facet::_Incref()' [ILINK32 错误] 错误:未解析的外部 'std::ios_base::ios_base()' [ILINK32 错误] 错误:未解析的外部 'std::ios_base::getloc() const' [ILINK32 错误] 错误:未解析的外部 'std::ctype::_Getcat(std::locale::facet * *, std::locale *)' [ILINK32 错误] 错误:未解析的外部 'std::ctype::widen(char) const' [ILINK32 错误] 错误:未解析的外部 'std::ios_base::rdstate() const' [ILINK32 错误] 错误:无法执行链接

还有其他将文件读入字符串的解决方案吗?

【问题讨论】:

  • 检查您的库路径。您的标准库可能存在一些配置问题。
  • @Devolus : intsand of ifstream , 在 Borland C++, RAD XE Embarcadero IDE 中读取文件有什么解决方案吗?
  • 您的问题不是标准库函数,而是您的设置。作为旁注,您发布的内容无论如何都不是正确的 C++ 代码,因此您无论如何都应该发布一个完整的示例。
  • @Devolus :我在这里写了给出错误的代码。我的目标是创建读取整个大文件数据并将文件内容返回到字符串变量的函数。项目又大又旧,所以我目前无法对配置/设置进行重大更改。
  • 为什么在 VCL 中使用 iostream 和 fstream?您在 VCL 中原生获得了 AnsiString ...TStringsTMemo-&gt;Lines 可以使用简单的 LoadFromFile 方法加载整个文本文件。文件访问也很简单,使用VCL:FileOpen/FileCreate, FileSeek, FileRead/FileWrite, FileClose。但是对于您的错误,您的项目配置错误,因此可能是您在项目文件中有一些奇怪的设置或损坏......有时创建新的会有所帮助。 Unresolved external 表示您已包含标头但没有代码,也没有链接 obj/lib/dll

标签: c++ c++builder vcl c++builder-xe


【解决方案1】:

让我们创建一个空的 VCL 表单应用程序并在其上添加一个 TMemo 控件。 IDE 会自动将其命名为Memo1。 Memo 对象是一个具有 2 个重要属性的文本编辑器:

  1. Memo1-&gt;Text

    Text 是一个 System::String(来自 VCL 的自动重新分配字符串类,包含备忘录的整个文本。String 有一个 Length() 函数返回存在的字符数,并且每个像这样使用[] 运算符访问字符(从 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
    

    String 里面有很多支持功能,对你来说最重要的是格式化输出:

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

    您也可以使用String 作为局部变量:

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

    同样为了向后兼容,如果您需要 char* 来实现某些功能,那么只需将 String 分配给 AnsiString 并调用其 c_str() 方法:

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

    但请注意不要覆盖未分配的空间,或者在 as 内的任何重新分配之后或在 as 超出范围之后使用该指针。这主要用作 Win32 API 函数、C 函数、非 VCL LIB/DLL 等的输入参数。

  2. Memo1-&gt;Lines

    这是一个TStrings 类,其中包含Strings 的动态数组。在 TMemo 中,每个元素代表Text 中的一行。您可以像这样动态地将行添加到Memo1

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

    您可以像这样加载/保存整个备忘录内容:

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

    Memo1-&gt;Lines 中的任何更改也将更改Memo1-&gt;Text,反之亦然,因为它们都代表相同的东西。您可以将备忘录隐藏(不可见)并在您不想显示自己在做什么时仍然使用它...

您还可以使用不带任何 VCL 组件的文件访问函数将整个文件加载到 char[] 缓冲区中,如下所示:

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;

或者:

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;

或者:

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

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

delete strm;

std::fstream 不同,它们适用于任何文件......即使持有控制代码。

【讨论】:

  • "TextAnsiString" - 不,不是。它是 System::String,在 C++Builder 2009 及更高版本(包括 XE)中,System::StringSystem::UnicodeString 的别名,而不是 System::AnsiString 的别名。因此,char *txt = Memo1-&gt;Text.c.str(); 将无法编译(无论如何这很危险,因为当语句完成时,txt 将指向无效内存)。此外,Memo1-&gt;Text[i]='0'; 对备忘录没有影响,因为它正在修改由 Text getter 返回的临时 String 对象。
  • @RemyLebeau 它应该是 c_str() 的粗好捕获,但过去是正确的 Text 属性与 AnsiString 不一样我对 BCB 和 BDS 的使用有偏见,并且没有使用 XE 的经验.很快就会修复我的错误
  • "你可以隐藏你的备忘录(不可见)并且仍然使用它,以防你不想显示你在做什么" - 使用 TStringList 类相反。不要将视觉控件用于非视觉工作。
  • @RemyLebeau _D("") 是什么?它是System::String 常量的某种支持宏吗?还是保留unicode?​​span>
  • 它是一个支持宏,是的。它确保文字使用与 System::StringSystem::Char 使用的相同的字符集编码(当前 UTF-16 在 2009+ 中)。它类似于 C 标准库中用于 _TCHAR 文字的 _T() 宏,以及用于 TCHAR 文字的 Win32 API 中的 TEXT() 宏。
猜你喜欢
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
相关资源
最近更新 更多