Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 46 additions & 2 deletions src/main/java/me/mneri/csv/CsvReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,52 @@ public T next() throws CsvException, IOException {
*/
public static <T> CsvReader<T> open(File file, CsvDeserializer<T> deserializer) throws IOException {
return open(file, CsvOptions.defaultOptions(), deserializer);
}

}

/**
* Opens a file for reading using {@link DefaultCsvDeserializer}, returning a {@code CsvReader}. Bytes from the file are
* decoded into characters using the default JVM charset. Reading commences at the beginning of the file.
*
* @param file the file to open.
* @param clazz The class of the objects.
* @param <T> the type of the objects to read.
* @return A new {@code CsvReader} to read the specified file.
* @throws IOException if an I/O error occurs.
*/
public static <T> CsvReader<T> open(File file, Class<T> clazz) throws IOException {
return open(file, CsvOptions.defaultOptions(), new DefaultCsvDeserializer<T>(clazz));
}

/**
* Opens a file for reading using {@link DefaultCsvDeserializer}, returning a {@code CsvReader}. Bytes from the file are
* decoded into characters using the default JVM charset. Reading commences at the beginning of the file.
*
* @param file the file to open.
* @param options reading options.
* @param clazz The class of the objects.
* @param <T> the type of the objects to read.
* @return A new {@code CsvReader} to read the specified file.
* @throws IOException if an I/O error occurs.
*/
public static <T> CsvReader<T> open(File file, CsvOptions options, Class<T> clazz) throws IOException {
return open(file, TextUtil.defaultCharset(), options, new DefaultCsvDeserializer<T>(clazz));
}

/**
* Opens a file for reading using {@link DefaultCsvDeserializer}, returning a {@code CsvReader}. Bytes from the file are
* decoded into characters using the specified charset. Reading commences at the beginning of the file.
*
* @param file the file to open.
* @param charset the charset of the file.
* @param clazz The class of the objects.
* @param <T> the type of the objects to read.
* @return A new {@code CsvReader} to read the specified file.
* @throws IOException if an I/O error occurs.
*/
public static <T> CsvReader<T> open(File file, Charset charset, Class<T> clazz) throws IOException {
return open(file, charset, CsvOptions.defaultOptions(), new DefaultCsvDeserializer<T>(clazz));
}

/**
* Opens a file for reading, returning a {@code CsvReader}. Bytes from the file are decoded into characters using
* the default JVM charset. Reading commences at the beginning of the file.
Expand Down
98 changes: 83 additions & 15 deletions src/main/java/me/mneri/csv/CsvWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,24 @@ public static <T> CsvWriter<T> open(File file, Charset charset, CsvOptions optio
throws IOException {
return open(Files.newBufferedWriter(file.toPath(), charset), options, serializer);
}

/**
* Opens or creates a file for writing, returning a {@code CsvWriter} that may be used to write object to the file in
* csv format. The file is opened for writing, created if it doesn't exist or initially truncated to a size of 0 if it
* exists. Characters are encoded using the specified charset. Objects are serialized using
* {@link DefaultCsvSerializer}.
*
* @param file the file to open.
* @param charset the charset to use for encoding.
* @param options writing options.
* @param clazz The class of the objects.
* @param <T> the type of the objects to serialize.
* @return A new {@code CsvWriter} to write into the specified file.
* @throws IOException if an I/O error occurs.
*/
public static <T> CsvWriter<T> open(File file, Charset charset, CsvOptions options, Class<T> clazz) throws IOException {
return open(Files.newBufferedWriter(file.toPath(), charset), options, new DefaultCsvSerializer<T>(clazz));
}

/**
* Opens or creates a file for writing, returning a {@code CsvWriter} that may be used to write object to the file
Expand All @@ -142,21 +160,71 @@ public static <T> CsvWriter<T> open(File file, Charset charset, CsvOptions optio
*/
public static <T> CsvWriter<T> open(File file, CsvSerializer<T> serializer) throws IOException {
return open(file, CsvOptions.defaultOptions(), serializer);
}

