我正在尝试创建一个 csv 文件,其中的标题来自地图,值来自对象。我有一个 Java 对象,它存储不同的属性数据。
public class MyObject {
private String name;
private String email;
private Integer id;
private String phone;
getters and setters...
}
我有一个 Map,其中用户有键值对,其中键是 MyObject 的属性名称,值是 csv 文件的列标题。 例如:
Map<String, String> columnMap = new HashMap<>();
columnMap.put("id", "Id");
columnMap.put("name", "User Name");
columnMap.put("email", "User Email");
columnMap.put("phone", "User Phone");
我的目标是从数据创建一个 csv 文件,我首先要从地图中检索值以设置为标题,然后根据 MyObject 类中存储的内容创建行。 例如:
public class CopyMapToSBForFile {
public static void main(String[] args) {
List<MyObject> myObjects = new ArrayList<>();
MyObject myObject1 = new MyObject();
myObject1.setId(1);
myObject1.setName("Name 1");
myObject1.setEmail("Email 1");
myObject1.setPhone("111-121-2121");
MyObject myObject2 = new MyObject();
myObject2.setId(2);
myObject2.setName("Name 2");
myObject2.setEmail("Email 2");
myObject2.setPhone("111-121-2121");
MyObject myObject3 = new MyObject();
myObject3.setId(3);
myObject3.setName("Name 3");
myObject3.setEmail("Email 3");
myObject3.setPhone("111-121-2121");
myObjects.add(myObject1);
myObjects.add(myObject2);
myObjects.add(myObject3);
Map<String, String> columnMap = new HashMap<>();
columnMap.put("id", "Id");
columnMap.put("name", "User Name");
columnMap.put("email", "User Email");
columnMap.put("phone", "User Phone");
Field[] fields = MyObject.class.getDeclaredFields();
StringBuffer sb = new StringBuffer();
for (Field field : fields) {
System.out.println(field.getName());
if (columnMap.containsKey(field.getName())) {
sb.append(columnMap.get(field.getName()));
sb.append(",");
}
}
}
}
从上面的示例中,您可以看到使用反射 utils 我能够创建标头对象,但我坚持如何将 MyObject 中的值附加到 StringBuffer 对象以创建类似以下输出的内容:
User Name,User Email,Id,User Phone
Name 1,Email 1,1,111-121-2121
Name 2,Email 2,2,111-121-2121
Name 3,Email 3,3,111-121-2121
我有一个代码可以将 StringBuffer 转换为 CSV,但在创建标头后,我对如何创建上述输出感到困惑。另外,我想确保程序正确处理行,以防列的顺序发生变化,其中 Id 是第一列而不是第三列。
您不需要反射来创建标头。如果根据您的评论,地图仅包含对象中可用的字段,则只需从地图中获取值即可创建标题。使用 LinkedHashMap 而不是 HashMap,因为第一个保证顺序,而第二个则不保证顺序。对于内容,我建议每行/对象创建一个字符串数组,而不是使用 StringBuffer 或 StringBuilder,并将其余部分留给 opencsv 来处理分隔符、引号 .. 等。
请参阅以下示例作为起点。您可以通过不像我那样在主方法中执行所有操作来改进它,而是提取更多方法来创建标头、写入文件等并实现适当的错误处理。
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.opencsv.CSVWriter;
public class Example {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
List<MyObject> myObjects = createSampleList();
Map<String, String> columnMap = new LinkedHashMap<>();
columnMap.put("name", "User Name");
columnMap.put("id", "Id");
columnMap.put("email", "User Email");
columnMap.put("phone", "User Phone");
List<String[]> csvData = new ArrayList<>();
String[] header = columnMap.values().toArray(String[]::new);
csvData.add(header);
for (MyObject myObject : myObjects) {
List<String> row = new ArrayList<>();
for (String key : columnMap.keySet()) {
Field field = MyObject.class.getDeclaredField(key);
field.setAccessible(true);
String value = String.valueOf(field.get(myObject));
row.add(value);
}
csvData.add(row.toArray(String[]::new));
}
// default separator is a comma, default all fields are enclosed in double quotes, you can change this by providing a boolean flag writer.writeAll(csvData, false);
try (CSVWriter writer = new CSVWriter(new FileWriter("/path/to/your/csv/test.csv"))) {
writer.writeAll(csvData);
}
}
private static List<MyObject> createSampleList() {
List<MyObject> myObjects = new ArrayList<>();
MyObject myObject1 = new MyObject();
myObject1.setId(1);
myObject1.setName("Name 1");
myObject1.setEmail("Email 1");
myObject1.setPhone("111-121-2121");
MyObject myObject2 = new MyObject();
myObject2.setId(2);
myObject2.setName("Name 2");
myObject2.setEmail("Email 2");
myObject2.setPhone("111-121-2121");
MyObject myObject3 = new MyObject();
myObject3.setId(3);
myObject3.setName("Name 3");
myObject3.setEmail("Email 3");
myObject3.setPhone("111-121-2121");
myObjects.add(myObject1);
myObjects.add(myObject2);
myObjects.add(myObject3);
return myObjects;
}
public static class MyObject {
private String name;
private String email;
private Integer id;
private String phone;
//getters and setters
}
}