【问题标题】:String manipulation for VML PathVML 路径的字符串操作
【发布时间】:2014-06-10 11:43:41
【问题描述】:

您好,我正在尝试使用 Java 字符串操作来解析 VML 路径值。我想检索路径中的所有命令,例如 MoveToLineToCurveToRLineTo(其他命令)以及它们对应的 xy 坐标/参数。

这里是要解析的示例数据,每个命令都有自己的 x,y 坐标。

 1. m1,1 l1,200,200,200,200,1 xe
 2. m, l1,200,200,200,200,1 xe

您能否建议一种算法或代码来检索命令和每个命令的参数? 例如在数字 1 中。

Command = moveto 'm'

Command Parameters = (x=1,y=1).

参考: http://www.w3.org/TR/NOTE-VML#_Toc416858391

这很奇怪,但我尝试使用像

这样的 StringTokenizer
StringTokenizer tokenizer = new StringTokenizer(path);

一位朋友建议使用 StringTokenizer,它做了一些接近我的目标的事情,它给了我以下数据。也许我可以利用 StringTokenizer 来满足我的需要。

m1,1
l1,200,200,200,200,1
xe

对于#1,这是理想的输出。 (伪代码)

String command_type = "m"        List<String, String> parameters =   add("1", "1")
String command_type = "l"        List<String, String> parameters =   add("1", "200")
                                                                     add("200", "200")
                                                                     add("200", "1")
String command_type = "x"        (can have no parameter )
String command_type = "e"        (can have no parameter )

对于#2,这是理想的输出。 (伪代码)

String command_type = "m"        List<String, String> parameters =   add("0", "0")  // because the x and y parameters are not specified so I need to force them to 0,0
String command_type = "l"        List<String, String> parameters =   add("1", "200")
                                                                     add("200", "200")
                                                                     add("200", "1")
String command_type = "x"        (can have no parameter )
String command_type = "e"        (can have no parameter )

【问题讨论】:

  • 您能否为您的 3 个示例中的每一个提供所需的输出?
  • 您好,感谢您的快速回复,我更新了示例并删除了第三个。 :-)
  • String tokenizer 已弃用,使用 String.split(regex) 效果相同

标签: java string string-matching stringtokenizer vml


【解决方案1】:

一个好的规范在这里很重要,但根据您的示例输入和输出,我猜到了:

字母 -> 逗号分隔参数 -> 字母 -> 逗号分隔参数

我还注意到命令不是用空格分隔的。例如你有 xe 作为两个单独的命令。这意味着在您的样本空间中没有任何意义,可以忽略。

我还注意到命令都是单个字母。 (否则 xe 不会作为两个命令出现)

参数也必须成对出现,并且必须是数字。我在您的样本中没有看到负数,但我认为这些是可能的。我还将假设它们是整数而不是小数。

因此,根据假设的规范,我可以提出一个可能的解决方案,让您查看并弄清楚它在做什么。

package ic.ac.uk.relationshipvisualiser.app;

import java.util.ArrayList;
import java.util.List;

public class TmpNoFXTest {

    private static class coOrd {
        int x = 0;
        int y = 0;
        public coOrd(int p_x,int p_y) {
            x=p_x;y=p_y;
        }
        public int getX() {return x;}
        public int getY() {return y;}
    }
    private static class command {
        String command = "";
        List<coOrd> param_list = new ArrayList<coOrd>();

        public command(String p_command) {
            command = p_command;
        }
        private String parseOneParam(String p_inp) {
            if (p_inp.equals("")) return "";
            if (isLetter(p_inp.substring(0,1))) return p_inp;
            int firstChar = 0;
            for (int c=0;c<p_inp.length();c++) {
                if (firstChar==0) {
                    if (isLetter(p_inp.substring(c,c+1))) {
                        firstChar = c;
                    }
                }
            }

            String parms = p_inp.substring(0,firstChar);
            if (parms.length()==0) return p_inp.substring(firstChar);
            int x = 0;
            int y = 0;

            int p = 0;
            String tmp = "";
            while ((p<parms.length()) && (!parms.substring(p,p+1).equals(","))) {
                tmp = tmp + parms.substring(p,p+1);
                p++;
            }
            p++;
            if (tmp.length()>0) {
                x = Integer.parseInt(tmp);
            }

            tmp = "";
            while ((p<parms.length()) && (!parms.substring(p,p+1).equals(","))) {
                tmp = tmp + parms.substring(p,p+1);
                p++;
            }

            if (p_inp.substring(p,p+1)==",") p++;

            if (tmp.length()>0) {
                y = Integer.parseInt(tmp);
            }

            param_list.add(new coOrd(x,y));

            return p_inp.substring(p);
        }
        public String parseParams(String p_inp) {
            if (p_inp.equals("")) return "";
            while (!isLetter(p_inp)) {
                p_inp = parseOneParam(p_inp);
            }
            return p_inp;
        }
        public String toString() {
            String ret = "";
            ret = "String command_type = \"" + command + "\"";
            if (param_list.size()==0) return ret + "     (can have no parameter )";


            for (int c=0;c<param_list.size();c++) {
                if (c>0) ret += "\n                         ";
                ret += "        List<String, String> parameters =   add(\"" + param_list.get(c).getX() + "\", \"" + param_list.get(c).getY() + "\")";               
            }

            return ret;
        }
    }
    private static boolean isLetter(String p_inp) {
        return p_inp.substring(0,1).matches("\\p{L}");
    }


    private static String parseSingleCommand(String p_inp, List<command> p_cmds) throws Exception {
        //Read a single command off the incoming string and pass the remaining input back

        String cmd = p_inp.substring(0,1);
        if (!isLetter(p_inp)) throw new Exception("Error command starts with non letter (" + cmd + ")");


        p_inp = p_inp.substring(1);
        command c = new command(cmd);
        p_inp = c.parseParams(p_inp);

        p_cmds.add(c);
        return p_inp;
    }

    private static List<command> parse(String p_inp) throws Exception {
        List<command> r = new ArrayList<command>();

        //spaces don't matter and I want to make this case-insensitive to minimise errors
        p_inp = p_inp.toLowerCase();
        p_inp = p_inp.replace(" ", "");

        while (p_inp.length()>0) {
            p_inp = parseSingleCommand(p_inp,r);
        }
        return r;
    }

    public static void main(String[] args) {
        System.out.println("Start tmpTest");

        List<String> tests = new ArrayList<String>();
        tests.add("m1,1 l1,200,200,200,200,1 xe");
        tests.add("m, l1,200,200,200,200,1 xe");

        for (int c=0;c<tests.size();c++) {
            System.out.println("Running test case " + c + " (" + tests.get(c) + ")");
            try {
                List<command> pr = parse(tests.get(c));

                for (int d=0;d<pr.size();d++) {
                    System.out.println(pr.get(d).toString());
                }

            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
        };

        System.out.println("End tmpTest");
    }
}

【讨论】:

  • 谢谢你,这是解决需求的一种非常好的算法。现在我面临更复杂的字符串值,例如:m@0,l@0@0,0@0,0@2@0@2@0,21600@1,21600@1@2,21600@2,21600 @0@1@0@1,xe 我目前正在处理它,我会非常感谢任何帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 2019-01-08
  • 2023-04-04
  • 1970-01-01
相关资源
最近更新 更多