簡體   English   中英

讀取CSV文件並寫入另一個CSV-ArrayIndexOutOfBoundsException和模式困難

[英]Read CSV file and write to another CSV - ArrayIndexOutOfBoundsException and pattern difficuties

我正在創建一個Java程序,該程序從一個csv文件中讀取數據,並且幾乎不更改地保存到另一個csv文件中:

a)在輸出文件的第三欄中,我只能從輸入文件的第四欄中提取特定格式的價格(例如4.99、2522.78)

b)在otput文件的第4列中,我必須從輸入文件的第5列中提取格式為DD.MM.YYYY的日期。

c)最后三行的輸入文件沒有最后一列。 當我讀取行並想要讀取第一行而沒有最后一列時,它會引發異常。

還有很多,但這些都是要克服的困難。 你可以幫幫我嗎? 我有模式,但我只是不知道如何在像我這樣的表中使用它。

碼:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RwCSV {

private static final String SOURCE_FILE = "/home/krystian/Pulpit/products.csv";
private static final String RESULT_FILE = "/home/krystian/Pulpit/result3.csv";
private static final String DELIMITER1 = ";";
private static final String DELIMITER2 = "|";
//Pattern pattern;

public static void main(String[] args) {
    try (
            BufferedReader br = new BufferedReader(new FileReader(SOURCE_FILE));
            FileWriter fw = new FileWriter(RESULT_FILE)) {


        String line;
        while ((line = br.readLine()) != null) {
            String[] values = line.split(DELIMITER1);
            String[] result = new String[5];

            Pattern p = Pattern.compile("\\d+.\\d\\d");
            Matcher m = p.matcher(values[3]);
            //System.out.println(values[4]);
            result[0] = "'"+values[0]+"'";
            result[1] = "'"+values[1]+"?id="+values[2]+"'";
            result[2] = "'"+values[3]+"'";
            result[3] = "'"+values[3]+"'";
            result[4] = "'"+values[4]+"'"; //throws exception java.lang.ArrayIndexOutOfBoundsException

            for (int i = 0; i < result.length; i++) {
                fw.write(result[i].replace("\"", ""));

                if (i != result.length - 1) {
                    fw.write(DELIMITER2);
                }

                if (values.length<5) {continue;}
            }
            fw.write("\n");
        }
    } catch (FileNotFoundException ex) {
        System.out.println("File not found.");
    } catch (IOException ex) {
        ex.printStackTrace(System.out);
    }
    catch (NullPointerException ex) {

    }
}
}

輸入文件:

"Product Name";"Link";"SKU";"Selling-Price";"description"
"Product #1";"http://mapofmetal.com";"AT-23";"USD 1,232.99";"This field contains no date!"
"Product #2";"http://mapofmetal.com";"BU-322";"USD 8654.56";"Here a date: 20.09.2014"
"Product #3";"http://mapofmetal.com";"FFZWE";"EUR 1255,59";"Another date: 31.4.1999"
"Product #4";"http://mapofmetal.com";234234;"345,99 €";"Again no date in this field."
"Product #5";"http://mapofmetal.com";"UDMD-4";"$34.00";"Here are some special characters: öäüß"
"Product #6";"http://mapofmetal.com";"33-AAU43";"431.333,0 EUR";"American date: 12-23-2003"
"Product #7";"http://mapofmetal.com";"33-AAU44";"431.333,0 EUR";"One more date: 1.10.2014"
"Product #8";"http://mapofmetal.com";"33-AAU45";"34,99";
"Product #9";"http://mapofmetal.com";"UZ733-2";234.99;
"Product #10";"http://mapofmetal.com";"42-H2G2";42;

輸出文件行模式(必須更改分隔符和引號字符):

'Product #2'|'http://mapofmetal.com?id=BU-322'|'8654.56'|'20.09.2014'

關於ArrayIndexOutOfBounds

您的問題似乎是當輸入以;結尾時; ,則第5個元素將被丟棄。 例如:

"abc;def;".split(";")  ->  ["abc", "def"]

而不是您想要的, ["abc", "def", ""]

為此,請將您期望的數字元素作為第二個參數傳遞給.split() ,例如:

"abc;def;".split(";", 3)  ->  ["abc", "def", ""]

或負值:

"abc;def;".split(";", -1)  ->  ["abc", "def", ""]

docs中對此進行了解釋。

關於提取價格

提取價格非常棘手,因為您有多種格式:

  • 1,232.99美元
  • 歐元1255,59
  • 345,99€
  • $ 34.00
  • 34,99

最大的問題是逗號,有時它應該被忽略,有時是小數點。 這可以與您給出的示例一起使用,但可能並不詳盡,並且您可能需要根據其他可能的輸入進行改進:

String price;
if (values[3].startsWith("EUR ") || values[3].endsWith(" €")) {
    // ignore non-digits and non-commas, and replace commas with dots
    price = values[3].replaceAll("[^\\d,]", "").replaceAll(",", ".");
} else {
    // ignore non-digits and non-dots
    price = values[3].replaceAll("[^\\d.]", "");
}

然后是這種格式,我不確定該怎么做:

431.333,0 EUR

我認為您需要更好的輸入格式規范。 處理這種不一致的輸入會不必要地困難且容易出錯。

根據您要使用此代碼的時間長短,可以選擇快速還是更可靠的選擇。

一種簡單的方法是添加嘗試並四處查找以檢查值[4]中的結果,然后在文件中不存在默認值時在該catch中插入默認值。

您的產品文件只有4列,以“產品#8”開頭。 因此,您嘗試訪問values [4],並且該數組索引不存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM