0

我正在使用 Windows 10 下的 C++ builder (10.3) 社区版来开发在三星 Galaxy A40 上运行的应用程序。

我似乎无法工作的一件事是将 TListBox 的内容保存到文件中。

作为 Android 的新手,我不确定这个文件应该出现在哪里以及我需要什么权限。

我在函数中尝试了以下操作,将列表框的内容保存到文件中,但似乎无法打开要写入的文件。它总是返回 -1 :

int hFile;      // File Handle
int ByteCt=0;

hFile = FileOpen("Shopping.lst", fmOpenWrite);
if (hFile > 0)
{
    for (int i=0; i<ListBox1->Count; i++)
    {
        ByteCt+=FileWrite(hFile,ListBox1->Items[i].Text.c_str(),
                                ListBox1->Items->Strings[i].Length());
        ByteCt+=FileWrite(hFile,"\n\r",2);
    }
    FileClose(hFile);
}

有什么基本的我错过了,还是什么?

4

1 回答 1

1

使用System::Ioutils::TPath该类来确定您的应用可以访问的各种系统路径。有关详细信息,请参阅跨受支持目标平台的标准 RTL 路径函数。例如:

String FileName = TPath::Combine(TPath::GetDocumentsPath(), _D("Shopping.lst"));
hFile = FileOpen(FileName, fmOpenWrite);
// or: hFile = FileCreate(FileName);

但仅供参考,ListBox1->Items是 a TStrings,它有自己的SaveToFile()方法,例如:

ListBox1->Items->SaveToFile(FileName, TEncoding::UTF8);

你只是在复制SaveToFile()已经为你做的事情。因此,您不需要手动编写字符串 - 特别是因为您甚至没有正确编写它们!

String在 C++Builder 中是 的别名UnicodeString,它是一个 UTF-16 编码的字符串。它Length()指定它包含的WideCharchar16_t在 Android 上)元素的数量,但FileWrite()仅处理原始字节。所以你只写了每个的 1/2 字节,String因为sizeof(WideChar)=2. 而且,"\n\r"也不是一个有效的换行符。您需要使用"\r\n"or just "\n",或使用 RTL 的sLineBreak全局常量。但更糟糕的是,您试图以String原始 UTF-16 格式编写 s,但以 8 位 ANSI/UTF-8 格式编写换行符。因此,您最终会得到一个混合编码文件,许多软件将无法正确读取该文件。

如果您真的想String手动编写 s ,那么它需要看起来更像这样:

int hFile;      // File Handle
int ByteCt=0, BytesWritten;

hFile = FileOpen(FileName, fmOpenWrite);
// or: hFile = FileCreate(FileName);
if (hFile > 0)
{
    for (int i=0; i < ListBox1->Count; i++)
    {
        String s = ListBox1->Items->Strings[i];
        BytesWritten = FileWrite(hFile, s.c_str(), s.Length() * sizeof(WideChar));
        if (BytesWritten < 0) break;
        ByteCt += BytesWritten;
        BytesWritten = FileWrite(hFile, _D("\r\n"), sizeof(WideChar) * 2);
        if (BytesWritten < 0) break;
        ByteCt += BytesWritten;

        /* alternatively:
        UTF8String s = ListBox1->Items->Strings[i];
        BytesWritten = FileWrite(hFile, s.c_str(), s.Length());
        if (BytesWritten < 0) break;
        ByteCt += BytesWritten;
        BytesWritten = FileWrite(hFile, "\r\n", 2);
        if (BytesWritten < 0) break;
        ByteCt += BytesWritten;
        */
    }
    FileClose(hFile);
}

但是,不要FileWrite()直接使用,而是考虑使用TStreamWriter,例如:

int ByteCt=0;

std::unique_ptr<TStreamWriter> File(new TStreamWriter(FileName, TEncoding::UTF8));
// or: auto File = std::make_unique<TStreamWriter>(FileName, TEncoding::UTF8);

for (int i=0; i < ListBox1->Count; i++)
{
    String s = ListBox1->Items->Strings[i];
    File->WriteLine(s);
    ByteCt += (File->Encoding->GetByteCount(s) + File->Encoding->GetByteCount(File->NewLine));
}
于 2020-05-28T21:30:51.310 回答