【问题标题】:C# array, String must be exactly one character longC# 数组,字符串必须恰好是一个字符长
【发布时间】:2022-01-13 23:28:51
【问题描述】:

我很流利,但我不确定我在这里做错了什么。我正在尝试从 Web 输出中获取数据,并通过“br /”和空格将其解析为数组。感谢您提前提供任何帮助。我在底部的string[] outputarray = ieoutput.Split(char.Parse("<br />")); 行收到错误“字符串必须恰好是一个字符长”。再次感谢。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class UserData : MonoBehaviour
{
    // URL of your webserver
    string weburl = "127.0.0.1";
    string uid = "?uid=" + "219844";
    string secret = "secret=" + "428032";
    string php;
    string output;
    string[] outputarray;
    void Start()
    {
        Read();
    }
    void Generate(){
        if (PlayerPrefs.HasKey("uid"))
        {
            uid = PlayerPrefs.GetString(uid);
            secret = PlayerPrefs.GetString(secret);
        }
        else {
            StartCoroutine(newUser("newuser", weburl, "genuser.php"));
        }       
    }
    void Read()
    {
        php = "read.php";
        StartCoroutine(readUser("read", weburl, "read.php", uid, secret));
    }
    IEnumerator newUser(string usage, string serverurl, string phpfile) {
        string ieusage = usage;
        string url = serverurl;
        string iephp = phpfile;
        if (ieusage == "newuser"){
            UnityWebRequest www = UnityWebRequest.Get(url + "/userdata/" + iephp);
            yield return www.SendWebRequest();
            output = www.downloadHandler.text;
            Debug.Log(output);
 
            if (www.result != UnityWebRequest.Result.Success) {
                Debug.Log(www.error);
            }
        }
    }
    IEnumerator readUser(string usage, string serverurl, string phpfile, string userid, string usersecret) {
        string ieusage = usage;
        string url = serverurl;
        string iephp = phpfile;
        string ieuid = userid;
        string iesecret = usersecret;
        string ieoutput = "";
        if (ieusage == "read"){
            UnityWebRequest www = UnityWebRequest.Get(url + "/userdata/" + iephp + ieuid + "&" + iesecret);
            yield return www.SendWebRequest();
            output = www.downloadHandler.text;
            ieoutput = output;
            Debug.Log(output);
 
            if (www.result != UnityWebRequest.Result.Success) {
                Debug.Log(www.error);
            }
        }
        string[] outputarray = ieoutput.Split(char.Parse("<br />"));
        for(int i = 0; i < outputarray.Length; i++)
        {
            Debug.Log(outputarray[i]);
        }
    }
    // Update is called once per frame
    void Update()
    {
        
    }
}

【问题讨论】:

  • char.Parse("&lt;br /&gt;")
  • 好吧,不管它是什么代码,我可以向你保证,代码是完全不正确的——考虑到Char.Parse 的文档,我不同意你的自我评估,即你“非常流利”非常清楚,参数值中必须恰好有 1 个字符 - 异常消息是不言自明的。这表明您还不了解 character-value 是什么,这是编程中非常基本的单元,因此您不能“非常流利”。
  • 在这种情况下,我强烈建议使用 JSON 之类的东西在 PHP 和 C# 之间交换数据。
  • 只有 .NET Core 的 .NET Framework 中没有 string.Split(string)。他们正在使用 Unity3D,它使用 Mono,即 .NET Framework。从长远来看,手动解析字符串不是首选。他们应该创建一个简单的类来表示他们想要传输的数据(数据传输对象),并使用 JSON 进行序列化和反序列化。然后你使用对象而不是字符串。
  • @DSander Unity使用.Net Framework。他们使用“.Net 4.6等效”,它实际上支持.Net Standard 2.1 and .Net Framework,所以string.Split(string)在Unity中绝对有效......也许你应该在说明这个答案的大部分内容是错误之前尝试并确认你所说的 - 编辑:好吧,标准 2.1 仅在 Unity 2021 之后才出现,在它只是标准 2.0 之前;)

标签: c# arrays unity3d split


【解决方案1】:
char.Parse("<br />")

会给你一个FormatException,因为char.Parse 需要一个长度正好是1string,正如错误消息告诉你的那样。


在 Unity 2020 及之前

你想使用string.Split(string[], System.StringSplitOptions)

var outPutArray = ieoutput.Split(new string []{"<br />"}, System.StringSplitOptions.None);

自 Unity 2021 起现在支持 .Net Standard 2.1

您只想使用string.Split(string)

var outPutArray = ieoutput.Split("<br />");

或者 - 因为最常见的是 &lt;br&gt; 标签实际上是在没有结束 / 的情况下使用的 - 实际上可能有多个分隔符选项,例如

var outPutArray = ieoutput.Split(new string []{"<br />", "<br>", "<br/>"}, System.StringSplitOptions.None);

由于通常有多种方法可以准确编写这些 HTML 标记以匹配所有不同的编写方式,因此您也可以使用 Regex.Split,例如

