【问题标题】:Creation of Batches from CSV resulting in erroneous state从 CSV 创建批次导致错误状态
【发布时间】:2013-01-29 18:58:09
【问题描述】:

我正在尝试从使用 opencsv 的 CSVWriter 编写的 CSV 文件进行批处理: CSVWriter writer = new CSVWriter(new FileWriter(filePath+createFileName), ',', CSVWriter.DEFAULT_QUOTE_CHARACTER);

和 BufferedReader 来读取写入的文件。 CSV文件被写入,我认为读取操作也很顺利。所以,到目前为止它工作得很好。但是,当我选择使用相同操作将特定数据写入 Csv 时,批次的创建就会出错。 出现异常,说明“无法解析 CSV。找到未转义的引号。带引号的值应在引号内”,这使应用程序无法以预期的方式运行。

经历此错误后,数据中似乎存在一些“”(双引号)或“(双引号)符号。(我的数据格式为“asdf”,“1.0”,“”, “定义”)。 据我了解,我尝试应用正则表达式来查找双引号但找不到任何双引号,因为在检查文件后它不包含重复的双引号。我关注的链接是:Regular expression to find and replace unescaped Non-successive double quotes in CSV file

此后在代码中,我使用: File tmpFile = File.createTempFile("bulkAPIInsert", ".csv");将数据保存在临时文件中,然后将其删除。

在用以下代码替换上述代码后,我以某种方式处理了即将到来的异常,但它进一步导致另一个声明“无法解析 CSV。EOF 在关闭打开的报价之前达到”。 文件 tmpFile = new File("bulkAPIInsert.csv");

我认为不应该遵循上述解决方法,因为这会是应用程序的性能问题。

通过查看 CSVReader 类,我发现定义的自定义异常声明与我得到的完全相同的异常。但我认为它是在某个双引号(CSV 文件的单元格值)中找到双引号时出现的。我将链接称为:https://github.com/mulesoft/salesforce-connector/blob/master/src/main/java/com/sforce/async/CSVReader.java

任何人都可以建议我哪里做错了或任何解决这个问题的方法吗?

我将代码 sn-p 分享给你: Method1 然后 Method2 被调用。

    Method1: private List<BatchInfo> createBatchesFromCSVFile(RestConnection connection,
            JobInfo jobInfo, String csvFileName) throws Exception {
        List<BatchInfo> batchInfos = new ArrayList<BatchInfo>();
        BufferedReader rdr = new BufferedReader(new InputStreamReader(
                new FileInputStream(csvFileName)));

        // read the CSV header row
        String hdr = rdr.readLine();
        byte[] headerBytes = (hdr + "\n").getBytes("UTF-8");
        int headerBytesLength = headerBytes.length;
//      I was making use of the following code which I replaced with the next line of code.
//      File tmpFile = File.createTempFile("bulkAPIInsert", ".csv");
        File tmpFile = new File("bulkAPIInsert.csv");
        // Split the CSV file into multiple batches
        try {
            FileOutputStream tmpOut = new FileOutputStream(tmpFile);
            int maxBytesPerBatch = 10000000; // 10 million bytes per batch
            int maxRowsPerBatch = 10000; // 10 thousand rows per batch
            int currentBytes = 0;
            int currentLines = 0;
            String nextLine;

            while ((nextLine = rdr.readLine()) != null) {
                byte[] bytes = (nextLine + "\n").getBytes("UTF-8"); //TODO
                if (currentBytes + bytes.length > maxBytesPerBatch
                        || currentLines > maxRowsPerBatch) {
                    createBatch(tmpOut, tmpFile, batchInfos, connection, jobInfo);
                    currentBytes = 0;
                    currentLines = 0;
                }
                if (currentBytes == 0) {
                    tmpOut = new FileOutputStream(tmpFile);
                    tmpOut.write(headerBytes);
                    currentBytes = headerBytesLength;
                    currentLines = 1;
                }
                tmpOut.write(bytes);
                currentBytes += bytes.length;
                currentLines++;
            }

            if (currentLines > 1) {
                createBatch(tmpOut, tmpFile, batchInfos, connection, jobInfo);
            }
        } finally {
            if(!tmpFile.delete())
                tmpFile.deleteOnExit();
            rdr.close();
        }
        return batchInfos;
    }

/**
     * Wait for a job to complete by polling the Bulk API.
     */
    Method2: private void awaitCompletion(RestConnection connection, JobInfo job,
            List<BatchInfo> batchInfoList) throws AsyncApiException { 
        try{
            /****
            Some code
            **/
                BatchInfo[] statusList = connection.getBatchInfoList(job.getId())
                .getBatchInfo();
                for (BatchInfo b : statusList) {
                    if (b.getState() == BatchStateEnum.Completed) {
                        if (incomplete.remove(b.getId())) 
                            //Do Something
                    }
                    else if(b.getState() == BatchStateEnum.Failed){ 

                        System.out.println("Reason: "+b.getStateMessage()+".\n  " +
                                "Number of Records Processed: "+b.getNumberRecordsProcessed());
                        throw (new Exception(""));
                    }
                }
            }
        }catch(Exception ex){log.debug(" Exception occurred.");}
    }

BatchInfo 的 getStateMessage() 方法给出了所讨论的错误消息。

【问题讨论】:

  • 我的建议是创建一个简单的示例(使用您的一些数据)来重现问题。如果您要拆分 CSV 文件,请非常小心不要嵌入换行符(多行记录),否则您将遇到麻烦!你可能想试试Super CSV,看看你的数据是否真的有问题。
  • 我尝试从底部删除一些 csv 记录,直到我删除该记录时,使用“numberRecordsProcessed=0”创建了一个批次,它等待说“等待结果-1”和然后什么也没有发生。该记录看起来也没有恶意。它类似于“3745”,“TEST TEST1 12345 TEST TEST TEST,TEST 43215”,“DPPI-3745”,如果我不删除此记录,错误消息仍然会出现“无法解析 CSV。找到未转义的引号。带引号的值应在引号内"

标签: java salesforce apex-code bulkloader opencsv


【解决方案1】:

感谢“猎犬”,帮助我。

回答

已通过删除每个单元格的换行符解决了该问题。

【讨论】:

    猜你喜欢
    • 2017-05-30
    • 2020-10-12
    • 2018-12-22
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    • 2016-08-08
    • 1970-01-01
    • 2020-03-06
    相关资源
    最近更新 更多