解码UTF问题?

时间:2015-05-07 21:16:38

标签: java c#

我正在研究我的android项目&我有一个异国情调的问题让我发疯。我正在尝试将字符串转换为 Utf-16 Utf-8 。 我使用这段代码来实现它,但它给了我一个带有一些负面成员的数组!

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应用程序,它将关键字发送到服务器。这些单词由客户发送。我的客户使用(波斯语,فارسی)字符。 第二部分是一个Web应用程序,由C#和它必须回应我的客户。

问题:当我将这些单词发送到服务器时,它会在“????”的流上运行而不是正确的单词。我已经尝试了很多方法来解决这个问题,但他们无法解决这个问题。之后我决定将 utf-16 utf-8 的字符串发送到服务器并将其转换为正确的单词。所以我选择了我在帖子顶部描述的方法。

我的原始代码可靠吗?

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

我的原始代码是什么?

将参数发送到服务器的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 个答案:

答案 0 :(得分:3)

我解决了。起初我改变了我的java code.i通过使用URLEncoder类将我的String转换为UTF-8。

new java Code:

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());
        }

答案 1 :(得分:1)

  

我的第一个问题是这些负数是什么?!

它们是文本的每个16位值中各个字节的有符号字节表示。在Java中,byte类型是带符号的值,类似于intlong,但只有8位信息。它可以表示从-128127的任何值。他们只是&#34;消极&#34;当被解释为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位值,采用小端字节顺序:0xFEFF0x0633,{{1 }和0x06CC。这些16位值中的每一个都代表一个Unicode代码点。

第一个用作UTF16编码文本的字节顺序标记。它是一个Unicode字符,专门用于指示UTF16编码中的字节是little-endian还是big-endian。其他三个是你实际字符串中的字符。

但是当你将字节分开并单独查看它们时,如果将其视为有符号字节值,则任何大于0x0631的值(当被视为无符号字节值时)表示< em>负号作为签名字节值。因此,0x7F0xFF0xFE都显示为负数(每个都大于0xCC)。但它们实际上仍然只是有效的16位Unicode代码点值的一半。

请注意,如果解释不正确,即使这些代码点值也会显示为负数。在您的示例中,只有一个显示为否定 - 0x7F在{em>签名 16位值时被解释为0xFEFF,即使Unicode代码点实际为十进制{{1 - 但是还有很多其他Unicode字符的值高于-257(十进制65279),如果被视为带符号的16位值,则会显示为负值。

最重要的是,计算机对数字一无所知。它们只有位,方便地分组为字节和各种字大小。当您想知道这些位的含义时,您必须确保告诉计算机在向您显示位时使用的正确,有用的表示。如果你不这样做,那么你会得到一些与其预期表示不匹配的其他解释。垃圾进,垃圾出。


现在,假设您了解了上述所有内容,请考虑您更广泛的问题:

  

当我将这些单词发送到服务器时,它会在&#34; ????&#34;而不是正确的单词。我已经尝试了很多方法来解决这个问题,但他们无法解决这个问题。

问自己的第一个问题是&#34;我如何解释这些字节?我如何向用户显示它们?&#34;你并没有分享任何在这方面实际相关的代码,但你确实说过,当你只使用拉丁字母(&#34;英文字符&#34;)时它可以正常工作。假设你也用UTF16测试了拉丁字母方案,那么这告诉我基本的I / O工作正常;你可能遇到的主要问题是字节顺序,但如果发生这种情况,即使是拉丁字符也会出现乱码。

因此,您描述的0x7FFFF最可能的解释是您不能在可以显示波斯字符的上下文中查看文本。例如,使用32767类将它们写出到控制台窗口。控制台窗口中使用的字体不支持Unicode感知渲染,因此它不会显示波斯字符。在各种其他环境中存在类似的问题,包括例如记事本(取决于正在使用的字体)和其他编辑器。


非常抱歉。以上所有内容实际上只是一种冗长的方式告诉你&#34;一切都很好,你可能只是没有使用正确的工具来验证你的结果。&#34;

请注意,如果没有a good, minimal, complete code example能够可靠地再现您所感知到的任何问题,那么就无法确切地说明发生了什么。如果在阅读并理解了这个答案之后,您仍然认为代码存在问题,那么您需要花时间创建一个能够清楚地展示实际问题的良好代码示例。一行代码值得千言万语,一个正确的代码示例值得用金重量(混合几个完全不适用的比喻:))。