2017-10-28 92 views
0

我做了一个简单的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字符的映射”。

+0

https://stackoverflow.com/questions/23810909/mobile-application-error-when-loading-from-stream 我的坏。它是重复的, 解决方法是更改​​以下行:'Enviar.SaveToStream(EnvioStream,TEncoding.UTF8);' –

回答

2

在这种情况下,您忽略了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; 
+0

谢谢雷米!它在客户端和服务器上完美地启动了,即使经过数百次尝试不良的3G连接。 –

相关问题