Я пытаюсь записать данные из базы данных в CSV-файл через поток Java. Для письма я использую банку OPENCSV. Проблема, с которой я сталкиваюсь, заключается в том, что иногда в значениях файла CSV искажаются, как показано ниже в строках 1 и 4. Я понятия не имею, почему это происходит. Значения, поступающие из базы данных, все в порядке (как видно из журналов), но в CSV-файле его нет.

[E[EcoUnit 01]  [Segment B/1]   [2017-12-29 22:13:23.047]   [ventilation air humidity]  [70.18]
[EcoUnit 01]    [Segment B/1]   [2017-10-25 22:21:36.583]   [ventilation air humidity]  [69.65]
[EcoUnit 01]    [Segment B/1]   [2017-10-25 22:22:36.59]    [ventilation air humidity]  [69.33]
[EcoUnit 01]    [Segment B/017-11-14 12:02:48.013]  [ventilation fan]   [30]    

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


List<String> values = new ArrayList<String>();
                    fw = new FileWriter(file);
                    writer = new CSVWriter(fw); 
                    writer.writeNext(headers);
                    values.add(doc.getFieldValue("Unit_Label").toString());
                    values.add(doc.getFieldValue("Segment_Label").toString());
                    values.add("[" + doc.getFieldValue("datestring").toString() + "]");
                    values.add(doc.getFieldValue("Item_Label").toString());
                    values.add(doc.getFieldValue("Value").toString());
                    writer.writeNext(values.toArray(new String[]{}));

Добавление полного кода функции, отвечающей за создание файла и запись в него.

public void createAndFillFile(String startDateStr, String endDateStr, int fileNumber,SolrDocumentList results){
        try{
            String startDateParts[] = startDateStr.split(" ");
            String startDate  = startDateParts[0];
            String endDateParts[] = endDateStr.split(" ");
            String endDate  = endDateParts[0];
            if(fileNumber == 1){

                Date date = new Date() ;
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss") ;

                String currentDate = dateFormat.format(date); //This line can be removed and in below line directly can be used
                zipFile = currentDate + ".zip";

                dir = new File("C:" + File.separator + "EcotronDownloadable" + File.separator + currentDate);


                dir.mkdir();

                path = dir.getAbsolutePath() + File.separator ;
                file = new File(path+ startDate + "_" + endDate + "_" + fileNumber + ".csv");
                fw = new FileWriter(file);
                writer = new CSVWriter(fw);
                writer.writeNext(headers);

            }
            synchronized(file){
            for (SolrDocument doc : results) {
                List<String> values = new ArrayList<String>();
                Thread.sleep(1);
                long fileLength = file.length();
                if(fileLength<maxFileSize){
                    values.add(doc.getFieldValue("Unit_Label").toString());
                    values.add(doc.getFieldValue("Segment_Label").toString());
                    values.add("[" + doc.getFieldValue("datestring").toString() + "]");
                    values.add(doc.getFieldValue("Item_Label").toString());
                    values.add(doc.getFieldValue("Value").toString());
                    //log.trace(values);
                    writer.writeNext(values.toArray(new String[]{}));
                }
                else{
                    fw.flush();
                    fw.close();
//                  writer.close();
                    j = j + 1;
                    file = new File(path + startDate + "_" + endDate  + "_" + j + ".csv") ;
                    fw = new FileWriter(file);
                    writer = new CSVWriter(fw); 
                    writer.writeNext(headers);
                    values.add(doc.getFieldValue("Unit_Label").toString());
                    values.add(doc.getFieldValue("Segment_Label").toString());
                    values.add("[" + doc.getFieldValue("datestring").toString() + "]");
                    values.add(doc.getFieldValue("Item_Label").toString());
                    values.add(doc.getFieldValue("Value").toString());
                    //log.trace(values);
                    writer.writeNext(values.toArray(new String[]{}));

                }
            }
            }

//          fw.flush();
//          fw.close();
//          writer.close();

        }
        catch (Exception e) {

            e.printStackTrace();
        }

    }

``
-1
nehag 21 Ноя 2019 в 15:41

1 ответ

Вы можете иметь два экземпляра FileWriter (в разных потоках ) , указывающие на тот же файл и запись одновременно.

Попробуй это:

    synchronized (file)
    {
        List<String> values = new ArrayList<String>();
        fw = new FileWriter(file);
        writer = new CSVWriter(fw);
        writer.writeNext(headers);
        values.add(doc.getFieldValue("Unit_Label").toString());
        values.add(doc.getFieldValue("Segment_Label").toString());
        values.add("[" + doc.getFieldValue("datestring").toString() + "]");
        values.add(doc.getFieldValue("Item_Label").toString());
        values.add(doc.getFieldValue("Value").toString());
        writer.writeNext(values.toArray(new String[]{}));
    }
0
VeryNiceArgumentException 21 Ноя 2019 в 15:54
Большое спасибо за ответ, но проблема по-прежнему та же. Синхронизировал файл, но результаты такие же.
 – 
nehag
21 Ноя 2019 в 17:05
Добавлен полный код функции, отвечающей за создание файла и запись в файл в вопросе.
 – 
nehag
21 Ноя 2019 в 17:11
- Я знаю, что вы оставили часть записи (writer.writeNext (заголовки)) вне синхронизированного блока. Проверить это
 – 
VeryNiceArgumentException
21 Ноя 2019 в 17:42