如何从一个字符中获取数据?

7

我正在使用 Assembly C# 编写 Unity 项目。我尝试获取特殊字符,例如 é,但在控制台中只显示空白字符:" "。例如将"How are you?"翻译为"¿Cómo estás?",但它返回"Cmo Ests"。我将返回的字符串"Cmo Ests"放入字符数组中并意识到它是一个非空的空白字符。我正在使用 Encoding.UTF8,当我执行以下操作时:

char ch = '\u00e9';
print (ch);

它将打印出“é”。我尝试使用以下代码从给定的字符串中获取字节:

byte[] utf8bytes = System.Text.Encoding.UTF8.GetBytes(temp);

在翻译"How are you?"时,它会返回一个字节字符串,但对于像é这样的特殊字符,我得到了239、191、189这一系列字节,这是一个替换字符。

为准确确定是哪个字符,我需要从这些字符中检索出什么类型的信息?我需要对Google给我的信息做些什么,还是其他什么方法?我需要一个通用的情况,可放入我的程序中,并适用于任何输入字符串。如果有人能帮忙,将不胜感激。

下面是引用的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using System.Collections;
using System.Net;
using HtmlAgilityPack;


public class Dictionary{
string[] formatParams;
HtmlDocument doc;
string returnString;
char[] letters;
public char[] charString;
public Dictionary(){
    formatParams = new string[2];
    doc = new HtmlDocument();
    returnString = "";
}

public string Translate(String input, String languagePair, Encoding encoding)
    {
        formatParams[0]= input;
        formatParams[1]= languagePair;
        string url = String.Format("http://www.google.com/translate_t?hl=en&ie=UTF8&text={0}&langpair={1}", formatParams);

        string result = String.Empty;

        using (WebClient webClient = new WebClient())
        {
            webClient.Encoding = encoding;
            result = webClient.DownloadString(url);
        }       
        doc.LoadHtml(result);
        input = alter (input);
        string temp = doc.DocumentNode.SelectSingleNode("//span[@title='"+input+"']").InnerText;
        charString = temp.ToCharArray();
        return temp;
    }
// Use this for initialization
void Start () {

}
string alter(string inputString){
    returnString = "";
    letters = inputString.ToCharArray();
    for(int i=0; i<inputString.Length;i++){
        if(letters[i]=='\''){
            returnString = returnString + "&#39;";  
        }else{
            returnString = returnString + letters[i];   
        }
    }
    return returnString;
}
}

你应该包含生成响应的代码。 - Austin Salonen
我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
你的方法存在几个问题。首先,UTF8编码是一种多字节编码。这意味着如果您使用任何非ASCII字符(具有char代码> 127),则会得到一系列特殊字符,指示系统这是一个Unicode字符。因此,实际上您的序列239、191、189表示一个不是ASCII字符的单个字符。如果您使用UTF16,则会获得固定大小的编码(2字节编码),它实际上将字符映射到无符号短整数(0-65535)。 - byteflux
Unity标签是为了Microsoft Unity而设立的,请不要滥用它。 - Lex Li
这不是微软的Unity。我正在使用第三方的3D开发软件Unity。 - Cameron Barge
显示剩余6条评论
5个回答

1
也许你应该使用另一个API/URL。 下面的这个函数使用不同的URL返回JSON数据,似乎效果更好:
    public static string Translate(string input, string fromLanguage, string toLanguage)
    {
        using (WebClient webClient = new WebClient())
        {
            string url = string.Format("http://translate.google.com/translate_a/t?client=j&text={0}&sl={1}&tl={2}", Uri.EscapeUriString(input), fromLanguage, toLanguage);
            string result = webClient.DownloadString(url);

            // I used JavaScriptSerializer but another JSON parser would work
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            Dictionary<string, object> dic = (Dictionary<string, object>)serializer.DeserializeObject(result);
            Dictionary<string, object> sentences = (Dictionary<string, object>)((object[])dic["sentences"])[0];
            return (string)sentences["trans"];
        }
    }

如果我在控制台应用程序中运行这个:
    Console.WriteLine(Translate("How are you?", "en", "es"));

它将显示

¿Cómo estás?

当尝试将此内容放入程序中时,它会提示缺少命名空间。我尝试了“using System.web;”,但仍然提示缺少命名空间。我需要使用哪个命名空间才能使其正常工作? - Cameron Barge
你需要添加一个对 System.Web.Extensions 的程序集引用。 - Simon Mourier
@CameronBarge 我对Simon的帖子进行了一些编辑(正在进行同行评审...),但总的来说,您需要在“引用”中包含System.Web.Extensions程序集,并且需要使用System.NetSystem.Web.Script.Serialization - flindeberg

0

我在我的一个项目中遇到了同样的问题[语言资源本地化翻译]。

我正在做同样的事情,使用 System.Text.Encoding.UTF8.GetBytes(),由于 utf8 编码,会在结果字符串中收到像您的特殊字符一样的东西,例如 239、191、189。

