Используйте класс System::Ioutils::TPath
, чтобы определить различные системные пути, к которым ваше приложение может получить доступ. Подробнее см. Стандартные функции пути RTL для поддерживаемых целевых платформ . Например:
String FileName = TPath::Combine(TPath::GetDocumentsPath(), _D("Shopping.lst"));
hFile = FileOpen(FileName, fmOpenWrite);
// or: hFile = FileCreate(FileName);
Но, к вашему сведению, ListBox1->Items
- это TStrings
, у которого есть собственный метод SaveToFile()
, например:
ListBox1->Items->SaveToFile(FileName, TEncoding::UTF8);
Вы просто дублируете то, что SaveToFile()
уже делает для вас. Таким образом, вам не нужно писать строки вручную - тем более, что вы даже не пишете их правильно!
String
в C ++ Builder - это псевдоним для UnicodeString
, который представляет собой строку в кодировке UTF-16. Его Length()
определяет количество элементов WideChar
(char16_t
на Android), которые он содержит, но FileWrite()
работает только с необработанными байтами. Таким образом, вы записываете только 1/2 байта каждого String
с sizeof(WideChar)=2
. Кроме того, "\n\r"
также не является допустимым разрывом строки. Вам нужно будет использовать "\r\n"
или просто "\n"
или использовать глобальную константу RTL sLineBreak
. Но что еще хуже, вы пытаетесь записать String
s в их исходном формате UTF-16, но пишете разрывы строк в 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));
}