/**
* Opens or creates a file for writing, returning a {@code CsvWriter} that may be used to write object to the file
* in csv format. The file is opened for writing, created if it doesn't exist or initially truncated to a size of 0
* if it exists. Characters are encoded using the default JVM charset. Objects are serialized using the specified
* serializer.
*
* @param file the file to open.
* @param options writing options.
* @param serializer the serializer used to convert objects into csv lines.
* @param <T> the type of the objects to serialize.
* @return A new {@code CsvWriter} to write into the specified file.
* @throws IOException if an I/O error occurs.
*/
}

/**
* Opens or creates a file for writing, returning a {@code CsvWriter} that may be used to write object to the file in
* csv format. The file is opened for writing, created if it doesn't exist or initially truncated to a size of 0 if it
* exists. Characters are encoded using the default JVM charset. Objects are serialized using
* {@link DefaultCsvSerializer}.
*
* @param file the file to open.
* @param clazz The class of the objects.
* @param <T> the type of the objects to serialize.
* @return A new {@code CsvWriter} to write into the specified file.
* @throws IOException if an I/O error occurs.
*/
public static <T> CsvWriter<T> open(File file, Class<T> clazz) throws IOException {
return open(file, new DefaultCsvSerializer<T>(clazz));
}

/**
* Opens or creates a file for writing, returning a {@code CsvWriter} that may be used to write object to the file in
* csv format. The file is opened for writing, created if it doesn't exist or initially truncated to a size of 0 if it
* exists. Characters are encoded using the default JVM charset. Objects are serialized using
* {@link DefaultCsvSerializer}.
*
*
* @param file the file to open.
* @param options writing options.
* @param clazz The class of the objects.
* @param <T> the type of the objects to serialize.
* @return A new {@code CsvWriter} to write into the specified file.
* @throws IOException if an I/O error occurs.
*/
public static <T> CsvWriter<T> open(File file, CsvOptions options, Class<T> clazz) throws IOException {
return open(file, TextUtil.defaultCharset(), options, new DefaultCsvSerializer<T>(clazz));
}

/**
* Return a new {@code CsvWriter} using the specified {@link Writer} for writing and a {@link DefaultCsvSerializer} to
* serialize. Bytes file are encoded into characters using the writer's charset. Writing commences at the point
* specified by the reader.
*
* @param writer the {@link Writer} used to write.
* @param clazz The class of the objects.
* @param <T> the type of the objects to serialize.
* @return A new {@code CsvWriter} to write into the specified file.
*/
public static <T> CsvWriter<T> open(Writer writer, Class<T> clazz) {
return open(writer, CsvOptions.defaultOptions(), new DefaultCsvSerializer<T>(clazz));
}


