这可能是一个简单的问题,但我已经谷歌搜索超过一个小时,还没有找到答案。
我正在尝试使用String.split()方法和一个小型Android应用程序来分割输入字符串。输入字符串将是:“启动ip:192.168.1.101;端口:5900”。我在两次迭代中这样做,以确保所有必需的参数都存在。我首先尝试对空格和分号进行拆分,以便对单个标记进行整理。接下来,我试图拆分冒号,以剥去每条信息的识别标签。
因此,例如,我希望第一轮拆分能够从上面的示例字符串中获取以下数据: (1)发射 (2)ip:192.168.1.101 (3)港口:5900
然后第二轮会给我以下内容: (1)192.168.1.101 (2)5900
但是,我写的以下代码并没有给出我的期望:
private String[] splitString(String inputString)
{
String[] parsedString;
String[] orderedString = new String[SOSLauncherConstants.SOCKET_INPUT_STRING_PARSE_VALUE];
parsedString = inputString.trim().split("; ");
Log.i("info", "The parsed data is as follows for the initially parsed string of size " + parsedString.length + ": ");
for (int i = 0; i < parsedString.length; ++i)
{
Log.i("info", parsedString[i]);
}
for (int i = 0; i < parsedString.length; ++i )
{
if (parsedString[i].toLowerCase().contains(SOSLauncherConstants.PARSED_LAUNCH_COMMAND_VALUE))
{
orderedString[SOSLauncherConstants.PARSED_COMMAND_WORD] = parsedString[i];
}
if (parsedString[i].toLowerCase().contains("ip"))
{
orderedString[SOSLauncherConstants.PARSED_IP_VALUE] = parsedString[i].split(":")[1];
}
else if (parsedString[i].toLowerCase().contains("port"))
{
orderedString[SOSLauncherConstants.PARSED_PORT_VALUE] = parsedString[i].split(":")[1];
}
else if (parsedString[i].toLowerCase().contains("username"))
{
orderedString[SOSLauncherConstants.PARSED_USERNAME_VALUE] = parsedString[i].split(":")[1];
}
else if (parsedString[i].toLowerCase().contains("password"))
{
orderedString[SOSLauncherConstants.PARSED_PASSWORD_VALUE] = parsedString[i].split(":")[1];
}
else if (parsedString[i].toLowerCase().contains("color"))
{
orderedString[SOSLauncherConstants.PARSED_COLOR_VALUE] = parsedString[i].split(":")[1];
}
}
Log.i("info", "The parsed data is as follows for the second parsed string of size " + orderedString.length + ": ");
for (int i = 0; i < orderedString.length; ++i)
{
Log.i("info", orderedString[i]);
}
return orderedString;
}
结果,我得到以下内容: 对于大小为1的解析字符串,解析后的数据如下:
启动ip:192.168.1.106;端口:5900
对于大小为6的第二个解析字符串,解析后的数据如下:
启动ip:192.168.1.106;端口:5900
192.168.1.106;端口
然后,当然,它会崩溃,因为for循环会遇到一个空字符串。
旁注: 以下代码段来自定义所有字符串索引的常量类 -
public static final int SOCKET_INPUT_STRING_PARSE_VALUE = 6;
public static final int PARSED_COMMAND_WORD = 0;
public static final String PARSED_LAUNCH_COMMAND_VALUE = "launch";
public static final int PARSED_IP_VALUE = 1;
public static final int PARSED_PORT_VALUE = 2;
public static final int PARSED_USERNAME_VALUE = 3;
public static final int PARSED_PASSWORD_VALUE = 4;
public static final int PARSED_COLOR_VALUE = 5;
我调查需要一个可能的转义(通过在分号前插入\\)分号分隔符,甚至尝试使用它,但这不起作用。奇怪的是,空格和分号都不能作为分隔符,但冒号第二次起作用。有没有人会有什么想法会导致这个?
谢谢你的时间!
编辑:我还应该补充一点,我通过WiFi套接字连接收到了字符串。我认为这不应该有所作为,但我希望你能获得所需的所有信息。
答案 0 :(得分:9)
String.split(String)
采用正则表达式。使用"[; ]"
。例如:
"foo;bar baz".split("[; ]")
将返回包含"foo"
,"bar"
和"baz"
的数组。
如果您需要空格组作为单个分隔符,您可以使用以下内容:
"foo;bar baz".split("(;| +)")
答案 1 :(得分:1)
我相信String.split()会尝试在您指定的每个字符上(或在正则表达式上)拆分,而不是分别对每个字符进行拆分。也就是说,split(";.")
根本不会拆分"a;b.c"
,而是会拆分"a;.b"
。
Guava's Splitter可能会有更好的运气,这意味着比java.lang.String.split
稍微不可预测。
我会写类似
的内容 Iterable<String> splits = Splitter.on(CharMatcher.anyOf("; ")).split(string);
但Splitter
还提供流畅式自定义,例如“修剪结果”或“跳过空字符串。”
答案 2 :(得分:0)
你有没有理由使用String.split(),但没有使用正则表达式?如果字符串格式一致,这是正则表达式的完美候选者。
我不确定你的格式是否已修复,如果是,那么下面的正则表达式应该为你分解(确定有人可以提出一个更优雅的正则表达式)。如果你有几个命令字符串,那么你可以使用更灵活的正则表达式并循环遍历所有组:
Pattern p = Pattern.compile("([\w]*)[ ;](([\w]*):([^ ;]*))*");
Matcher m = p.match( <input string>);
if( m.find() )
command = m.group(1);
do{
id = m.group(3);
value = m.group(4);
} while( m.find() );
在线测试正则表达式的好地方是http://www.regexplanet.com/simple/index.html。如果你只想让正则表达式正确,它允许你使用正则表达式而无需每次都编译和启动应用程序。