是否有基于CSV文件生成.java Bean文件的Java库?

时间:2014-05-15 11:17:58

标签: java csv

例如,如果我有一个CSV这样的文件:

name, age, height
joe, 23, 180.5

我需要一个Blah.java bean文件自动生成如下:

public class Blah{

  String name;
  int age;
  float height;

  // getters and setters...
}

是否有可以实现这一目标的图书馆?我当然搜索过,但空手而归。

3 个答案:

答案 0 :(得分:3)

我不知道现有的库能够做到这一点(我没有进行网络搜索,因为很可能,你在提问之前已经这样做了)。

  

(编辑:似乎在bchetty链接的答案中使用的库至少接近你一直在寻找的那个)

对于最简单的情况,这是通过几行代码完成的 - 尽管严格来说,根本不可能:从CSV文件中,您无法获得任何代码有关列的类型的信息。 (在下面的示例中,我通过手动指定列的类型来解决此问题。)

此外,在许多情况下,写一个简单的"很容易。解决方案,但在第一次拍摄后,需求得到了扩展,事实证明,从一开始就使用复杂的解决方案将是有益的。因此,如果您稍后要将其扩展为

  • 可配置的格式(缩进,方括号......)
  • 索引属性
  • 非原始值类型(例如,Person包含Address对象作为属性)
  • 约束属性(即PropertyChangeSupport
  • ...或其他任何不仅仅是写一些吸气剂+设定者

那么您应该考虑使用允许您描述类的基础结构。我现在正在考虑类似Eclipse JDT之类的东西,当然,对于目前的问题,这将是一种过度杀伤力。

  

编辑2:根据评论,使用一些代码扩展了代码片段""推断""列的类型。请注意,这是一种非常简单实用的方法,它不会进行复杂的错误检查,并且在某些情况下结果可能不是所需的结果。例如。当一列包含第一行中的字符串100时,列类型将推断为int,尽管在第二行中,同一列可以包含字符串123.456,应该被视为double - 不要谈论缺失或特殊的价值观,例如比如-意思是"没有可用数据"。如果某些内容无法根据第一行无法推断为intdouble,则会将其视为String

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class BeanGenerator
{
    public static void main(String[] args) throws IOException
    {
        //testManualSetup();
        testAutomaticSetup();
    }

    private static void testManualSetup()
    {
        List<BeanProperty> beanProperties = 
            new ArrayList<BeanProperty>();
        beanProperties.add(new BeanProperty("name", String.class));
        beanProperties.add(new BeanProperty("age", Integer.TYPE));
        beanProperties.add(new BeanProperty("height", Double.TYPE));

        String result = generateBeanFile("Person", "", beanProperties);
        System.out.println(result);
    }

    private static void testAutomaticSetup() throws IOException
    {
        List<BeanProperty> beanProperties = inferBeanProperties("test.csv"); 

        System.out.println("Inferred properties:");
        for (BeanProperty beanProperty : beanProperties)
        {
            System.out.println(beanProperty);
        }

        String result = generateBeanFile("Person", "", beanProperties);
        System.out.println(result);
    }


    static List<BeanProperty> inferBeanProperties(String fileName) throws IOException
    {
        FileInputStream fileInputStream = null;
        try
        {
            fileInputStream = new FileInputStream(fileName);
            return inferBeanProperties(fileInputStream);
        }
        finally
        {
            if (fileInputStream != null)
            {
                fileInputStream.close();
            }
        }
    }


    private static List<BeanProperty> inferBeanProperties(
        InputStream inputStream) throws IOException
    {
        final String delimiter = ",";
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        List<String> names = null;
        List<Class<?>> types = null;
        while (true)
        {
            String line = br.readLine();
            if (line == null)
            {
                return Collections.emptyList();
            }
            if (line.trim().length()==0)
            {
                continue;
            }
            if (names == null)
            {
                names = tokenize(line, delimiter);
            }
            else
            {
                types = inferTypes(line, delimiter);
                break;
            }
        }
        List<BeanProperty> beanProperties = new ArrayList<BeanProperty>();
        for (int i=0; i<names.size(); i++)
        {
            String name = names.get(i);
            Class<?> type = types.get(i);
            BeanProperty beanProperty = new BeanProperty(name, type);
            beanProperties.add(beanProperty);
        }
        return beanProperties;
    }

    private static List<String> tokenize(String line, String delimiter)
    {
        List<String> list = new ArrayList<String>();
        String tokens[] = line.split(delimiter);
        for (String token : tokens)
        {
            list.add(token.trim());
        }
        return list;
    }
    private static List<Class<?>> inferTypes(String line, String delimiter)
    {
        List<String> tokens = tokenize(line, delimiter);
        List<Class<?>> types = new ArrayList<Class<?>>();
        for (String token : tokens)
        {
            types.add(inferType(token));
        }
        return types;
    }


    private static Class<?> inferType(String token)
    {
        try
        {
            Integer.parseInt(token);
            return Integer.TYPE;
        }
        catch (NumberFormatException e)
        {
            // Ignored
        }
        try
        {
            Double.parseDouble(token);
            return Double.TYPE;
        }
        catch (NumberFormatException e)
        {
            // Ignored
        }
        return String.class;
    }


    static class BeanProperty
    {
        private final String name;
        private final Class<?> type;

        BeanProperty(String name, Class<?> type)
        {
            this.name = name;
            this.type = type;
        }

        String getName()
        {
            return name;
        }

        Class<?> getType()
        {
            return type;
        }

        @Override
        public String toString()
        {
            return name+": "+type;
        }
    }

    static String generateBeanFile(String beanName,
        String header, 
        List<BeanProperty> beanProperties)
    {
        StringBuilder sb = new StringBuilder();

        sb.append(header);

        sb.append("public class "+beanName+"\n");
        sb.append("{"+"\n");
        for (BeanProperty beanProperty : beanProperties)
        {
            sb.append("    private ");
            sb.append(beanProperty.getType().getSimpleName());
            sb.append(" ");
            sb.append(decapitalize(beanProperty.getName()));
            sb.append(";"+"\n");
        }
        sb.append("\n");
        sb.append("    public "+beanName+"()"+"\n");
        sb.append("    {"+"\n");
        sb.append("        // Default constructor"+"\n");
        sb.append("    }"+"\n");
        for (BeanProperty beanProperty : beanProperties)
        {
            sb.append("\n");
            sb.append(createSetterString(beanProperty));
            sb.append("\n");
            sb.append(createGetterString(beanProperty));
        }
        sb.append("}"+"\n");
        return sb.toString();
    }

    private static String createSetterString(BeanProperty beanProperty)
    {
        StringBuilder sb = new StringBuilder();

        sb.append("    public void set");
        sb.append(capitalize(beanProperty.getName()));
        sb.append("(");
        sb.append(beanProperty.getType().getSimpleName());
        sb.append(" ");
        sb.append(decapitalize(beanProperty.getName()));
        sb.append(")"+"\n");

        sb.append("    {"+"\n");

        sb.append("        this.");
        sb.append(decapitalize(beanProperty.getName()));
        sb.append(" = ");
        sb.append(decapitalize(beanProperty.getName()));
        sb.append(";"+"\n");

        sb.append("    }"+"\n");

        return sb.toString();
    }

    private static String createGetterString(BeanProperty beanProperty)
    {
        StringBuilder sb = new StringBuilder();

        sb.append("    public ");
        sb.append(beanProperty.getType().getSimpleName());
        sb.append(" get");
        sb.append(capitalize(beanProperty.getName()));
        sb.append("()"+"\n");

        sb.append("    {"+"\n");

        sb.append("        return ");
        sb.append(decapitalize(beanProperty.getName()));
        sb.append(";"+"\n");

        sb.append("    }"+"\n");

        return sb.toString();
    }

    private static String decapitalize(String s)
    {
        char c = Character.toLowerCase(s.charAt(0));
        return c + s.substring(1);
    }

    private static String capitalize(String s)
    {
        char c = Character.toUpperCase(s.charAt(0));
        return c + s.substring(1);
    }

}

答案 1 :(得分:2)

您可以使用Apache-Commons-CSV来解析CSV文件,然后使用use CGLIB to generate Java class files at runtime

答案 2 :(得分:-1)

虽然到目前为止我还没有使用它,但是SuperCSV [你已经在你的标签中有了]]有2个自定义bean读取器。 CsvBeanReader and CsvDozerBeanReader。请参阅以下网站上的sample

/**
 * An example of reading using CsvBeanReader.
 */
private static void readWithCsvBeanReader() throws Exception {

        ICsvBeanReader beanReader = null;
        try {
                beanReader = new CsvBeanReader(new FileReader(CSV_FILENAME), CsvPreference.STANDARD_PREFERENCE);

                // the header elements are used to map the values to the bean (names must match)
                final String[] header = beanReader.getHeader(true);
                final CellProcessor[] processors = getProcessors();

                CustomerBean customer;
                while( (customer = beanReader.read(CustomerBean.class, header, processors)) != null ) {
                        System.out.println(String.format("lineNo=%s, rowNo=%s, customer=%s", beanReader.getLineNumber(),
                                beanReader.getRowNumber(), customer));
                }

        }
        finally {
                if( beanReader != null ) {
                        beanReader.close();
                }
        }
}

<强>更新

请注意,您无法创建java类本身,因为您需要知道它从文件中读取的POJO。如果您需要实际创建类文件,您可能需要考虑使用CsvListReader来读取行,然后使用getter和setter手动生成类。但是,您可能需要包含其他元数据,例如&#34;字段类型&#34;。