LINUX.ORG.RU

История изменений

Исправление saahriktu, (текущая версия) :

Присмотрелся ещё к этому блочному чтению. Оно по определению работает для элементов одинакового заранее известного веса в байтах. Что хорошо подходит как для однобайтных кодировок так и для UTF-16/UTF-32. С UTF-8 всё сложнее. Там уже точно без предварительного побайтного разбора не понять даже сколько символов в строке. В то время как в случае UTF-16/UTF-32 вес файла в байтах можно поделить на вес одного символа, а в случае однобайтных кодировок сколько байтов - столько и символов.

В С размер файла можно узнать и без предварительного побайтного чтения, да:

        FILE *fptr;
        long fsize;
        char *filebuf;

        fptr = fopen("test1.txt", "r");
        fseek(fptr, 0L, SEEK_END);
        fsize = ftell(fptr);
        rewind(fptr);
А в Паскале есть отдельная функция FileSize().

Вот так в Паскале выглядит чтение блоком в динамический массив однобайтных символов с последующим конвертированием из UTF-8 во внутреннее юникодное представление (UTF-16) и последующим выводом прочитанного уже из юникодной строки:

program filetest2;
    {$codepage UTF8}
uses strings, cwstring;
var
        fptr: File of Char;
        filebuf: PChar;
        unicodebuf: UnicodeString;
        fsize: Int64;
begin
        assign(fptr,'test1.txt');
        reset(fptr);
        fsize := FileSize(fptr);
        New(filebuf);
        GetMem(filebuf, fsize);
        BlockRead(fptr, filebuf^, fsize);
        filebuf[fsize - 1] := Chr(0);
        close(fptr);
        unicodebuf := UTF8Decode(filebuf); (* конвертируем байты из буфера в юникодную (UTF-16) строку *)
        Freemem(filebuf, fsize); (* старый буфер больше ненужен *)
        writeln(unicodebuf);
end.
Итоговая строка будет ровно нужного размера, а не, например, 256 символов если было прочитано всего 117. Работает этот вариант значительно быстрее, да, даже учитывая последующее конвертирование прочитанного.

Исходная версия saahriktu, :

Присмотрелся ещё к этому блочному чтению. Оно по определению работает для элементов одинакового заранее известного веса в байтах. Что хорошо подходит как для однобайтных кодировок так и для UTF-16/UTF-32. С UTF-8 всё сложнее. Там уже точно без предварительного побайтного разбора не понять даже сколько символов в строке. В то время как в случае UTF-16/UTF-32 вес файла в байтах можно поделить на вес одного символа, а в случае однобайтных кодировок сколько байтов - столько и символов.

В С размер файла можно узнать и без предварительного побайтного чтения, да:

        FILE *fptr;
        long fsize;
        char *filebuf;

        fptr = fopen("test1.txt", "r");
        fseek(fptr, 0L, SEEK_END);
        fsize = ftell(fptr);
А в Паскале есть отдельная функция FileSize().

Вот так в Паскале выглядит чтение блоком в динамический массив однобайтных символов с последующим конвертированием из UTF-8 во внутреннее юникодное представление (UTF-16) и последующим выводом прочитанного уже из юникодной строки:

program filetest2;
    {$codepage UTF8}
uses strings, cwstring;
var
        fptr: File of Char;
        filebuf: PChar;
        unicodebuf: UnicodeString;
        fsize: Int64;
begin
        assign(fptr,'test1.txt');
        reset(fptr);
        fsize := FileSize(fptr);
        New(filebuf);
        GetMem(filebuf, fsize);
        BlockRead(fptr, filebuf^, fsize);
        filebuf[fsize - 1] := Chr(0);
        close(fptr);
        unicodebuf := UTF8Decode(filebuf); (* конвертируем байты из буфера в юникодную (UTF-16) строку *)
        Freemem(filebuf, fsize); (* старый буфер больше ненужен *)
        writeln(unicodebuf);
end.
Итоговая строка будет ровно нужного размера, а не, например, 256 символов если было прочитано всего 117. Работает этот вариант значительно быстрее, да, даже учитывая последующее конвертирование прочитанного.