请查看我的解决方案......希望这可以帮助到您。

根本不要使用编码,Google 翻译将正确返回像 á 这样的字符串本身。进行一些字符串操作并按原样阅读字符串......

通用解决方案 [适用于 Google 支持的每种语言翻译]

try
{
    //Don't use UtF Encoding 
    // use default webclient encoding

    var url = String.Format("http://www.google.com/translate_t?hl=en&text={0}&langpair={1}", "►" + txtNewResourceValue.Text.Trim() + "◄", "en|" + item.Text.Substring(0, 2));                    

     var webClient = new WebClient();
     string result = webClient.DownloadString(url); //get all data from google translate in UTF8 coding..

      int start = result.IndexOf("id=result_box");
      int end = result.IndexOf("id=spell-place-holder");
      int length = end - start;
      result = result.Substring(start, length);
      result = reverseString(result);

      start = result.IndexOf(";8669#&");//◄
      end = result.IndexOf(";8569#&");  //►
      length = end - start;

      result = result.Substring(start +7 , length - 8);
      objDic2.Text =  reverseString(result);

       //hard code substring; finding the correct translation within the string.
        dictList.Add(objDic2);
}
catch (Exception ex)
 {
  lblMessages.InnerHtml = "<strong>Google translate exception occured no resource   saved..." + ex.Message + "</strong>";
                error = true;
}

public static string reverseString(string s)
{
    char[] arr = s.ToCharArray();
    Array.Reverse(arr);
    return new string(arr);

}

从代码中可以看出,没有进行任何编码,我发送了两个特殊的键字符作为“►”+ txtNewResourceValue.Text.Trim() + “◄”,以确定从Google返回翻译的开始和结束。

此外,通过我的语言工具,当我将“How are you”发送到Google翻译时,我得到的是“Cómo Estás?”:)

最好的问候 [Shaz]

---------------------------编辑-------------------------

public string Translate(String input, String languagePair) {

    try
    {


        //Don't use UtF Encoding 
        // use default webclient encoding
        //input        [string to translate]
        //Languagepair [eg|es]

        var url = String.Format("http://www.google.com/translate_t?hl=en&text={0}&langpair={1}", "►" + input.Trim() + "◄", languagePair);

        var webClient = new WebClient();
        string result = webClient.DownloadString(url); //get all data from google translate 

        int start = result.IndexOf("id=result_box");
        int end = result.IndexOf("id=spell-place-holder");
        int length = end - start;
        result = result.Substring(start, length);
        result = reverseString(result);

        start = result.IndexOf(";8669#&");//◄
        end = result.IndexOf(";8569#&");  //►
        length = end - start;

        result = result.Substring(start + 7, length - 8);

        //return transalted string
        return reverseString(result); 


    }
    catch (Exception ex)
    {
        return "Google translate exception occured no resource   saved..." + ex.Message";

    }
}

谢谢您的回复。您能否提供更多关于这应该放在我的代码中哪里的见解,例如方法名称和参数等。任何帮助都将不胜感激。 - Cameron Barge
@Cameron,请检查新编辑的代码,应该可以为您工作...如果有任何问题,请告诉我... - Shazhad Ilyas

0

你的方法存在几个问题。首先,UTF8编码是一种多字节编码。这意味着如果你使用任何非ASCII字符(char code > 127),你将得到一系列特殊字符,指示系统这是一个Unicode字符。所以实际上你的序列239、191、189表示一个不是ASCII字符的单个字符。如果你使用UTF16,则会得到固定大小的编码(2字节编码),它们实际上将字符映射到无符号短整型(0-65535)。

C#中的char类型是一个两字节类型,因此它实际上是一个无符号短整型。这与其他语言(如C/C++)不同,其中char类型是一个1字节类型。

因此,在你的情况下,除非你真的需要使用byte[]数组,否则你应该使用char[]数组。或者,如果你想对字符进行编码,以便它们可以在HTML中使用,那么你只需遍历字符并检查字符代码是否大于128,然后你可以用&hex字符代码替换它。


0
你已经基本掌握了它。只需将编码字母插入 \u 中即可正常工作。
string mystr = "C\u00f3mo Est\u00e1s?";

谢谢您,但这只是针对一个特定情况的解决方案。我需要一个通用解决方案。 - Cameron Barge

0

我对GoogleTranslate API不是很了解,但我的第一反应是你可能遇到了Unicode规范化问题。

可以看看System.String.Normalize()及其相关函数。

Unicode非常复杂,我简单地解释一下。许多符号在Unicode中可以用不同的方式表示,例如:'é'可以表示为'é'(一个字符),或者表示为'e'+'重音符号'(两个字符),或者根据API返回的内容,可能完全不同。

Normalize函数将把你的字符串转换为具有相同文本含义的字符串,但二进制值可能不同,这可能会解决你的输出问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接