Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用SuperCSV ICsvBeanReader解析枚举_Java_Csv_Enums_Supercsv - Fatal编程技术网

Java 使用SuperCSV ICsvBeanReader解析枚举

Java 使用SuperCSV ICsvBeanReader解析枚举,java,csv,enums,supercsv,Java,Csv,Enums,Supercsv,我解析CSV文件并使用创建域对象。我的域对象有一个枚举字段,例如: public class TypeWithEnum { private Type type; public TypeWithEnum(Type type) { this.type = type; } public Type getType() { return type; } public void setType(Type type) { this.type = type; } } 我的枚举如

我解析CSV文件并使用创建域对象。我的域对象有一个枚举字段,例如:

public class TypeWithEnum {

private Type type;

public TypeWithEnum(Type type) {
    this.type = type;
}

public Type getType() {
    return type;
}

public void setType(Type type) {
    this.type = type;
}
}
我的枚举如下所示:

public enum Type {

    CANCEL, REFUND
}
class MyCellProcessor extends CellProcessorAdaptor {
    public Object execute(Object value, CSVContext context) {
        Type type = Type.valueOf(value.toString());
        return next.execute(type, context);
    }
}
正在尝试从此CSV文件创建bean:

final String[] header = new String[]{ "type"  };
ICsvBeanReader inFile = new CsvBeanReader(new FileReader(
    getFilePath(this.getClass(), "learning/enums.csv")), CsvPreference.STANDARD_PREFERENCE);

final CellProcessor[] processors = 
    new CellProcessor[]{ TODO WHAT TO PUT HERE? };
TypeWithEnum myEnum = inFile.read(
    TypeWithEnum.class, header, processors);
这与 填充对象上下文时出错:null有问题的处理器:null 位于org.supercsv.io.CsvBeanReader.fillObject(未知源) 位于org.supercsv.io.CsvBeanReader.read(未知来源)

有关于解析枚举的提示吗?我应该为此编写自己的处理器吗

我已经尝试编写自己的处理器,类似这样:

public enum Type {

    CANCEL, REFUND
}
class MyCellProcessor extends CellProcessorAdaptor {
    public Object execute(Object value, CSVContext context) {
        Type type = Type.valueOf(value.toString());
        return next.execute(type, context);
    }
}
但它也死了,只有一个例外

my enums.csv文件的内容很简单:

取消

退款

我试图重现您的错误,但一切都对我有效。我使用超级SV 1.52:

  private enum ENUMS_VALUES{TEST1, TEST2, TEST3};
  @Test
  public void testEnum3() throws IOException
  {
    String testInput = new String("TEST1\nTEST2\nTEST3");
    ICsvBeanReader  reader = new CsvBeanReader(new StringReader(testInput), CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE);
    final String[] header = new String[] {"header"};
    reader.read(this.getClass(), header, new CellProcessor[] {new CellProcessorAdaptor() {

      @Override
      public Object execute(Object pValue, CSVContext pContext)
      {
        return next.execute(ENUMS_VALUES.valueOf((String)pValue), pContext);
      }}});

  }

  @Test
  public void testEnum4() throws IOException
  {
    String testInput = new String("TEST1\nTEST2\nTEST3");
    ICsvBeanReader reader = new CsvBeanReader(new StringReader(testInput), CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE);
    final String[] header = new String[] {"header"};
    reader.read(this.getClass(), header, new CellProcessor[] {new CellProcessorAdaptor()
    {

      @Override
      public Object execute(Object pValue, CSVContext pContext)
      {
        return ENUMS_VALUES.valueOf((String)pValue);
      }}});
  }

  public void setHeader(ENUMS_VALUES value)
  {
    System.out.println(value);
  }

您遇到的异常是,CsvBeanReader无法实例化
TypeWithEnum
类,因为它没有默认(无参数)构造函数。打印堆栈跟踪可能是一个好主意,这样您就可以看到出错的全部细节

Super CSV依赖于这样一个事实,即您应该为其每个字段提供一个有效的类,即具有默认构造函数和公共getter/setter的类

因此,您可以通过将以下内容添加到
TypeWithEnum
来修复异常:

public TypeWithEnum(){
}
关于解析枚举的提示,有两个最简单的选项:

1。使用HashMapper处理器

@Test
public void hashMapperTest() throws Exception {

    // two lines of input
    String input = "CANCEL\nREFUND";

    // you could also put the header in the CSV file
    // and use inFile.getCSVHeader(true)
    final String[] header = new String[] { "type" };

    // map from enum name to enum
    final Map<Object, Object> typeMap = new HashMap<Object, Object>();
    for( Type t : Type.values() ) {
        typeMap.put(t.name(), t);
    }

    // HashMapper will convert from the enum name to the enum
    final CellProcessor[] processors = 
        new CellProcessor[] { new HashMapper(typeMap) };

    ICsvBeanReader inFile = 
        new CsvBeanReader(new StringReader(input),
        CsvPreference.STANDARD_PREFERENCE);

    TypeWithEnum myEnum;
    while((myEnum = inFile.read(TypeWithEnum.class, header, processors)) !=null){
        System.out.println(myEnum.getType());
    }

}
用它