/**
* Opens or creates a file for writing, returning a {@code CsvWriter} that may
* be used to write object to the file in csv format. The file is opened for
* writing, created if it doesn't exist or initially truncated to a size of 0 if
* it exists. Characters are encoded using the default JVM charset. Objects are
* serialized using the specified serializer.
*
* @param file the file to open.
* @param options writing options.
* @param serializer the serializer used to convert objects into csv lines.
* @param <T> the type of the objects to serialize.
* @return A new {@code CsvWriter} to write into the specified file.
* @throws IOException if an I/O error occurs.
*/
public static <T> CsvWriter<T> open(File file, CsvOptions options, CsvSerializer<T> serializer) throws IOException {
return open(file, TextUtil.defaultCharset(), options, serializer);
}
Expand Down
112 changes: 112 additions & 0 deletions src/main/java/me/mneri/csv/DefaultCsvDeserializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright 2018 Massimo Neri <[email protected]>
*
* This file is part of mneri/csv.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package me.mneri.csv;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* A {@link CsvDeserializer} to deserialize objects after they have been serialized with {@link DefaultCsvSerializer}.
* Values are passed to the fields using the <b>setters</b> of the class. <b>Transient</b> fields will be ignored.
*
* @author George Zougianos <a href="https://github.com/gzougianos">github.com/gzougianos</a>
*
* @param <T> The type of the Java objects to deserialize.
*/
public class DefaultCsvDeserializer<T> implements CsvDeserializer<T> {
private List<Method> setters;
private Class<T> clazz;

public DefaultCsvDeserializer(Class<T> clazz) {
this.clazz = clazz;
setters = new ArrayList<>();
Field[] fields = clazz.getDeclaredFields();
final Method[] methods = clazz.getMethods();
for (Field f : fields) {
f.setAccessible(true); // Need to access private field
if (Modifier.isTransient(f.getModifiers())) // Skip Transient fields
continue;
findSetter(methods, f.getName());
}
}

private void findSetter(Method[] methods, String fieldName) {
for (Method m : methods) {
if (m.getName().equalsIgnoreCase("set" + fieldName))
setters.add(m);
}
}

@Override
public T deserialize(RecyclableCsvLine line) throws Exception {
T obj = clazz.newInstance();
int lineId = 0;
for (Method m : setters) {
// Recognize the type of the value by the argument the setter has.
String argType = m.getParameterTypes()[0].getSimpleName();
Object val = null;
switch (argType.toLowerCase()) {
case "string":
val = line.getString(lineId);
break;
case "date":
val = line.getString(lineId);
if (val != null) {
long timestamp = Long.parseLong(String.valueOf(val));
val = new Date(timestamp);
}
break;
case "int":
case "integer":
val = line.getInteger(lineId);
break;
case "double":
val = line.getDouble(lineId);
break;
case "long":
val = line.getLong(lineId);
break;
case "float":
val = line.getFloat(lineId);
break;
case "short":
val = line.getShort(lineId);
break;
case "biginteger":
val = line.getBigInteger(lineId);
break;
case "bigdecimal":
val = line.getBigDecimal(lineId);
break;
default:
throw new CsvException("Cannot deserialize value for type " + argType + ".");
}
lineId++;
if (val != null) {
m.invoke(obj, val);
}
}
return obj;
}

}
80 changes: 80 additions & 0 deletions src/main/java/me/mneri/csv/DefaultCsvSerializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2018 Massimo Neri <[email protected]>
*
* This file is part of mneri/csv.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package me.mneri.csv;

import java.lang.reflect.Field;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* A {@link CsvSerializer} to serialize all (non <b>transient</b>) fields of an Object using {@link java.lang.reflect}
* package. <b>Getter methods</b> will be invoked in order to get the values of the fields. <b>Transient</b> fields will
* be ignored.
* @see DefaultCsvDeserializer
*
* @author George Zougianos <a href="https://github.com/gzougianos">github.com/gzougianos</a>
*
* @param <T> The type of the Java objects to serialize.
*/
public class DefaultCsvSerializer<T> implements CsvSerializer<T> {
private List<Method> getters;

public DefaultCsvSerializer(Class<T> clazz) {
getters = new ArrayList<>();
Field[] fields = clazz.getDeclaredFields();
final Method[] methods = clazz.getMethods();
for (Field f : fields) {
f.setAccessible(true); // Need to access private field
if (Modifier.isTransient(f.getModifiers())) // Skip Transient fields
continue;
findGetter(methods, f.getName());
}
}

private void findGetter(Method[] methods, String fieldName) {
for (Method m : methods) {
if (m.getName().equalsIgnoreCase("get" + fieldName))
getters.add(m);
}
}

@Override
public void serialize(T object, List<String> out) throws Exception {
for (Method getter : getters) {
Object obj = getter.invoke(object);
String value = "";
String returnType = getter.getReturnType().getName().toString();
if (obj != null) {
switch (returnType.toLowerCase()) {
case "java.util.date": // If it is a date, save it as timestamp
Date d = (Date) obj;
value = Long.toString(d.getTime());
break;
default:
value = obj.toString();
}
}
out.add(value.equalsIgnoreCase("null") ? "" : value);
}
}
}
Loading