0

所以,我期待我的数据采用以下格式:

"domain::foo::127"

所以这是我的代码:

String[] typeChunks = input.split("::");

            String type = typeChunks[0];
            String edge = typeChunks[1];

            double reputation = Double.parseDouble(typeChunks[2].trim());

但我得到了这个错误

            java.lang.NumberFormatException: empty String
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1011)
at java.lang.Double.parseDouble(Double.java:540)
at org.attempt2.BuildGraph$ReduceClass.reduce(BuildGraph.java:94)
at org.attempt2.BuildGraph$ReduceClass.reduce(BuildGraph.java:1)
at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:176)
at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:650)
at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:418)
at org.apache.hadoop.mapred.Child$4.run(Child.java:255)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1136)
at org.apache.hadoop.mapred.Child.main(Child.java:249)

有什么好的方法来处理这个?

4

7 回答 7

2

没有一种单一的好方法可以验证数据,除非在使用数据之前就应该这样做。我建议不要拆分您的数据字符串,然后将它们单独转换为可能会遇到异常的正确数据类型,而是将您的数据字符串作为一个整体解析,Scanner这也可以为您提供类型安全性。

Double reputation = null;
String type = null, edge = null;

String dataString = "domain::foo::127";
Scanner scanner = new Scanner(dataString).useDelimiter("::");

if (scanner.hasNext()) {
    type = scanner.next();
} else
  throw new IllegalArgumentException("Type not found!");
if (scanner.hasNext()) {
    edge = scanner.next();
} else
  throw new IllegalArgumentException("Edge not found!");
if (scanner.hasNextDouble()) {
    reputation = scanner.nextDouble();
} else
  throw new IllegalArgumentException("Reputation not found!");

System.out.println(type); // domain
System.out.println(edge); // foo
System.out.println(reputation); // 127.0


一个同样好的方法是针对正则表达式测试完整的数据字符串(如果它不是太长的话),但代价是丢失关于哪个数据单元未通过验证的信息。

Pattern pattern = Pattern.compile("(\\w+)::(\\w+)::(\\d+)");
Matcher matcher = pattern.matcher(dataString);

if (matcher.matches()) {
    type = matcher.group(1);
    edge = matcher.group(2);
    reputation = Double.valueOf(matcher.group(3));
} else
  throw new IllegalArgumentException("Invalid input data");
于 2013-10-25T00:25:28.373 回答
1

使用正则表达式,您可以验证输入字符串是否有效!

String pattern = "[a-z]+::{1}[a-z]+::{1}[0-9]+(\\.[0-9][0-9]?)?";

String type, edge;
double reputation;

if(input.matches(pattern)){
    String[] typeChunks = input.split("::");
    type = typeChunks[0];
    edge = typeChunks[1];
    reputation = Double.parseDouble(typeChunks[2].trim());
}
else
    throw new IllegalArgumentException();

这个正则表达式将检查

  1. 字母类型
  2. 字母边缘
  3. 带或不带小数的数值信誉
  4. "::" 在所有三个之间
于 2013-10-25T00:45:40.097 回答
1

您需要处理数据格式错误的情况。这并不是一个详尽的验证,但它可能是一个开始的地方:

String[] format = "domain::foo::127".split("::");

...

boolean validateFormat(String[] format) {
  // Check for anything that you don't want coming through as data
  return format.length == 3;
}
于 2013-10-25T00:06:52.787 回答
0

创建一个简单的帮助类来检查你的字符串怎么样......比如

public class StringUtil {

public static boolean isNullOrEmpty(final String string)

{
return string == null || string.isEmpty() || string.trim().isEmpty();

}

}

所以这样就不需要使用trim()了。因为如果你在一个空字符串上使用 trim() 你会得到一个异常。但是你仍然需要处理 Double.parseDouble 中的 NumberFormatException。

因此,如果您不想每次都添加 try 和 catch 块,您可以为 Double.parseDouble 创建一个简单的包装器来捕获异常并以您的方式处理它们(假设返回 -1)。

double reputation = StringUtil.isNullOrEmpty(typeChunks[2])== true ? 0 : YourClass.methodToParseDoubleAndHandleException(typeChunks[2]);

于 2013-10-25T01:09:05.090 回答
0

if (!input.equals("")){之前使用 String[] typeChunks = input.split("::");,不要忘记关闭 }

于 2013-10-25T00:10:42.227 回答
0

您可以在解析字符串值之前进行验证:

double reputation = (typeChunks[2].trim() != null && 
                    !typeChunks[2].trim().isEmpty()) ? 
                     Double.parseDouble(typeChunks[2].trim()) : 0;
于 2013-10-25T00:10:43.300 回答
0

错误消息是由于处理空数据。

double reputation = 0;
final String reputStr = typeChunks[2];
if ((reputStr != null) && !("").equals(reputStr.trim()))
{
   reputation = Double.parseDouble(typeChunks[2].trim());
}
于 2013-10-25T00:18:24.200 回答