Como mesclar arquivos CSV em Java

Meu primeiro arquivo csv se parece com o header incluído (o header está incluído apenas no topo, não após cada input):

NAME,SURNAME,AGE Fred,Krueger,Unknown .... n records 

Meu segundo arquivo pode ser assim:

 NAME,MIDDLENAME,SURNAME,AGE Jason,Noname,Scarry,16 .... n records with this header template 

O arquivo mesclado deve ficar assim:

 NAME,SURNAME,AGE,MIDDLENAME Fred,Krueger,Unknown, Jason,Scarry,16,Noname .... 

Basicamente, se os headers não corresponderem, todos os novos títulos de header (colunas) devem ser adicionados após o header original e seus valores de acordo com essa ordem.

ATUALIZAR:

Acima de CSV foram reduzidos para que eu possa ilustrar o que eu quero alcançar, na realidade, arquivos CSV são gerados um passo antes disso (mesclar) e pode ser de até 100 colunas

Alguém tem alguma idéia de como posso fazer isso? Eu apreciaria qualquer ajuda

Eu criaria um modelo para o formato ‘maior’ (uma class simples com quatro campos e uma coleção para instâncias dessa class) e implementaria dois analisadores, um para o primeiro, um para o segundo modelo. Crie registros para todas as linhas de ambos os arquivos csv e implemente um gravador para gerar o csv no formato correto. Em resumo:

  public void convert(File output, File...input) { List records = new ArrayList(); for (File file:input) { if (input.isThreeColumnFormat()) { records.addAll(ThreeColumnFormatParser.parse(file)); } else { records.addAll(FourColumnFormatParser.parse(file)); } } CsvWriter.write(output, records); } 

De seu comentário eu vejo, que você tem um monte de diferentes formatos csv com algumas colunas comuns.

Você poderia definir o modelo para qualquer linha nos vários arquivos csv como este:

 public class Record { Object id; // some sort of unique identifier Map values; // all key/values of a single row public Record(Object id) {this.id=id;} public void put(String key, String value){ values.put(key, value); } public void get(String key) { values.get(key); } } 

Para analisar qualquer arquivo, você deve primeiro ler o header e adicionar os headers de coluna a um keystore global (será necessário posteriormente para a saída) e criar registros para todas as linhas, como:

 //... List records = new ArrayList() for (File file:getAllFiles()) { List keys = getColumnsHeaders(file); KeyStore.addAll(keys); // the store is a Set for (String line:file.getLines()) { String[] values = line.split(DELIMITER); Record record = new Record(file.getName()+i); // as an example for id for (int i = 0; i < values.length; i++) { record.put(keys.get(i), values[i]); } records.add(record); } } // ... 

Agora o keystore usou todos os nomes de header de coluna e podemos iterar sobre a coleção de todos os registros, obter todos os valores para todas as chaves (e obter null se o arquivo para esse registro não usou a chave), montar as linhas csv e gravar tudo para um novo arquivo.

Leia no header do primeiro arquivo e crie uma lista dos nomes das colunas. Agora leia o header do segundo arquivo e adicione os nomes das colunas que ainda não existem na lista ao final da lista. Agora você tem suas colunas na ordem que você quer e você pode escrever isso para o novo arquivo primeiro.

Em seguida, eu analisaria cada arquivo e, para cada linha, criaria um Mapa do nome da coluna para o valor. Depois que a linha for analisada, você poderá iterar sobre a nova lista de nomes de coluna e extrair os valores do mapa e gravá-los imediatamente no novo arquivo. Se o valor for nulo, não imprima nada (apenas uma vírgula, se necessário).

Pode haver soluções mais eficientes disponíveis, mas acho que isso atende aos requisitos estabelecidos.

Tente isto:

http://ondra.zizka.cz/stranky/programovani/ruzne/querying-transforming-csv-using-sql.texy

 crunch input.csv output.csv "SELECT AVG(duration) AS durAvg FROM (SELECT * FROM indata ORDER BY duration LIMIT 2 OFFSET 6)"