【问题标题】:Android CSV parser problemAndroid CSV 解析器问题
【发布时间】:2011-08-29 17:25:16
【问题描述】:

我在解析 CSV 文件时遇到问题。它只有 2 行数据,用逗号分隔。第一行是日期,第二行是值。日期字段将始终包含日期,但有时该值为空白(或 null?)。当它达到空值时,我得到一个 StringIndexOutOfBoundsException 并且应用程序崩溃。我正在记录每个循环并且可以看到数据,但是一旦我达到空值,它就会停止循环并给出错误。如果没有空值,那么它就完美了。这是我的代码:

        BufferedReader buf = new BufferedReader(new StringReader(file));
        String line = null;
        while ((line = buf.readLine()) != null) {
            try {
                String date = null, value = null;
                String[] RowData = line.split(",");
                date = RowData[0];
                value = RowData[1]; (this is the row it crashes on)

这是 CSV 的样子:

2011-08-28 09:16,8.23

2011-08-28 09:15,8.24

2011-08-28 09:14,8.26

2011-08-28 09:13,8.34

2011-08-28 09:12,

2011-08-28 09:11,10.72

2011-08-28 09:10,

2011-08-28 09:09,

09:13 的值是我收到错误之前 logcat 中的最后一件事。

这解决了它:

                if(RowData.length == 2) {
                    date = RowData[0];
                    value = RowData[1];
                } else {
                    date = RowData[0];
                    value = "0";
                }

我在 value 字段中写了一个 0,这样以后的进程就不会被 null 值阻塞。感谢大家的帮助!

【问题讨论】:

    标签: android parsing csv text-parsing


    【解决方案1】:

    你想做这个或类似的事情:

    String date = null, value = null;
    String[] RowData = line.split(",");
    date = RowData[0];
    
    if(RowData.length ==2)value = RowData[1]; (this is the row it crashes on)
    

    或者它的一些变体,例如if(RowData.length

    【讨论】:

    • 我尝试了各种变体,但它仍然崩溃。我试过 if(RowData.length
    • 我必须把 if 语句放在 date = RowData[0];谢谢!
    【解决方案2】:

    既然您可以使用已经编写好的库来为您完成解析,为什么还要编写自己的 CSV 解析?或许OpenCSV 会帮助您实现 CSV 解析目标。

    【讨论】:

    • 因为我不想要一个完整的库,几行代码就可以满足我的需要。我只是不能让它跳过空值。
    • 在编译时使用 ProGuard 去除所有未使用的类。
    • 我使用一个简单的 if 语句修复了它。我只是不确定要检查什么。我正在检查我试图设置的字符串而不是整个 RowData。无论如何感谢您的建议。当我第一次编写代码时,我曾研究过一段时间,但我决定在第一个空字段之后终止循环并将现有数据转储到数据库。我终于回到了它,现在它已经修复了:)
    【解决方案3】:

    在尝试访问之前检查 RowData 的长度。看起来 split() 正在返回一个包含单个对象的数组,但您正在尝试访问第二个对象,这确实超出了范围。

    【讨论】:

    • 我更新了我上面的问题,包括导致崩溃的 CSV 文件部分。该行不为空,但第二个对象有时为空。我尝试了检查 null 和 if 语句的不同变体,但它总是在逗号后面没有任何内容。
    【解决方案4】:
    public class CityParser {
        DocumentBuilderFactory factory;
        DocumentBuilder builder;
        Document doc;
    
        Element ele;
    
        int mediaThumbnailCount;`enter code here`
        boolean urlflag;
        CityListBean objBean = null;
    
        Vector<CityListBean> vecCityList;
    
        public CityParser() {
    
        }
    
        public Vector<CityListBean> getCityData() {
    
            vecCityList = new Vector<CityListBean>();
            try {
                HttpClient httpClient = new DefaultHttpClient();
                HttpContext localContext = new BasicHttpContext();
                HttpGet httpGet = new HttpGet(
                        "http://heresmyparty.com/cms/index.php?option=com_chronocontact&chronoformname=add_event_form_download");
                HttpResponse response = httpClient.execute(httpGet, localContext);
                // String result = "";
    
                BufferedReader reader = new BufferedReader(new InputStreamReader(
                        response.getEntity().getContent()));
    
                CSVReader csvreader = new CSVReader(reader);
                String[] nextLine;
                while ((nextLine = csvreader.readNext()) != null) {
    
                    CityListBean objcitylist = new CityListBean();
                    // nextLine[] is an array of values from the line
                    objcitylist.setText_title(nextLine[5]);
                    objcitylist.setText_host(nextLine[6]);
                    objcitylist.setText_price(nextLine[7]);
                    objcitylist.setDate(nextLine[8]);
                    objcitylist.setText_venue(nextLine[11]);
                    objcitylist.setAddress(nextLine[12]);
                    objcitylist.setLatitude(nextLine[13]);
                    objcitylist.setLongitude(nextLine[14]);
                    objcitylist.setFile(nextLine[15]);
                    objcitylist.setText_description(nextLine[16]);
                    objcitylist.setCity(nextLine[17]);
                    vecCityList.addElement(objcitylist);
    
                }
    
    
                  /*for (int i = 0; i < vecCityList.size(); i++) { CityListBean
                  objcity = (CityListBean) vecCityList.get(i);
    
                  System.out.println("Cf_id : " + objcity.getCityName());
                  System.out.println("-----------------------------------"); }*/
    
    
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
            return vecCityList;
        }
    }
    
    ==========================================================================================
    
    public class CSVReader {
    
        private BufferedReader br;
    
        private boolean hasNext = true;
    
        private char separator;
    
        private char quotechar;
    
        private int skipLines;
    
        private boolean linesSkiped;
    
    
        public static final char DEFAULT_SEPARATOR = ',';
    
        public static final char DEFAULT_QUOTE_CHARACTER = '"';
    
        public static final int DEFAULT_SKIP_LINES = 0;
    
        public CSVReader(Reader reader) {
            this(reader, DEFAULT_SEPARATOR, DEFAULT_QUOTE_CHARACTER,
                DEFAULT_SKIP_LINES);
        }
    
        public CSVReader(Reader reader, char separator, char quotechar, int line) {
            this.br = new BufferedReader(reader);
            this.separator = separator;
            this.quotechar = quotechar;
            this.skipLines = line;
        }
    
        public String[] readNext() throws IOException {
    
            String nextLine = getNextLine();
            return hasNext ? parseLine(nextLine) : null;
        }
    
        private String getNextLine() throws IOException {
            if (!this.linesSkiped) {
                for (int i = 0; i < skipLines; i++) {
                    br.readLine();
                }
                this.linesSkiped = true;
            }
            String nextLine = br.readLine();
            if (nextLine == null) {
                hasNext = false;
            }
            return hasNext ? nextLine : null;
        }
    
        private String[] parseLine(String nextLine) throws IOException {
    
            if (nextLine == null) {
                return null;
            }
    
            List<String> tokensOnThisLine = new ArrayList<String>();
            StringBuffer sb = new StringBuffer();
            boolean inQuotes = false;
            do {
                    if (inQuotes) {
                    // continuing a quoted section, reappend newline
                    sb.append("\n");
                    nextLine = getNextLine();
                    if (nextLine == null)
                        break;
                }
                for (int i = 0; i < nextLine.length(); i++) {
    
                    char c = nextLine.charAt(i);
                    if (c == quotechar) {
                            // this gets complex... the quote may end a quoted block, or escape another quote.
                            // do a 1-char lookahead:
                            if( inQuotes  // we are in quotes, therefore there can be escaped quotes in here.
                                && nextLine.length() > (i+1)  // there is indeed another character to check.
                                && nextLine.charAt(i+1) == quotechar ){ // ..and that char. is a quote also.
                                    // we have two quote chars in a row == one quote char, so consume them both and
                                    // put one on the token. we do *not* exit the quoted text.
                                    sb.append(nextLine.charAt(i+1));
                                    i++;
                            }else{
                                    inQuotes = !inQuotes;
                                    // the tricky case of an embedded quote in the middle: a,bc"d"ef,g
                                    if(i>2 //not on the begining of the line
                                                    && nextLine.charAt(i-1) != this.separator //not at the begining of an escape sequence
                                                    && nextLine.length()>(i+1) &&
                                                    nextLine.charAt(i+1) != this.separator //not at the     end of an escape sequence
                                    ){
                                            sb.append(c);
                                    }
                            }
                    } else if (c == separator && !inQuotes) {
                        tokensOnThisLine.add(sb.toString());
                        sb = new StringBuffer(); // start work on next token
                    } else {
                        sb.append(c);
                    }
                }
            } while (inQuotes);
            tokensOnThisLine.add(sb.toString());
            return (String[]) tokensOnThisLine.toArray(new String[0]);
    
        }
    
        public void close() throws IOException{
            br.close();
        }
    
    }
    

    【讨论】:

    • 谢谢,这对我帮助很大!
    【解决方案5】:

    你有没有试过先检查

    if (RowData[1]!=null) or possibly if (RowData[1]!="") 
    

    我不明白为什么这会导致您的应用崩溃, 它应该将值设置为 null""

    【讨论】:

    • 谢谢,我已经修复了它,但它崩溃了,因为导致它实际崩溃的应用程序部分不接受空字符串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多