Обратная запись в CSV с Java с использованием Super CSV

Я уже давно работаю над этим кодом и просто хочу, чтобы мне давали простые советы, если я пройду тупик. Суть, в которой я сейчас нахожусь, состоит в том, чтобы собрать одинаковые ячейки из разных CSV-файлов и скопировать одну строку в другой CSV-файл. Вопрос на самом деле заключается в том, можно ли написать по конкретным строкам, скажем, например, если 2 строки совпадают в строке 50, я хочу записать обратно в строку 50. Я предполагаю, что я, возможно, извлеку все в хэш-карту, запишите это в тогда что тогда напишу обратно в файл.csv? Есть ли более простой способ?

например, у меня есть один CSV, в котором есть данные о человеке, а у другого есть данные о свойствах, где проживает реальный человек, я хочу скопировать данные об имуществе в CSV человека, а также сопоставить их с правильными данными о человеке. надеюсь, что это имеет смысл

public class Old {
 public static void main(String [] args) throws IOException
 {
   List<String[]> cols;
   List<String[]> cols1;

   int row =0;
   int count= 0;
   boolean b;
   CsvMapReader Reader = new CsvMapReader(new FileReader("file1.csv"), CsvPreference.EXCEL_PREFERENCE);
   CsvMapReader Reader2 = new CsvMapReader(new FileReader("file2.csv"), CsvPreference.EXCEL_PREFERENCE);

   try {
       cols = readFile("file1.csv");
       cols1 = readFile("fiel2.csv");
       String [] headers = Reader.getCSVHeader(true);

       headers = header(cols1,headers          

           } catch (IOException e) {
       e.printStackTrace();
       return;
   }

   for (int j =1; j<cols.size();j++) //1
   {
       for (int i=1;i<cols1.size();i++){
           if (cols.get(j)[0].equals(cols1.get(i)[0]))
           {


           }
       }

   }

}


private static List<String[]> readFile(String fileName) throws IOException
{
   List<String[]> values = new ArrayList<String[]>();
   Scanner s = new Scanner(new File(fileName));
   while (s.hasNextLine()) {
       String line = s.nextLine();
       values.add(line.split(","));
   }
   return values;
}
public static void csvWriter (String fileName, String [] nameMapping ) throws FileNotFoundException
{
    ICsvListWriter writer = new CsvListWriter(new PrintWriter(fileName),CsvPreference.STANDARD_PREFERENCE);
    try {
        writer.writeHeader(nameMapping);

    } catch (IOException e) {

        e.printStackTrace();
    }

}
public static String[] header(List<String[]> cols1, String[] headers){
    List<String> list = new ArrayList<String>();
    String [] add;
    int count= 0;
    for (int i=0;i<headers.length;i++){
        list.add(headers[i]);
    }

    boolean c;
    c= true;
    while(c)        {           
        add = cols1.get(0);
        list.add(add[count]);
        if (cols1.get(0)[count].equals(null))// this line is never read errpr
        {               
            c=false;
            break;
        } else  
        count ++;

    }

    String[] array = new String[list.size()];
    list.toArray(array);
    return array;

}

2 ответа

Решение

Просто будьте осторожны, если вы сначала прочитаете все адреса и личные данные (как предположил Томас) - если вы имеете дело только с небольшими CSV-файлами, то это нормально, но вам может не хватить памяти, если вы имеете дело с большие файлы.

В качестве альтернативы я собрал пример, который сначала читает адреса, а затем записывает объединенные данные о человеке / адресе, а он считывает данные о человеке.

Просто несколько вещей, чтобы отметить:

  • Я использовал CsvMapReader и CsvMapWriter, потому что вы были - это означало, что мне пришлось использовать карту, содержащую карту, для хранения адресов. Использование CsvBeanReader/CsvBeanWriter сделало бы это немного более элегантным.

  • Код из вашего вопроса на самом деле не использует Super CSV для чтения CSV (вы используете Scanner а также String.split()). Вы столкнетесь с проблемами, если ваш CSV содержит запятые в данных (что вполне возможно с адресами), поэтому гораздо безопаснее использовать Super CSV, который будет обрабатывать экранированные запятые для вас.

Пример:

package example;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import org.supercsv.io.CsvMapReader;
import org.supercsv.io.CsvMapWriter;
import org.supercsv.io.ICsvMapReader;
import org.supercsv.io.ICsvMapWriter;
import org.supercsv.prefs.CsvPreference;

public class CombiningPersonAndAddress {

    private static final String PERSON_CSV = "id,firstName,lastName\n"
            + "1,philip,fry\n2,amy,wong\n3,hubert,farnsworth";

    private static final String ADDRESS_CSV = "personId,address,country\n"
            + "1,address 1,USA\n2,address 2,UK\n3,address 3,AUS";

    private static final String[] COMBINED_HEADER = new String[] { "id",
            "firstName", "lastName", "address", "country" };

    public static void main(String[] args) throws Exception {

        ICsvMapReader personReader = null;
        ICsvMapReader addressReader = null;
        ICsvMapWriter combinedWriter = null;
        final StringWriter output = new StringWriter();

        try {
            // set up the readers/writer
            personReader = new CsvMapReader(new StringReader(PERSON_CSV),
                    CsvPreference.STANDARD_PREFERENCE);
            addressReader = new CsvMapReader(new StringReader(ADDRESS_CSV),
                    CsvPreference.STANDARD_PREFERENCE);
            combinedWriter = new CsvMapWriter(output,
                    CsvPreference.STANDARD_PREFERENCE);

            // map of personId -> address (inner map is address details)
            final Map<String, Map<String, String>> addresses = 
                    new HashMap<String, Map<String, String>>();

            // read in all of the addresses
            Map<String, String> address;
            final String[] addressHeader = addressReader.getCSVHeader(true);
            while ((address = addressReader.read(addressHeader)) != null) {
                final String personId = address.get("personId");
                addresses.put(personId, address);
            }

            // write the header
            combinedWriter.writeHeader(COMBINED_HEADER);

            // read each person
            Map<String, String> person;
            final String[] personHeader = personReader.getCSVHeader(true);
            while ((person = personReader.read(personHeader)) != null) {

                // copy address details to person if they exist
                final String personId = person.get("id");
                final Map<String, String> personAddress = addresses.get(personId);
                if (personAddress != null) {
                    person.putAll(personAddress);
                }

                // write the combined details
                combinedWriter.write(person, COMBINED_HEADER);
            }

        } finally {
            personReader.close();
            addressReader.close();
            combinedWriter.close();
        }

        // print the output
        System.out.println(output);

    }
}

Выход:

id,firstName,lastName,address,country
1,philip,fry,address 1,USA
2,amy,wong,address 2,UK
3,hubert,farnsworth,address 3,AUS

Из вашего комментария кажется, что у вас следующая ситуация:

  • Файл 1 содержит лиц
  • Файл 2 содержит адреса

Затем вы хотите сопоставить людей и адреса по некоторому ключу (одному или нескольким полям) и записать комбинацию обратно в файл CSV.

Таким образом, самый простой подход может быть что-то вроде этого:

//use a LinkedHashMap to preserve the order of the persons as found in file 1
Map<PersonKey, String[]> persons = new LinkedHashMap<>();
//fill in the persons from file 1 here

Map<PersonKey, String[]> addresses = new HashMap<>();
//fill in the addresses from file 2 here

List<String[]> outputLines = new ArrayList<>(persons.size());    
for( Map.Entry<PersonKey, String[]> personEntry: persons.entrySet() ) {
  String[] person = personEntry.getValue();
  String[] address = addresses.get( personEntry.getKey() );

  //merge the two arrays and put them into outputLines
}

//write outputLines to a file

Обратите внимание, что PersonKey может быть просто String или объект-обертка (Integer и т. д.), если вы можете сопоставить людей и адреса по одному полю. Если у вас есть больше полей, вам может понадобиться PersonKey объект с equals() а также hashCode() правильно переопределено.

Другие вопросы по тегам