用于将单记录csv文件读入类字段的编程习惯用法

时间:2012-06-15 09:51:11

标签: java oop design-patterns csv

假设我想阅读以下文件:

TestFile;100

进入班级的领域:

public class MyReader { 
    String field1;
    Integer field2;
}

阅读内容有两种略有不同的方式:

公共类MyReader {

public void loadValues(File file) throws IOException {

    //a generic method that reads the content file to a string throwing an IOException
    String line = readFileToString(file);
    String[] values = line.split(";");

    field1=values[0];
    field2=Integer.parseInt(values[1]);

}

//then i'll have well known getters:

public String getField1() {
  return field1;
} 

public Integer getField2() {
  return field2;
}

现在是第二个成语:

private String[] values; //made the values a class field

public void loadValues(File file) throws IOException {

    //a generic method that reads the content file to a string throwing an IOException
    String line = readFileToString(file);

    values = line.split(";");

}

public String getField1() {
  return values[0]
} 

public Integer getField2() {
  return Integer.parseInt(values[1]);
}

最大的区别在于异常管理。 我特意省略了捕获两种情况下可能发生的两个运行时异常:

  • ArrayIndexOutOfBoundsException如果文件包含少于两个字段
  • NumberFormatException如果整数解析失败

第一种方法
所有字段都在启动时加载。其中一个是不可解析的,我得到NumberFormatException。如果字段少于所需字段,我将获得越界异常。这听起来不错,特别是如果我想确保我将使用特定的一个事实背后的所有字段值的正确性:失败的快速范例。 假设我有一百个字段,该记录包含一个错误,而该错误又被记录到文件中以进行故障排除。原样,这段代码就是这样的:

Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)

即:我得到错误,导致错误的值,给出错误的行号,但不是字段名称。对开发人员有好处,对于通常无法访问源代码的系统engeneer来说不太好。

第二种方法
仅当通过getter 访问字段时,才会从数据字符串中“提取”和解析字段。 在相同的情况下,每个getter可能返回上述两个错误。 与“快速失败模式”相反,存在一定程度的“容错”。如果记录的第100个字段包含不正确的值,但该类的客户端不调用其getter,则永远不会抛出异常。 另一方面,当调用不正确值的getter时,记录的异常将包含导致问题的字段的信息(在堆栈跟踪中):

at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:449)
at java.lang.Integer.parseInt(Integer.java:499)

at com.test.MyReader.getField2(MyReader.java:39)

at com.test.MyReader.test(MyReader.java:33)
at com.test.MyReader.main(MyReader.java:16)

问题(S)

这两种方法都有利有弊,人们可以说决定采用哪种方法取决于具体情况。问题是:

  • getter和setter是javabeans的主题。他们返回异常是“可接受的”吗?
  • 两种方法中的类可能显然具有相同的接口,但由于它们具有完全不同的异常架构,因此客户端应该以完全不同的方式使用它们。那么如何向客户提出这个事实呢?也许吸气剂的语义是误导性的,或许有一种更有说服力的方式?

1 个答案:

答案 0 :(得分:2)

首先,第二种方法不会起作用,因为您将values []数组存储为局部变量,并且它不会被其他函数(在您的情况下为getter)访问。

第二个不要在你的getter中抛出异常,因为你暴露的api会误导并且不符合任何约定。

第三,不要自己解析字符串,而是考虑使用现成的库进行csv解析,而不是重新发明轮子,例如。 http://opencsv.sourceforge.net/

第四,为csv记录创建一个简单的POJO对象,你可以在为每个字段分配值的同时检查错误,然后抛出异常,提供默认值等。

希望有所帮助