Как я могу писать в файл с помощью C ++ Buider в приложении Android? - PullRequest
0 голосов
/ 28 мая 2020

Я использую версию сообщества C ++ Builder (10.3) под Windows 10 для разработки приложения для работы на Samsung Galaxy A40.

Одна вещь, с которой я не могу работать, - это сохранение содержимого TListBox в файл.

Будучи новичком ie в 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);
}

Я что-то пропустил или что?

1 Ответ

1 голос
/ 29 мая 2020

Используйте класс 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));
}
...