2015-05-07 34 views
5

我工作在我的android項目&我有一個奇特的問題,讓我發瘋。我試圖將字符串轉換爲Utf-16Utf-8。 我使用這段代碼來實現它,但它給了我一個負面成員的數組!解碼UTF問題?

Java代碼的

String Tag="سیر"; 
String Value=""; 
try{ 
      byte[] bytes = Tag.getBytes("UTF-16"); 
      for(int i=0;i<bytes.length;i++){ 
      Value=Value+String.valueOf(bytes[i])+","; 
     } 

數組成員: 陣成員[-1,-2,51,6,-52,6,49,6]。我查看了UTF-16的表。它沒有任何負數,並且我使用了一個網站,該網站將文字轉換爲UTF-16M。它給了我"0633 06CC 0631"HEX。如果您將此數字更改爲十進制,您將看到:"1577 1740 1585"。如你所見,這裏沒有負數!所以我的第一個問題是這些負數是什麼?!

爲什麼我要將單詞轉換爲UTF-8或UTF-16?

我正在開展一個項目。這個項目有兩個部分。第一部分是一個將關鍵字發送到服務器的android應用程序。這些詞是由客戶發送的。我的客戶使用(波斯語,فارسی)字符。第二部分是由C#製作的網絡應用程序&它必須迴應我的客戶。

問題:當我將這些單詞發送到服務器時,它在「????」流上工作,而不是正確的詞。我嘗試了很多方法來解決這個問題,但他們無法解決這個問題。之後,我決定將自己的字符串發送到服務器,並將其轉換爲正確的單詞。所以我選擇了我在帖子頂部描述的那些方法。

我的原始碼是否可靠?

是的。如果我使用英文字符,它的反應非常好。

我的原始代碼是什麼?

的Java代碼,其參數發送到服務器:

protected String doInBackground(String...Urls){ 
       String Data=""; 
       HttpURLConnection urlConnection = null; 
       try{ 
        URL myUrl=new URL("http://10.0.2.2:80/Urgence/SearchResault.aspx?Tag="+Tag); 
        urlConnection = (HttpURLConnection)myUrl.openConnection();  
        BufferedReader in = new BufferedReader (new InputStreamReader(urlConnection.getInputStream()));   
        String temp=""; 
        // Data is used to store Server's Response 
        while((temp=in.readLine())!=null) 
        {    
         Data=Data+temp;   
        }  
       } 

C#代碼,響應客戶端:

string Tag = Request.QueryString["Tag"].ToString(); 
    SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["conStr"].ToString(); 
      SqlCommand cmd = new SqlCommand("FetchResaultByTag"); 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.AddWithValue("@NewsTag",Tag); 
      cmd.Connection = con; 
      SqlDataReader DR; 
      String Txt = ""; 
      try 
      { 
       con.Open(); 
       DR = cmd.ExecuteReader(); 
       while (DR.Read()) 
       { 
        Txt = Txt + DR.GetString(0) + "-" + DR.GetString(1) + "-" + DR.GetString(2) + "-" + DR.GetString(3) + "/"; 
       } 
       //Response.Write(Txt); 
       con.Close(); 
      } 
      catch (Exception ex) 
      { 
       con.Close(); 
       Response.Write(ex.ToString()); 
      } 

*你覺得呢?你有什麼想法嗎?**

+2

你處理UTF8/16字符的字節表示。對於您的語言,您將使用hi-bit設置字節,這意味着它們將被視爲負數,因爲它們被用作有符號整數。 –

+0

您是否嘗試在'Tag'上使用[URLEncoder](http://docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html)? –

+0

'+ value'幾乎是構建URL /查詢字符串的有效方法。這裏是C#解決方案http://stackoverflow.com/questions/829080/how-to-build-a-query-string-for-a-url-in-c並且應該有等效的Java解決方案 - http:// stackoverflow .com/questions/5330104/encoding-url-query-parameters-in-java ...但這些都不涉及你提問的方式,所以不能回答... –

回答

1

我的第一個問題是這些負數是什麼?!

它們是您的文本的每個16位值內的單個字節的有符號字節表示形式。在Java中,byte類型是一個有符號值,類似於intlong,但只有8位信息。它可以代表從-128127之間的任何值。當解釋爲Java byte值時,它們只是「負面」。

當然,作爲UTF16編碼文本中的字節,解釋是沒有意義的。你應該只將它們解釋爲UTF16編碼的文本。但是負數是錯誤解釋UTF16編碼文本的自然結果,就好像它只是一個普通的有符號字節數組。

,就好像你做了什麼樣int i = -1; uint j = (uint)i;它類似於(在C#... Java沒有無符號整數類型本身),然後問爲什麼j否定,而是具有價值4,294,967,295 。那麼,j是一個未簽名的數據類型;用作-1作爲簽名的int的位模式與用作4,294,967,295作爲無符號uint相同。

如果上一段對你沒有意義,那麼你需要自己做一些閱讀,以瞭解計算機如何存儲數字以及簽名和未簽名數據類型之間的區別。


你的代碼,[-1,-2,51,6,-52,6,49,6]的輸出數組,實際上是 16位值,在little-endian字節順序:0xFEFF0x06330x06CC0x0631。這些16位值中的每一個都代表一個Unicode代碼點。

第一個用作UTF16編碼文本的字節順序標記。它是一個Unicode字符,專門用於指示UTF16編碼中的字節是小端還是大端。其他三個是你的實際字符串中的字符。

但是當你拉字節拆開,看他們個人,如果被視爲符號字節值,比0x7F(當爲無符號字節值考慮)更大的任何值表示號碼作爲簽署字節值。因此,0xFF,0xFE0xCC全都顯示爲負數(每個都大於0x7F)。但他們實際上仍然只是有效的16位Unicode代碼點值的每一半。

請注意,即使這些代碼點值可能會出現負面,如果解釋不正確。在你的榜樣,只有一個會出現負— 0xFEFF-257時解釋爲簽署 16位值,儘管Unicode代碼點實際上是十進制65279 —但也有很多是具有高於價值的其他Unicode字符0x7FFFF(十進制32767),並且如果查看爲有符號的16位值,則將顯示負值。

底線是計算機並不真正瞭解數字的任何內容。他們只是有位,方便地分成字節,和各種字的大小。當你想知道這些位是什麼意思時,你必須確保你告訴計算機正確,有用的表示,以顯示位給你。如果你不這樣做,那麼你會對那些不符合他們想要的表示的位進行一些其他的解釋。垃圾進垃圾出。現在


,假設你瞭解以上所有的,讓我們看看你的更廣泛的問題:

當我把這些話給服務器它適用於流「????」而不是正確的詞。我嘗試了很多方法來解決這個問題,但他們無法解決這個問題。

問自己的第一個問題是「我如何解釋這些字節?我如何將它們顯示給用戶?」你沒有分享任何在這方面實際相關的代碼,但你確實說過,當你只使用拉丁字母(「英文字符」)時,它工作正常。假設你也用UTF16測試了拉丁字母表情形,那麼這告訴我基本的I/O工作正常;你可能會錯誤的主要是字節順序,但如果發生這種情況,即使拉丁字符也會出現亂碼。

因此,您所描述的"????"最有可能的解釋是,您根本沒有在可以顯示波斯語字符的上下文中查看文本。例如,使用Console類將它們寫入控制檯窗口。控制檯窗口中使用的字體不支持Unicode感知渲染,因此它不會顯示波斯語字符。在其他各種情況下也有類似的問題,包括例如記事本(取決於正在使用的字體)和其他編輯器。


所以,對不起。以上所有內容實際上只是一種冗長的方式,告訴你「一切都很好,你可能只是沒有使用正確的工具來驗證你的結果。」

注意,如果沒有a good, minimal, complete code example可靠地再現您認爲什麼問題,它不是真的有可能肯定地說這是怎麼回事。如果在閱讀並理解了這個答案後,仍然認爲代碼存在問題,則需要花時間創建一個很好的代碼示例,以清楚地展示實際問題。一行代碼勝過千言萬語,一個正確的代碼例子是值得黃金重量的(混合幾個完全不適用的隱喻:))。

3

我解決它。起初我改變了我的java code.i通過使用URLEncoder類將我的String轉換爲UTF-8。

新的Java代碼:

try{ 
      Tag=URLEncoder.encode(Tag,"UTF-8"); 
      } 
      catch(Exception ex){ 
       Log.d("Er>encodeing-Problem",ex.toString());  
      } 

後,我通過HTTP協議

protected String doInBackground(String...Urls){ 
      String Data=""; 
      HttpURLConnection urlConnection = null; 
      try{ 
       URL myUrl=new URL("http://10.0.2.2:80/Urgence/SearchResault.aspx?Tag="+Tag); 
       urlConnection = (HttpURLConnection)myUrl.openConnection();  
       BufferedReader in = new BufferedReader (new InputStreamReader(urlConnection.getInputStream()));   
       String temp=""; 
       // Data is used to store Server's Response 
       while((temp=in.readLine())!=null) 
       {    
        Data=Data+temp;   
       } 

,並在我夾在服務器和解碼,它的結束送了它作爲查詢字符串。

新的C#代碼:

 string Tag = Request.QueryString["Tag"].ToString(); 
    SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["conStr"].ToString()); 
      SqlCommand cmd = new SqlCommand("FetchResaultByTag"); 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.AddWithValue("@NewsTag", HttpUtility.UrlDecode(Tag)); 
cmd.Connection = con; 
     SqlDataReader DR; 
     String Txt = ""; 
     try 
     { 
      con.Open(); 
      DR = cmd.ExecuteReader(); 
      while (DR.Read()) 
      { 
       Txt = Txt + DR.GetString(0) + "-" + DR.GetString(1) + "-" + DR.GetString(2) + "-" + DR.GetString(3) + "/"; 
      } 
      Response.Write(Txt); 
      con.Close(); 
     } 
     catch (Exception ex) 
     { 
      con.Close(); 
      Response.Write(ex.ToString()); 
     }