-
Есть кусок кода который получает от PHP какой-то текст в UTF8. Получаю данные вот таким образом:
HTTPRecvBuffer: array [0..512] of char;
......................
while True do
begin
Retries:=0;
repeat
lSucc:= InternetQueryDataAvailable(hFile, BytesRead, 0, 0);
if NOT lSucc then Sleep(SleepTime);
Inc(Retries);
until lSucc OR (Retries <= Attempts);
InternetReadFile(hFile, @HTTPRecvBuffer, BufferSize, BytesRead);
if BytesRead = 0 then break;
FOutStream.WriteBuffer(HTTPRecvBuffer, BytesRead);
ProgBytesReaded:=ProgBytesReaded+BytesRead;
if Assigned(OnProgress) then
OnProgress(Self, ProgBytesReaded, ProgTotalBytes);
if FTerminate then Break;
end;
из потока пытаюсь читать вот так:
function StreamToString(aStream: TStream): string;
var
SS: TStringStream;
begin
if aStream <> nil then
begin
SS := TStringStream.Create('');
try
SS.CopyFrom(aStream, 0);
Result := SS.DataString;
finally
SS.Free;
end;
end else Result := '';
end;
......................
ShowMessage(StreamToString(FOutStream));
......................
Но в результате русского текста не вижу, корявые символы получаются.. вот ещё на всякий случай результаты снифа полученной инфы: HTTP/1.1 200 OK\r\n
Date: Mon, 06 Feb 2012 10:21:39 GMT\r\n
Content-Type: text/html\r\n
Connection: keep-alive\r\n
Content-Length: 151\r\n
Line-based text data: text/html
<errcode>101</errcode>\n
[truncated] <errmsg>\320\240\320\265\320\263\320\270\321\201\321\202\321\200\320\260\321\206 \320\270\320\276\320\275\320\275\321\213\320\271 \320\272\320\273\321\216\321\207 \321\203\320\266\320\265 \320\270\321\201\320\277\320\276\320\273 Если урл вбить в адресной строке браузера и поставить вручную кодировку UTF8, то вижу именно то что отправил из PHP скрипта, т.е. с серверной частью проблем нет.
-
Добавлю ещё одно уточнение, код нормально работает с ANSI кодировкой, но сейчас возникла необходимость добавить мультиязыковую поддержку, поэтому переходим на UTF кодировку с которой и вылезли все вышеперечисленные проблемы.
-
Исходное сообщение которое не могу получить: <errcode>101</errcode> <errmsg>Регистрационный ключ уже используется на другом компьютере.</errmsg>
-
> Result := SS.DataString; Result := Utf8ToAnsi(SS.DataString); ?
> Если урл вбить в адресной строке браузера и поставить вручную кодировку UTF8, то вижу именно то что отправил из PHP скрипта, т.е. с серверной частью проблем нет. как раз есть, если приходится вручную кодировку указывать значит сервер не отдает в какой кодировке контент.
-
> HTTPRecvBuffer: array [0..512] of char; ? unf8 для русского текста раза в 3 длиннее.
-
как раз есть, если приходится вручную кодировку указывать значит сервер не отдает в какой кодировке контент. а каким образом он об этом сообщает? как такого текста html нет, серверная и клиентская часть общается между собой подобием xml Result := Utf8ToAnsi(SS.DataString); не помогает ? unf8 для русского текста раза в 3 длиннее данные блочно получаются, 512 размер блока while True do begin .... читаем по 512 байт, если больше нечего получать, выходим из цикла if BytesRead = 0 then break;
-
> sniknik © (06.02.12 15:12) [4] > > HTTPRecvBuffer: array [0..512] of char; > ? unf8 для русского текста раза в 3 длиннее.
Может и в 6, как карты лягут. Не говоря уже о том, что массив статический.
-
> Result := Utf8ToAnsi(SS.DataString); > не помогает значит преобразование уже было. поможет только для реально unf8, а не с уже попыткой, неправильной, его в юникод например преобразовать.
> Может и в 6 специально написал, для "русского текста", он насколько помню 3х-максимум 4х символьный.
-
Это что за числа?
-
Не пойму в чём вопрос по поводу длины.. Допустим я с сервера отправляю текст в 60 раз длинее чем 512, т.е. 30720 байт. Блоками по 512 байт за 60 итераций цикла, я сохраняю всё сообщение в поток FOutStream (WriteBuffer(HTTPRecvBuffer, BytesRead)), а потом всё 30720 байт пытаюсь сконвертировать из UTF8. В чём вопрос объясните? Проблема не в том как мне это прочитать, читается всё нормально там, вопрос в том как получить читаемый текст. Даже если всего лишь 512 байт прочитаются я получу хотя бы несколько букв моей посылки
-
> denkop > Result := Utf8ToAnsi(SS.DataString); не помогает
версия Delphi какая?
> sniknik > специально написал, для "русского текста", он насколько помню 3х-максимум 4х символьный.
буквы 2x-симвоьные
-
> Блоками по 512 байт а массив типа char... не всегда равно.
-
> версия Delphi какая? Delphi XE
> а массив типа char... не всегда равно. что именно не всегда равно? и причём массив char?
-
> версия Delphi какая? Delphi XE
> а массив типа char... не всегда равно. что именно не всегда равно? и причём массив char?
-
> denkop в ХЕ char string и, наверно, stringstream в 2 раза жирнее, тебе не нужен stringsteam, надо любым способом сырые байты перегнать в string или ansistring.
-
> что именно не всегда равно? byte = 1 байт, char = 2 байта. например.
> Delphi XE тогда у тебя все к юникоду, если ничего не делать, преобразовывается. и utf8 насколько понимаю (до сих пор на D7) автоматом поддерживается.
-
-
проблема решена, вместо: > SS := TStringStream.Create(''); нужно было явно указать кодировку для TStringStream: > SS := TStringStream.Create('', CP_UTF8);
> byte = 1 байт, char = 2 байта. не имеет абсолютно никакого отношения к вопросу, т.к. в конечном итоге мы получили в одной строке именно 30720 байт, ровно столько, сколько отправил сервер, а какой размер буфера использовался чтобы получить эти 30720 байт от сервера в моём вопросе не имеет никакого значения
> тогда у тебя все к юникоду, если ничего не делать, преобразовывается. и utf8 насколько понимаю (до сих пор на D7) автоматом поддерживается. при этом без CP_UTF8 работать не стало! автоматом в том случае когда есть явный контекст в виде используемых переменных ранее, а здесь данные приходят с сервера который может хоть на китайском прислать результат и автоматом одним здесь не обойдёшься
-
> Sha (06.02.2012 16:44:10) [10]
Двухсимволные если их первых 64К Юникода, дальше в силу вступают 3 и 4 символьные, и так до миллиона первых символов Юникода
-
> denkop (06.02.2012 16:54:13) [13]
А то что в твоем случае жно 512 символов.
-
> sniknik (06.02.2012 17:06:15) [15]
Автоматом 2009+, даже думать не нужно, есть такой тип ка UTFString, а вот пытаться преобразовать в ANSI это откровенная глупость
-
> Anatoly Podgoretsky © (06.02.12 17:17) [18] > Двухсимволные если их первых 64К Юникода, дальше в силу вступают 3 и 4
в первых 64к есть 1-, 2- и 3-символьные, а русские буквы - строго 2-символьные
|