当前位置: 首页 > 知识库问答 >
问题:

解码UTF问题?

封梓
2023-03-14

我正在做我的android项目

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”十六进制。如果将此数字更改为十进制,您将看到以下内容:“157717401585”。正如你看到的,这里没有负数!所以我的第一个问题是这些负数是什么?!

为什么要将单词转换为UTF-8或UTF-16?

我在做一个项目,这个项目有两个部分。第一部分是一个android应用程序,它向服务器发送关键词。这些话是客户发送的。我的客户使用(波斯语,فارسی ) 字符。第二部分是一个由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个答案

楚鸿波
2023-03-14

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

它们是文本的每个16位值中单个字节的有符号字节表示。在Java中,byte类型是一个有符号值,类似于intlong,但只有8位信息。它可以表示从-128127的任意值。当解释为Java字节时,它们仅为“负值”。

当然,作为UTF16编码文本中的字节,这种解释毫无意义。您应该仅将它们解释为UTF16编码文本。但是,负数是将UTF16编码的文本误解为有符号字节的普通数组的自然结果。

这类似于你做了类似inti=-1;uint j=(uint)i (在C#…中,Java本身没有无符号整数类型),然后询问为什么j不是负数,而是值4294967295。嗯,j是一种无符号数据类型;作为有符号的int用于-1的位模式与作为无符号的uint用于4294967295的位模式相同。

如果前面的段落对您没有意义,那么您需要自己阅读一些内容,以了解计算机如何存储数字,以及有符号和无符号数据类型之间的区别。


代码的输出数组,[-1,-2,51,6,-52,6,49,6],实际上是四个16位的值,以小数字节顺序排列:0xFEFF0x06330x06CC0x0631>。这些16位值中的每一个都代表一个Unicode代码点。

第一个用于UTF16编码文本的字节顺序标记。它是一个Unicode字符,专门用于指示UTF16编码中的字节是小端还是大端。另外三个是实际字符串中的字符。

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

请注意,如果解释不正确,即使这些代码点值也可能显示为负值。在您的示例中,当解释为有符号的16位值时,只有一个会显示为负数-0xFEFF-257,即使Unicode码点实际上是十进制的65279,但还有许多其他Unicode字符的值高于0x7FFFF(十进制32767),如果将其视为有符号的16位值,则显示为负数。

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


现在,假设你理解了以上所有内容,让我们考虑一下你更广泛的问题:

当我将这些单词发送到服务器时,它在一个“?”流上工作而不是正确的单词。我试过很多方法来解决这个问题,但他们都解决不了。

第一个要问自己的问题是“我是如何解读这些字节的?我如何向用户显示它们?"你没有分享任何在这方面实际相关的代码,但是你说过当你只使用拉丁字母(“英语字符”)时,它工作得很好。假设你也用UTF16测试了拉丁字母场景,那么这告诉我基本的输入/输出工作正常;你可能会出错的主要是字节顺序,但是如果发生这种情况,甚至拉丁字符也会被乱码。

所以"????"最可能的解释是您描述的是,您根本没有在可以显示波斯字符的上下文中查看文本。例如,使用控制台类将它们写入控制台窗口。控制台窗口中使用的字体不支持Unicode感知渲染,所以它不会显示波斯字符。在其他各种情况下也有类似的问题,包括例如。记事本(取决于使用的字体)和其他编辑器。


所以,对不起。所有这些都只是对你说“一切都很好,你可能只是没有使用正确的工具来验证你的结果。”

请注意,如果没有一个好的、最小的、完整的代码示例来可靠地再现您所看到的任何问题,就不可能确切地说发生了什么。如果在阅读和理解这个答案后,您仍然认为您的代码有问题,您需要花时间创建一个好的代码示例来清楚地演示实际问题。一行代码胜过一千个单词,一个合适的代码示例胜过黄金(混合几个完全不适用的隐喻:))。

壤驷棋
2023-03-14

我解决了。起初,我更改了java代码。我使用URLEncoder类将字符串转换为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());
        }
 类似资料:
  • 我在将文本从UTF-8编码转换为UTF-8编码时遇到问题。这里有字节数组, 我正在将其转换为UTF-8字符串并返回字节数组, 据我所知,这是一个3字节的数组。正当但这是我得到的。 这是什么原因?据我所知,在UTF-8 Specials中,2391189组合被称为替换字符。 这也是一个更大问题的一部分。

  • 我想知道是否有人能帮忙,我很难将UTF-8字符发布到SagePay。数据库是MySQL,带有数据库字符集utf8和数据库排序规则utf8_general_ci。数据库连接字符串使用useUnicode=true 所有发布到数据库的数据都存储为UTF-8,所有查询的数据都显示为UTF-8,但当字符串编码如下时: 然后发到SagePay,他们会收到一个来自国际字符所在位置的乱码字符串。如果字符串中不包

  • 问题内容: 如何使用Android解码utf-8字符串?我尝试使用此命令,但输出与输入相同: 问题答案: 字符串不需要编码。它只是一个Unicode字符序列。 要将字符串转换为字节序列时需要进行 编码 。您选择的字符集(UTF-8,cp1255等)确定了Character-> Byte映射。请注意,字符不必转换为单个字节。在大多数字符集中,大多数Unicode字符都转换为至少两个字节。 字符串的编

  • 问题内容: 最近,我们将应用程序从JDK 7迁移到了JDK8。更改之后,我们遇到了以下代码段的问题。 字节数组可能包含无效的UTF-8字节序列。UTF-8解码时,相同的字节数组在Java 7和Java 8上产生两个不同的字符串。 根据此SO帖子的答案,Java 8“修复”了Java7中的错误,并用替换字符串替换了无效的UTF-8字节序列,该字符串符合UTF-8规范。 但是我们想坚持使用Java 7

  • 作为Python的新手,我已经花了很多时间。 我怎么能解码这样的URL: 到python 2.7中的这个: 返回的内容非常难看。 仍然没有解决办法,任何帮助都是感激的。

  • 问题内容: 使用UTF-8编码创建字符串时存在不一致的地方。 运行此代码: 在Java 1.8.0_20(及更早版本)上,我们得到结果 在Java 1.7和1.6上,我们得到正确的结果: 您遇到此错误了吗?有没有解决方法? 对于Shift_JIS,JIS_X0212-1990,x-IBM300,x-IBM834,x-IBM942,x-IBM942C,x-JIS0208来说,这种不一致也很明显,但显