如何将UTF8字符的StringStream加载到Android中的StringList中?
我做了一个简单的Indy HTTP GET函数,使用Windows客户端和服务器可以很好地工作,但是在Android中使用客户端时,由于使用UTF8字符而尝试将StringStream加载到StringList时,它停滞不前。如何将UTF8字符的StringStream加载到Android中的StringList中?
客户端(线程内):
var
ss:TStringStream;
st:TStringList;
begin
ss := TStringStream.Create('',TEncoding.UTF8);
IdHTTP1.Request.UserAgent := 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; MAAU)';
IdHTTP1.Get('http://motoristaajudante.ddns.net:37009/-23.671373,-046.700072',ss);
ss.Position := 0;
st := TStringList.Create;
st.LoadFromStream(ss); // <<< Crash in this line on Android, on Windows works fine
end;
服务器:
procedure TfrmMain.DownloadServer9CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); // Indy HTTP Server
var
Enviar:TStringList;
EnvioStream:TMemoryStream;
begin
try
Enviar := TStringList.Create;
Enviar.Add('11111111111111111111111111111111111111 0006 Jardim São Caetano|Fique mais próximo'+' do conjunto de prédios do Jardim São Caetano para aumentar as chances de receber um chamado. Tente parar exatamente onde é apontado no mapa. ¬iMobby¬d19/09/2017 00:00:00 2359235923592359 0012 000 23590 ¬§');
Enviar.Add('11111111111111111111111111111111111111 0006 Jardim São Caetano|Fique mais próximo'+' do conjunto de prédios do Jardim São Caetano para aumentar as chances de receber um chamado. Tente parar exatamente onde é apontado no mapa. ¬iMobby¬d19/09/2017 00:00:00 2359235923592359 0012 000 23590 ¬§');
Enviar.Add('11111111111111111111111111111111111111 0006 Jardim São Caetano|Fique mais próximo'+' do conjunto de prédios do Jardim São Caetano para aumentar as chances de receber um chamado. Tente parar exatamente onde é apontado no mapa. ¬iMobby¬d19/09/2017 00:00:00 2359235923592359 0012 000 23590 ¬§');
Enviar.Add('@');
// if switching the above strings to only numbers and letters then the client loads the StringList normally on Android
EnvioStream := TMemoryStream.Create;
Enviar.SaveToStream(EnvioStream);
AResponseInfo.ContentStream := EnvioStream;
AResponseInfo.WriteContent;
finally
Enviar.Free;
Enviar := nil;
EnvioStream.Free;
EnvioStream := nil;
end;
尽管如此,如果切换到所有发送串数字和字母,然后在客户端加载的StringList通常在Android上,如果我只放一个UTF8字符就会崩溃。如何解决这个问题?
编辑:消息是“目标多字节代码页中不存在Unicode字符的映射”。
在这种情况下,您忽略了TEncoding.UTF8
的使用。
TStringStream
是D2009 +中的字节流。您传递给其构造函数的TEncoding
从不使用(构造函数的输入字符串为空,并且根本不使用DataString
属性)。因此,此代码正在下载原始字节,然后使用进行解析,然后将这些字节原样加载到TStringList
中,这只是发生在Android上的UTF-8,但在Windows上不是UTF-8。如果数据实际上不是UTF-8,则将其解码为UTF-8将失败。
如果你知道一个事实,下载数据在UTF-8编码,则需要明确指定调用LoadFromStream()
时:
var
ms: TMemoryStream;
st: TStringList;
begin
st := TStringList.Create;
try
ms := TMemoryStream.Create;
try
//...
IdHTTP1.Get('http://motoristaajudante.ddns.net:37009/-23.671373,-046.700072', ms);
ms.Position := 0;
st.LoadFromStream(ms, TEncoding.UTF8); // <-- here
finally
ms.Free;
end;
// use st as needed...
finally
st.Free;
end;
end;
但是,如果你不知道数据是否是UTF-8还是不行,你最好让TIdHTTP
解码为你,基于HTTP服务器如何描述它的编码:
var
st: TStringList;
begin
st := TStringList.Create;
try
//...
st.Text := IdHTTP1.Get('http://motoristaajudante.ddns.net:37009/-23.671373,-046.700072');
// use st as needed...
finally
st.Free;
end;
end;
在服务器端,你应该做更多的东西像这样的而不是确保数据以UTF-8编码:
procedure TfrmMain.DownloadServer9CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); // Indy HTTP Server
var
Enviar: TStringList;
EnvioStream: TMemoryStream;
begin
Enviar := TStringList.Create;
try
Enviar.Add('11111111111111111111111111111111111111 0006 Jardim São Caetano|Fique mais próximo'+' do conjunto de prédios do Jardim São Caetano para aumentar as chances de receber um chamado. Tente parar exatamente onde é apontado no mapa. ¬iMobby¬d19/09/2017 00:00:00 2359235923592359 0012 000 23590 ¬§');
Enviar.Add('11111111111111111111111111111111111111 0006 Jardim São Caetano|Fique mais próximo'+' do conjunto de prédios do Jardim São Caetano para aumentar as chances de receber um chamado. Tente parar exatamente onde é apontado no mapa. ¬iMobby¬d19/09/2017 00:00:00 2359235923592359 0012 000 23590 ¬§');
Enviar.Add('11111111111111111111111111111111111111 0006 Jardim São Caetano|Fique mais próximo'+' do conjunto de prédios do Jardim São Caetano para aumentar as chances de receber um chamado. Tente parar exatamente onde é apontado no mapa. ¬iMobby¬d19/09/2017 00:00:00 2359235923592359 0012 000 23590 ¬§');
Enviar.Add('@');
EnvioStream := TMemoryStream.Create;
try
Enviar.SaveToStream(EnvioStream, TEncoding.UTF8); // <-- here
except
EnvioStream.Free;
raise;
end;
// AResponseInfo.ContentStream takes ownership of the stream
// and will free it when AResponseInfo is freed. TIdHTTPServer
// will send the response automatically when this OnCommandGet
// handler exits, so you don't need to call WriteContent()
// manually...
AResponseInfo.ContentStream := EnvioStream;
AResponseInfo.ContentType := 'text/plain'; // <-- add this!
AResponseInfo.CharSet := 'utf-8'; // <-- add this!
finally
Enviar.Free;
end;
end;
谢谢雷米!它在客户端和服务器上完美地启动了,即使经过数百次尝试不良的3G连接。 –
https://stackoverflow.com/questions/23810909/mobile-application-error-when-loading-from-stream 我的坏。它是重复的, 解决方法是更改以下行:'Enviar.SaveToStream(EnvioStream,TEncoding.UTF8);' –