如何从 opencsv 中的特定 header 中读取?
How to read from particular header in opencsv?
我有一个 csv 文件。我想从 it.For 示例中提取特定列:
说,我有 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 只读取来自 header caste1 的数据?
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]);
}
有关根据 header 确定列索引的更复杂方法,请参阅 the answer from Scott Conway。
正在查看 javadoc
如果您创建了一个CSVReader 对象,那么您可以使用.readAll 方法来拉取整个文件。它 returns 一个 String[] 列表,每个 String[] 代表文件的一行。所以现在你有了每一行的标记,你只想要它的第二个元素,所以把它们分开,因为它们已经用分隔符很好地提供给你了。在每一行你只需要第二个元素,所以:
public static void main(String[] args){
String data = "63,Graham,101153.06,Abraham";
String result[] = data.split(",");
System.out.print(result[1]);
}
Magnilex 和 Sparky 是正确的,因为 CSVReader 不支持按列名读取值。但话虽如此,您可以通过两种方式做到这一点。
假设您有列名并且默认的 CSVReader 读取 header,您可以首先搜索 header 的位置,然后从那里开始使用它;
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
class 和 HeaderColumnNameMappingStrategy
直接转换为具有与 header 列名称相同的变量的 object。
因此,首先您要定义一个包含字段的 class(实际上您只需要输入您想要的字段 - 多余的字段将被忽略,缺失的字段为 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());
}
来自opencsv docs:
Starting with version 4.2, there’s another handy way of reading CSV files that doesn’t even require creating special classes. If your CSV file has headers, you can just initialize a CSVReaderHeaderAware and start reading the values out as a map:
reader = new CSVReaderHeaderAware(new FileReader("yourfile.csv"));
record = reader.readMap();
.readMap()
将 return 一条记录。需要反复调用.readMap()
获取所有记录,直到运行到最后(或第一个空行)时得到null
,例如:
Map<String, String> values;
while ((values = reader.readMap()) != null) {
// consume the values here
}
class 也有另一个允许更多自定义的构造函数,例如:
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
);
One downside which I have found is that since the reader is lazy it does not offer a record count, therefore, if you need to know the total number (for example to display correct progress information), then you'll need to use another reader just for counting lines.
You also have available the CSVReaderHeaderAwareBuilder
我的任务是从现有的 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
我有一个 csv 文件。我想从 it.For 示例中提取特定列: 说,我有 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 只读取来自 header caste1 的数据?
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]);
}
有关根据 header 确定列索引的更复杂方法,请参阅 the answer from Scott Conway。
正在查看 javadoc
如果您创建了一个CSVReader 对象,那么您可以使用.readAll 方法来拉取整个文件。它 returns 一个 String[] 列表,每个 String[] 代表文件的一行。所以现在你有了每一行的标记,你只想要它的第二个元素,所以把它们分开,因为它们已经用分隔符很好地提供给你了。在每一行你只需要第二个元素,所以:
public static void main(String[] args){
String data = "63,Graham,101153.06,Abraham";
String result[] = data.split(",");
System.out.print(result[1]);
}
Magnilex 和 Sparky 是正确的,因为 CSVReader 不支持按列名读取值。但话虽如此,您可以通过两种方式做到这一点。
假设您有列名并且默认的 CSVReader 读取 header,您可以首先搜索 header 的位置,然后从那里开始使用它;
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
class 和 HeaderColumnNameMappingStrategy
直接转换为具有与 header 列名称相同的变量的 object。
因此,首先您要定义一个包含字段的 class(实际上您只需要输入您想要的字段 - 多余的字段将被忽略,缺失的字段为 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());
}
来自opencsv docs:
Starting with version 4.2, there’s another handy way of reading CSV files that doesn’t even require creating special classes. If your CSV file has headers, you can just initialize a CSVReaderHeaderAware and start reading the values out as a map:
reader = new CSVReaderHeaderAware(new FileReader("yourfile.csv"));
record = reader.readMap();
.readMap()
将 return 一条记录。需要反复调用.readMap()
获取所有记录,直到运行到最后(或第一个空行)时得到null
,例如:
Map<String, String> values;
while ((values = reader.readMap()) != null) {
// consume the values here
}
class 也有另一个允许更多自定义的构造函数,例如:
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
);
One downside which I have found is that since the reader is lazy it does not offer a record count, therefore, if you need to know the total number (for example to display correct progress information), then you'll need to use another reader just for counting lines.
You also have available the CSVReaderHeaderAwareBuilder
我的任务是从现有的 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