【问题标题】:Correct way to parse a String of data解析数据字符串的正确方法
【发布时间】:2014-08-13 09:23:01
【问题描述】:

我对编程还很陌生,我最近构建了一个 Android 应用程序,它使用 USB OTG 从 USB 串行设备读取数据。我将数据读入字节缓冲区,将其转换为字符串,然后解析字符串,以便我可以选择和使用数据的不同部分在我的应用程序上显示不同的内容。

我首先使用 example.substring(example.lastIndexOf("123"); 拆分字符串并丢失我不需要的字符串的第一部分,然后检查子字符串的长度以确保数据正确,接下来,我将子字符串数据转换为 char 数组,以便能够选择数组的不同数据元素并将它们显示在屏幕上。这似乎可行,但我只是觉得它很乱,而且解析字符串的方法可能不正确。

有人可以给我一个想法,看看是否有更有效的方法来解析字符串,或者我是否应该携带用我目前的方法。

例如:

String s = "Serial Data String TX, ID: 1, UOD: 1234, OK";
String ss = s.substring(s.lastIndexOf("ID: "));

int len = ss.length();
char[] c = ss.toCharArray();

if (len == 20) {

if (c[4] == '1') {

String mSubstring = ss.substring(12, 16);
tv1.setText(mSubString);



这是一种混乱/低效的方法吗?

【问题讨论】:

  • 您想要解析/验证字符串的哪些元素?您的字符串似乎用逗号分隔,您可以使用 s.split(",") 对其进行拆分。
  • 考虑到变量 ss 和 s 一样大。执行 substring 会使用从 src String 中获取的 char 数组创建新的 String。因此,通过简单地将 s 设置为 null 来释放内存是行不通的。看一下子串方法
  • 预期输出是多少?字符串总是一样的吗?
  • 我想要的元素是“1”和“1234”,这样我就可以在屏幕上将它们显示为 ID:1 和 OUD:1234
  • @cbrook - 你的字符串中是否总是有 ID、UOD 等?

标签: java string oop parsing performance


【解决方案1】:

嗯,这是一种方法,虽然容易出错/异常。例如

s.substring(s.lastIndexOf("ID: "));

可能导致IndexOutOfBoundsException,因为lastIndexOf 可能返回-1。您必须检查并做出相应的反应。

此外,使用固定长度和索引也可能导致错误,最好动态确定。

我会做另一种方式,将原始字符串拆分为更小的部分,然后解析它们。您的示例字符串

String s = "Serial Data String TX, ID: 1, UOD: 1234, OK";

似乎可以被, 拆分,所以在第一步中执行s.split(", ") 会产生以下子字符串

String[] subs = {"Serial Data String TX", "ID: 1", "UOD: 1234", "OK"};

在第二步中,您可以将第一个数组中的第二个元素分隔为空格

subs[1].split(": ")

将导致

String[] subs2 = {"ID", "1"}

等等。

在尝试访问元素之前不要忘记检查元素是否存在。

更新

这是使用上述方法的一种可能的实现方式

public void testSplit() {
    String s = "Serial Data String TX, ID: 1, UOD: 1234, OK";

    String[] subs = s.split("\\s*,\\s*");

    String id = "not available";
    String uod = "not available";

    if(subs.length > 1) {
        String[] subsId = subs[1].split("\\s*:\\s*");
        if("ID".equals(subsId[0]) && subsId.length > 1) {
            id = subsId[1];
        }
    }

    if(subs.length > 2) {
        String[] subsUod = subs[2].split("\\s*:\\s*");
        if("UOD".equals(subsUod[0]) && subsUod.length > 1) {
            uod = subsUod[1];
        }
    }

    System.out.printf("ID=%s%nUOD=%s%n", id, uod);
}

输出是

ID=1
UOD=1234

如果您不完全知道 IDUOD 在原始字符串中的位置,那么您可能需要循环第一次拆分的结果并在每个拆分上进行第二次拆分,然后检查是否元素在索引0 处是您正在寻找的元素之一,如果是,则检查您是否在索引1 处有一个元素,如果是则取该值,否则没有可用的值。

【讨论】:

  • 感谢您的回答!我喜欢这种方法的想法,看起来会干净很多!
  • @cbrook 很酷,我添加了一个您可能想要检查的代码示例。
【解决方案2】:

您可以使用 substring 并直接比较,而不是将字符串转换为 char 数组:

if (len == 20 && "1".equals(ss.substring(4, 1)) {
    String mSubstring = ss.substring(12, 16);
    tv1.setText(mSubString);
}

或者你在ID:之后开始子串并使用startsWith()

String s = "Serial Data String TX, ID: 1, UOD: 1234, OK";
String ss = s.substring(s.lastIndexOf("ID: ") + "ID: ".length());

int len = ss.length();

if (len == 16 && ss.startsWith("1")) {
    String mSubstring = ss.substring(8, 12);
    tv1.setText(mSubString);
}

【讨论】:

    【解决方案3】:

    其实你可以通过多种方式来设计这个,这里我将告诉你哪种方式看起来最好,同时又不太复杂

    首先创建一个类,该类将包含 ID、UOD 等序列数据属性。

    那么既然你已经有了像“,”这样的分隔符和像“:”这样的内分隔符,用它们来分割并使用trim来得到实际的结果,尽量让它泛化,这样将来的新属性可以用最少的变化来适应.如果您正在为此寻找代码级别的解释,请告诉我。

    【讨论】:

      【解决方案4】:

      你可以使用正则表达式:

      String s = "Serial Data String TX, ID: 1, UOD: 1234, OK";
      Pattern p = Pattern.compile("ID: (\\d+), UOD: (\\d+), (\\w+)");
      
      Matcher m = p.matcher(s);
      if (m.find()) {
          System.out.println("ID: " + m.group(1));
          System.out.println("UOD: " + m.group(2));
          System.out.println("Status: " + m.group(3));
      }
      

      这将显示:

      ID: 1
      UOD: 1234
      Status: OK
      

      【讨论】:

        【解决方案5】:

        如果你知道字符串模式,最好使用正则表达式。例如,如果您想知道 UOD 值,那么

        Pattern pattern = Pattern.compile("(.*UOD:\\s?(\\d+),\\s?OK)");
                Matcher matcher = pattern.matcher(input);
                if (matcher.matches()) {
                    return matcher.group(2);
                }
                return null;
        

        【讨论】:

        • 这也是个好方法。
        【解决方案6】:

        你可以像这样使用正则表达式:

        public static void main(String args[]) {
            String s = "Serial Data String TX, ID: 1, UOD: 1234, OK";
            Pattern p = Pattern.compile("(\\w+)(?::\\s+)(\\d+)");
            Matcher m = p.matcher(s);
            while (m.find()) {
                System.out.println(m.group(1) + " - " + m.group(2));
         // add group1 as key and group2 as value to a map if you want the values to persist.
            }
        }
        

        O/P:

        ID - 1
        UOD - 1234
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-08-15
          • 1970-01-01
          • 1970-01-01
          • 2021-05-26
          • 2013-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多