我有一个csv文件。我想从中提取特定的列。例如: 说,我有csv:
id1,caste1,salary,name1
63,Graham,101153.06,Abraham
103,Joseph,122451.02,Charlie
63,Webster,127965.91,Violet
76,Smith,156150.62,Eric
97,Moreno,55867.74,Mia
65,Reynolds,106918.14,Richard
如何使用opencsv只读取头文件caste1中的数据?
答案 0 :(得分:7)
Magnilex和Sparky是正确的,因为CSVReader不支持按列名读取值。但话说有两种方法可以做到这一点。
鉴于您拥有列名并且默认CSVReader读取标题,您可以在第一个标题中搜索该位置,然后从那里开始使用该标题;
private int getHeaderLocation(String[] headers, String columnName) {
return Arrays.asList(headers).indexOf(columnName);
}
所以你的方法看起来像(省去了你需要输入的大量错误检查)
CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
String [] nextLine;
int columnPosition;
nextLine = reader.readNext();
columnPosition = getHeaderLocation(nextLine, "castle1");
while ((nextLine = reader.readNext()) != null && columnPosition > -1) {
// nextLine[] is an array of values from the line
System.out.println(nextLine[columnPosition]);
}
如果时间紧迫,我只会做上述事情而且你只关心一栏。这是因为openCSV可以使用CsvToBean
类和HeaderColumnNameMappingStrategy
直接转换为具有与标题列名称相同的变量的对象。
首先,你要定义一个具有字段的类(实际上你只需要放入你想要的字段 - 额外的内容被忽略,缺少的是null或默认值)。
public class CastleDTO {
private int id1;
private String castle1;
private double salary;
private String name1;
// have all the getters and setters here....
}
然后你的代码看起来像
CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
HeaderColumnNameMappingStrategy<CastleDTO> castleStrategy = new HeaderColumnNameMappingStrategy<CastleDTO>();
CsvToBean<CastleDTO> csvToBean = new CsvToBean<CastleDTO>();
List<CastleDTO> castleList = csvToBean.parse(castleStrategy, reader);
for (CastleDTO dto : castleList) {
System.out.println(dto.getCastle1());
}
答案 1 :(得分:2)
opencsv中没有内置功能可以按名称从列中读取。
official FAQ example有关于如何从文件中读取的以下示例:
CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
System.out.println(nextLine[0] + nextLine[1] + "etc...");
}
您只需通过使用nextLine[1]
访问行来获取每行第二列中的值(请记住,数组索引基于零)。
因此,在您的情况下,您只需阅读第二行:
CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
System.out.println(nextLine[1]);
}
有关从标题中确定列索引的更复杂方法,请参阅the answer from Scott Conway。
答案 2 :(得分:1)
来自opencsv docs:
从4.2版开始,还有另一种便捷的方式来读取CSV文件,甚至不需要创建特殊的类。如果您的CSV文件具有标题,则只需初始化CSVReaderHeaderAware并开始将值作为地图读出即可:
reader = new CSVReaderHeaderAware(new FileReader("yourfile.csv"));
record = reader.readMap();
.readMap()
将返回一条记录。您需要反复调用.readMap()
来获取所有记录,直到null
到达结尾(或第一个空行)为止,例如:
Map<String, String> values;
while ((values = reader.readMap()) != null) {
// consume the values here
}
该类还具有另一个允许更多自定义的构造函数,例如:
CSVReaderHeaderAware reader = new CSVReaderHeaderAware(
new InputStreamReader(inputStream),
0, // skipLines
parser, // custom parser
false, // keep end of lines
true, // verify reader
0, // multiline limit
null // null for default locale
);
我发现一个缺点是,由于读者很懒,它没有提供记录数,因此,如果您需要知道总数(例如显示正确的进度信息),则需要使用另一个阅读器只是为了数行。
答案 3 :(得分:0)
我有一个任务要从现有的csv中删除几列,例如csv:
FirstName, LastName, City, County, Zip
Steve,Hopkins,London,Greater London,15554
James,Bond,Vilnius,Vilniaus,03250
我只需要带有值的FirstName和LastName列,并且顺序必须相同非常重要-默认rd.readMap()不会保留顺序,此任务的代码如下:
String[] COLUMN_NAMES_TO_REMOVE = new String[]{"", "City", "County", "Zip"};
CSVReaderHeaderAware rd = new CSVReaderHeaderAware(new StringReader(old.csv));
CSVWriter writer = new CSVWriter((new FileWriter(new.csv)),
CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.NO_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END);
// let's get private field
Field privateField = CSVReaderHeaderAware.class.getDeclaredField("headerIndex");
privateField.setAccessible(true);
Map<String, Integer> headerIndex = (Map<String, Integer>) privateField.get(rd);
// do ordering in natural order - 0, 1, 2 ... n
Map<String, Integer> sortedInNaturalOrder = headerIndex.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.naturalOrder()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
// let's get headers in natural order
List<String> headers = sortedInNaturalOrder.keySet().stream().distinct().collect(Collectors.toList());
// let's remove headers
List<String> removedColumns = new ArrayList<String>(Arrays.asList(COLUMN_NAMES_TO_REMOVE));
headers.removeAll(removedColumns);
// save column names
writer.writeNext(headers.toArray(new String[headers.size()]));
List<String> keys = new ArrayList<>();
Map<String, String> values;
while ((values = rd.readMap()) != null) {
for (String key : headers) {
keys.add(values.get(key));
if (keys.size() == headers.size()) {
String[] itemsArray = new String[headers.size()];
itemsArray = keys.toArray(itemsArray);
// save values
writer.writeNext(itemsArray);
keys.clear();
}
}
}
writer.flush();
输出:
FirstName, LastName
Steve,Hopkins
James,Bond
答案 4 :(得分:-2)
查看javadoc
如果您创建CSVReader对象,则可以使用方法.readAll来拉取整个文件。它返回一个String []列表,每个String []代表一行文件。所以现在你有每行的标记,你只需要第二个元素,所以将它们分开,因为它们已经很好地用分隔符给你了。在每一行上你只需要第二个元素,所以:
public static void main(String[] args){
String data = "63,Graham,101153.06,Abraham";
String result[] = data.split(",");
System.out.print(result[1]);
}