var outPutArray = Regex.Split(ieoutput, "<[Bb][Rr].*?>", RegexOptions.Singleline);

在这里你匹配任何东西

  • &lt;br 开头(或&lt;BR&lt;Br 等)
  • 以下一个&gt; 结尾

不管它们之间有什么,即使是换行符(见RegexOptions.Singleline

Regex Example and further Explanation on regex101.com


但是正如已经建议的那样,如果您可以更改输出格式,实际上最简单的解决方案是使用换行符 (\n)。它是单个字符,因此您可以简单地使用

var outPutArray = ieoutput.Split('\n');

如果您的内容非常大并且您不一定需要同时使用outPutArray 的全部内容,您甚至可以考虑使用StringReaderStringReader.ReadLine 来逐行处理,而无需分配整个数组并解析整个字符串都提前。

【讨论】:

  • @Ruzihm 感谢您的编辑;)我再次包含了单个字符串的示例
【解决方案2】:

如果您绝对必须按照您的方式进行操作。如果您使用的是 Unity 2020 及以下版本。:

string[] outputarray = ieoutput.Split(new string[] {"<br/ >"}, System.StringSplitOptions.None);

如果您使用的是 Unity 2021 及更高版本:

string[] outputarray = ieoutput.Split("<br/ >");

否则,由于您似乎也控制了 PHP 输出,我建议让 PHP 输出 JSON 字符串。然后使用Newtonsoft.Json将JSON字符串转换为Object。

例如你的 PHP 可以这样做:

<?php
  $arr = array('Username' => 'DSander', 'UUID' => 'abcdefghijklmnopqrstuvwxyz');
  echo json_encode($arr);
?>

它会输出这个:

{
  "Username" : "DSander",
  "UUID" : "abcdefghijklmnopqrstuvwxyz"
}

然后你可以有一个简单的数据传输对象,像这样在 Unity 中进行序列化和反序列化:

[Serializable]
public class UserDTO
{ 
    public string Username { get; set; }
    public string UUID { get; set; }
}

然后您可以使用 Newtonsoft.Json 或其他 JSON 库来反序列化对象,如下所示:

using Newtonsoft.Json;

UserDTO user = JsonConvert.DeserializeObject<UserDTO>(ieoutput);
Debug.Log(user.Username);

注意:在 Unity 包管理器中,您必须单击 + 图标,单击“通过 git url 添加”,然后键入“com.unity.nuget.newtonsoft-json”以获取项目中的 Newtonsoft 依赖项。

您还可以像这样序列化用户并将其发送到您的 PHP 端点:

UserDTO user = new UserDTO
{
    Username = "DSander",
    UUID = Guid.NewGuid().ToString()
};

// serialize object to string
string userJsonData = JsonConvert.SerializeObject(user, Formatting.Indented);

// create POST form data
Dictionary<string, string> postData = new Dictionary<string, string>();
postData.Add("userJsonData", userJsonData);

// make POST request with data
UnityWebRequest www = UnityWebRequest.Post(url + "/userdata/" + iephp, postData);

然后在 PHP 端你可以使用 json_decode:

<?php
  $obj = json_decode($_POST["userJsonData"]);
  print $obj->{'Username'}; // DSander
?>

【讨论】:

  • String.Split(char[]) 将在提供的chars 中的任何 个上拆分,不一定在一起,也不一定按此顺序。你想要String.Split(string)
  • 兰斯,你错了。 String.Split(string) 仅存在于 .NET Core 中。他们将他们的问题标记为使用 Mono 的 Unity3D。这意味着它是 .NET Framework,解决方案是使用 String.Split(string[], StringSplitOptions)。我昨晚在我的回复中犯了一个愚蠢的错误,当它应该是 string[] 时使用 char[]。我已经编辑了我的解决方案。
  • 这个答案有一些好东西。对于解决询问者如何有效发送数据的 xy 问题,绝对值得一票。
  • @Ruzihm 我认为 XY 问题是基于迄今为止的假设。由于我们不知道 OP 的实际用例,而且 PHP 代码我猜我们现在都必须假设 OP 实际上需要单独的行......因此 JSON 只是开销,简单地按 \n 拆分会更有效如前所述......但如前所述,这是基于假设,直到我们得到进一步的输入。所以现在我宁愿坚持主要是如何正确分割字符串的请求/问题;)
  • @DSander Unity使用.Net Framework。他们使用“.Net 4.6等效”,它实际上支持.Net Standard 2.1 and .Net Framework,所以string.Split(string)在Unity中绝对有效......也许你应该在说明这个答案的大部分是错误的之前尝试确认你所说的 - 编辑:好吧,标准 2.1 仅在 Unity 2021 之后才出现,在它只是标准 2.0 之前;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
  • 2023-03-14
  • 2021-07-24
  • 2018-12-20
  • 2021-11-13
  • 2017-02-10
相关资源
最近更新 更多