@Test
public void customProcessorTest() throws Exception {

    // two lines of input
    String input = "CANCEL\nREFUND";

    final String[] header = new String[] { "type" };

    // HashMapper will convert from the enum name to the enum
    final CellProcessor[] processors = 
        new CellProcessor[] { new TypeProcessor() };

    ICsvBeanReader inFile = 
        new CsvBeanReader(new StringReader(input),
        CsvPreference.STANDARD_PREFERENCE);
    TypeWithEnum myEnum;
    while((myEnum = inFile.read(TypeWithEnum.class, header, processors)) !=null){
        System.out.println(myEnum.getType());
    }

}

我正在准备即将发布的超级CSV。我会确保更新网站,以明确您必须拥有一个有效的JavaBean,可能还有对可用处理器的描述,对于那些不喜欢阅读Javadoc的人。

这里是一个用于枚举的通用单元处理器

/** A cell processor to convert strings to enums. */
public class EnumCellProcessor<T extends Enum<T>> implements CellProcessor {

    private Class<T> enumClass;
    private boolean ignoreCase;

    /**
     * @param enumClass the enum class used for conversion
     */
    public EnumCellProcessor(Class<T> enumClass) {
        this.enumClass = enumClass;
    }

    /**
     * @param enumClass the enum class used for conversion
     * @param ignoreCase if true, the conversion is made case insensitive
     */
    public EnumCellProcessor(Class<T> enumClass, boolean ignoreCase) {
        this.enumClass = enumClass;
        this.ignoreCase = ignoreCase;
    }

    @Override
    public Object execute(Object value, CsvContext context) {
        if (value == null)
            return null;

        String valueAsStr = value.toString();

        for (T s : enumClass.getEnumConstants()) {
            if (ignoreCase ? s.name().equalsIgnoreCase(valueAsStr) : s.name().equals(valueAsStr)) {
                return s;
            }
        }

        throw new SuperCsvCellProcessorException(valueAsStr + " cannot be converted to enum " + enumClass.getName(), context, this);
    }

}
/**用于将字符串转换为枚举的单元处理器*/
公共类EnumCellProcessor实现CellProcessor{
私有类;
私有布尔型忽略事件;
/**
*@param enumClass用于转换的枚举类
*/
公共EnumCellProcessor(类enumClass){
this.enumClass=enumClass;
}
/**
*@param enumClass用于转换的枚举类
*@param ignoreCase如果为true,则转换不区分大小写
*/
公共EnumCellProcessor(类enumClass,布尔ignoreCase){
this.enumClass=enumClass;
this.ignoreCase=ignoreCase;
}
@凌驾
公共对象执行(对象值,CsvContext上下文){
如果(值==null)
返回null;
字符串值asstr=value.toString();
对于(ts:enumClass.getEnumConstants()){
if(ignoreCase?s.name().equalsIgnoreCase(valueAsStr):s.name().equals(valueAsStr)){
返回s;
}
}
抛出新的SuperSvCellProcessorException(valueAsStr+“无法转换为enum”+enumClass.getName(),上下文,此);
}
}
你会用它的

new EnumCellProcessor<Type>(Type.class);
新的EnumCellProcessor(Type.class);

您需要编写自己的处理器,supercsv中没有适合的解析器。好的,很高兴知道这是正确的方法。我尝试编写自己的处理器时编辑了这个问题(第一次询问堆栈溢出问题,所以我仍然学习如何正确地执行-请耐心:)我更新了我的答案,如果仍然出现错误,您可以发布enum.csv的内容吗?仅供参考。它包括许多错误修复和新功能(包括Maven支持和用于映射嵌套属性和数组/集合的新Dozer扩展)。该值不是null-已使用调试器对此进行了检查。“type”变量被分配了正确的枚举值。将枚举的内容添加到问题中。@TomekKaczanowski然后我怀疑枚举在某个地方破坏了Supercsv:)您必须调试Supercsv才能找到:/src在您下载的包中。无论如何,感谢您的帮助!我可能会使用另一个bean(使用字符串而不是枚举),然后在真正的bean上创建一个复制构造函数或类似的东西。@TomekKaczanowski我试图重现您的错误,但一切都对我有效,请参阅我的edit,因此我似乎做了一些愚蠢的事情。:)我已经实现了另一个解决方案(使用另一个无枚举的POJO),但将根据您的提示再次尝试。我一定会在这里发布我的发现。或者,你可以将两个
令牌
处理器链接在一起以获得相同的效果,例如
final CellProcessor[]processors=new CellProcessor[]{new Token(Type.CANCEL.name(),Type.CANCEL,new Token(Type.return.name(),Type.return))
我还将此作为一个补丁添加到SuperCSV,它可能会进入下一个版本。Adrian能否请您确认它是添加到SuperCSV的,因为我正在使用它,我必须使用它。我已经不再关注此项目,并且在项目中无法看到此类,因此很可能作者没有接受我的补丁。对不起!也许您可以控制我把这个贡献给这个项目。