aurelius
aurelius

Reputation: 4076

How to generate java class from csv file

I have multiple csv files containing about 200 to 300 columns and I need to create pojos out of them with a mapping of one to one (column too java class field). Never mind the fact that is not recommended. If you know a tool or how to do this automatically please pitch in.

so you have a csv file, containing thousands of rows with hundreds of columns, the first row contains the header of the columns. SO what I need, based on the first row (header of column) to create a java class that contains those headers as class fields. Never mind the actual data. I just need a java class with those fields

There was a question regarding somewhat this post but this was asked about 3 years ago, so I guess is obsolete.

Upvotes: 4

Views: 8491

Answers (3)

tucuxi
tucuxi

Reputation: 17955

This version doesn't use any fancy class-generating code; instead, it outputs Java source-files (or more accurately, a single class file, with a static public inner subclass for each non-header row in the CSV).

For the following input (borrowed from Binkan):

############
foo,bar
############
he"l\nl"o,world
cafe,babe

The output would be:

public class Out {
    public static class Row1 {
        public String foo = "he\"l\\nl\"o";
        public String bar = "world";
    }
    public static class Row2 {
        public String foo = "cafe";
        public String bar = "babe";
    }
}

And here is the code; partially adapted from Binkan's as regards line-by-line reading:

public class T {

    public static void classesFromRows(String fileName, PrintWriter out, String classNamePrefix) throws Exception{
        try(BufferedReader stream = new BufferedReader(new FileReader(fileName))) {
            String line = null;
            String[] fields = null;
            int rowNum = 0;
            while ((line = stream.readLine()) != null) {
                if (line.isEmpty() || line.startsWith("#")) {
                    // do nothing
                } else if (fields == null) {
                    fields = line.split(",");
                } else {
                    rowNum ++;
                    String[] values = line.split(",");
                    out.println("\tpublic static class " + classNamePrefix + rowNum + " {");
                    for (int i=0; i<fields.length; i++) {
                        out.println("\t\tpublic String " + fields[i] + " = \"" 
                            + StringEscapeUtils.escapeJava(values[i]) + "\";");
                    }
                    out.println("\t}");
                }           
            }
        }
    }

    // args[0] = input csv; args[1] = output file
    public static void main(String[] args) throws Exception {       
        File outputFile = new File(args[1]);
        String outputClass = outputFile.getName().replace(".java", "");
        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
        // missing: add a package here, if you want one
        out.println("public class " + outputClass + " {");
        classesFromRows(args[0], out, "Row");
        out.println("}");
        out.close();
    }
}

I have chosen to consider all data as strings (on the bright side, I am escaping them correctly using StringEscapeUtils); with some more code, you could specify other types.

Upvotes: 1

Harshavardhan Konakanchi
Harshavardhan Konakanchi

Reputation: 4294

As per my undersatnding, you are trying to read a csv file with large range of columns, being treated it as a table for database

My solution is as follows

  • Use csvjdbc to query the data columns

This can be done by using the file as data source and csvjdbc driver, and using the Metadata, you can retrieve all the columns

  • Create a runtime POJO Class using tool Provider

This can be done and a refernce is at here

Upvotes: 1

Binkan Salaryman
Binkan Salaryman

Reputation: 3058

You can use Javassist to generate classes at runtime:

Code:

public static void main(String[] args) throws Exception {
    String[] fieldNames = null;
    Class<?> rowObjectClass = null;
    try(BufferedReader stream = new BufferedReader(new InputStreamReader(Program.class.getResourceAsStream("file.csv")))) {
        while(true) {
            String line = stream.readLine();
            if(line == null) {
                break;
            }
            if(line.isEmpty() || line.startsWith("#")) {
                continue;
            }
            if(rowObjectClass == null) {
                fieldNames = line.split(",");
                rowObjectClass = buildCSVClass(fieldNames);
            } else {
                String[] values = line.split(",");
                Object rowObject = rowObjectClass.newInstance();
                for (int i = 0; i < fieldNames.length; i++) {
                    Field f = rowObjectClass.getDeclaredField(fieldNames[i]);
                    f.setAccessible(true);
                    f.set(rowObject, values[i]);

                }
                System.out.println(reflectToString(rowObject));
            }
        }
    }
}

private static int counter = 0;
public static Class<?> buildCSVClass(String[] fieldNames) throws CannotCompileException, NotFoundException {
    ClassPool pool = ClassPool.getDefault();
    CtClass result = pool.makeClass("CSV_CLASS$" + (counter++));
    ClassFile classFile = result.getClassFile();
    ConstPool constPool = classFile.getConstPool();
    classFile.setSuperclass(Object.class.getName());
    for (String fieldName : fieldNames) {
        CtField field = new CtField(ClassPool.getDefault().get(String.class.getName()), fieldName, result);
        result.addField(field);
    }
    classFile.setVersionToJava5();
    return result.toClass();
}

public static String reflectToString(Object value) throws IllegalAccessException {
    StringBuilder result = new StringBuilder(value.getClass().getName());
    result.append("@").append(System.identityHashCode(value)).append(" {");
    for (Field f : value.getClass().getDeclaredFields()) {
        f.setAccessible(true);
        result.append("\n\t").append(f.getName()).append(" = ").append(f.get(value)).append(", ");
    }
    result.delete(result.length()-2, result.length());
    return result.append("\n}").toString();
}


Resources:

file.csv (classpath):

############
foo,bar
############
hello,world
cafe,babe


Output:

CSV_CLASS$0@1324706137 {
    foo = hello, 
    bar = world
}
CSV_CLASS$0@1373076110 {
    foo = cafe, 
    bar = babe
}

Upvotes: 8

Related Questions