Использование Jackcess для получения числовых значений, хранящихся в текстовом поле, дает ClassCastException

Я работаю с Джекесс, чтобы читать и классифицировать базу данных доступа. Он просто предназначен для открытия базы данных, циклического прохождения каждой строки и вывода на консоль отдельных строк данных, которые удовлетворяют определенным условиям. Это работает нормально, за исключением случаев, когда я пытаюсь прочитать числовые значения. Мой код ниже. (Этот код встроен в графический интерфейс Swing и выполняется при нажатии кнопки j.)

if (inv == null) {                  // Check to see if inventory file has been set.  If not, then set it to the default reference path.
        inv = rPath;                        
}

if (inventoryFile.exists()) {                   // Check to see if the reference path exists.
        List<String> testTypes = jList1.getSelectedValuesList();
        List<String> evalTypes = jList3.getSelectedValuesList();
        List<String> grainTypes = jList2.getSelectedValuesList();

        StringBuilder sb = new StringBuilder();
        for (int i=0; i<=evalTypes.size()-1; i++) {
            if (i<evalTypes.size()-1) {
                sb.append(evalTypes.get(i)).append(" ");
            }
            else {
                sb.append(evalTypes.get(i));
            }
        }
        String evalType = sb.toString();

        try (Database db = DatabaseBuilder.open(new File(inv));) {

            Table sampleList = db.getTable("NTEP SAMPLES LIST");
            Cursor cursor = CursorBuilder.createCursor(sampleList);

            for (int i=0; i<=testTypes.size()-1; i++) {
                if ("Sample Volume".equals(testTypes.get(i))) {
                    if (grainTypes.size() == 1 && "HRW".equals(grainTypes.get(0))) {
                        switch (evalType) {
                            case "GMM":
                                for (Row row : sampleList){                                        
                                    if (null != row.getString("CURRENTGAC")) {}
                                    if ("HRW".equals(row.get("GRAIN")) && row.getDouble("CURRENTGAC")>=12.00) {
                                        System.out.print(row.get("GRAIN") + "\t");
                                        System.out.println(row.get("CURRENTGAC"));
                                    }
                                }                                    
                                break;
                            case "NIRT":
                                // some conditional code
                                break;
                            case "TW":
                                // some more code
                                break;
                         }
                    }
                    else {
                        JOptionPane.showMessageDialog(null, "Only HRW samples can be used for the selected test(s).", "Error", JOptionPane.ERROR_MESSAGE);
                    }                        
                    break;
                }

            }
        }
        catch (IOException ex) {
            Logger.getLogger(SampleFilterGUI.class.getName()).log(Level.SEVERE, null, ex);
        }

Когда код запускается, я получаю следующую ошибку:

java.lang.ClassCastException: java.lang.String не может быть приведен к java.lang.Double

Следующее условие выглядит как вызывающее ошибку.

row.getDouble ("CURRENTGAC")> = 12.00

Похоже, что когда данные считываются из базы данных, программа читает все в виде строки, даже если некоторые поля являются числовыми. Я пытался сделать это поле двойным, но java, похоже, не нравится. Я попытался использовать команды Double.parseDouble() и Double.valueOf(), чтобы попытаться преобразовать значение (как упомянуто здесь), но безуспешно.

У меня вопрос, как я могу преобразовать эти поля в числовые значения? Пытается набрать бросок, или есть другой метод, о котором я не знаю? В коде вы также заметите, что я создал курсор, но я им не пользуюсь. Первоначальный план состоял в том, чтобы использовать его для навигации по базе данных, но я нашел пример кода на веб-странице jackcess и решил использовать его вместо этого. Не уверен, что это был правильный ход или нет, но это казалось более простым решением. Буду признателен за любую оказанную помощь. Благодарю.

РЕДАКТИРОВАТЬ:

Чтобы программа считывала строковое значение из моей базы данных, я ввел следующий код

row.get("CURRENTGAC"). GetClass(). GetName()

Вывод был java.lang.String, так что это подтверждает, что это строка. Как и было предложено, я изменил следующий код

case "GMM":
    for (Row row : sampleList){
        if (null != row.get("CURRENTGAC")) 
        //System.out.println(row.get("CURRENTGAC").getClass().getName());
        System.out.println(String.format("|%s|", row.getString("CURRENTGAC")));

        /*if ("HRW".equals(row.get("GRAIN")) && row.getDouble("CURRENTGAC")>=12.00 && row.getDouble("CURRENTGAC")<=14.00) {
             System.out.print(row.get("GRAIN") + "\t");
             System.out.println(row.get("CURRENTGAC"));
        }*/                                        
    }                                    
    break;

Выход на консоль от этих изменений ниже

|9,85| |11,76| |9,57| |12,98| |10,43| |13,08| |10,53| |11,46| ...

Этот вывод, хотя выглядит числовым, все еще имеет строковый тип. Поэтому, когда я пытался запустить его с моим условным оператором (который закомментирован в обновленном образце кода), я все равно получаю ту же ошибку java.lang.ClassCastException, которую я получал раньше.

1 ответ

Решение

Джексесс не возвращает все значения в виде строк. Он извлечет поля (столбцы) таблицы как соответствующий тип Java для этого типа поля доступа. Например, с тестовой таблицей с именем "Table1"...

ID  DoubleField  TextField
--  -----------  ---------
 1         1.23  4.56     

... следующий код Java...

Table t = db.getTable("Table1");
for (Row r : t) {
    Object o;
    Double d;
    String fieldName;

    fieldName = "DoubleField";
    o = r.get(fieldName);
    System.out.println(String.format(
            "%s comes back as: %s", 
            fieldName, 
            o.getClass().getName()));
    System.out.println(String.format(
            "Value: %f", 
            o));
    System.out.println();

    fieldName = "TextField";
    o = r.get(fieldName);
    System.out.println(String.format(
            "%s comes back as: %s", 
            fieldName, 
            o.getClass().getName()));
    System.out.println(String.format(
            "Value: %s", 
            o));
    try {
        d = r.getDouble(fieldName);
    } catch (Exception x) {
        System.out.println(String.format(
                "r.getDouble(\"%s\") failed - %s: %s", 
                fieldName, 
                x.getClass().getName(),
                x.getMessage()));
    }
    try {
        d = Double.parseDouble(r.getString(fieldName));
        System.out.println(String.format(
                "Double.parseDouble(r.getString(\"%s\")) succeeded. Value: %f", 
                fieldName, 
                d));
    } catch (Exception x) {
        System.out.println(String.format(
                "Double.parseDouble(r.getString(\"%s\")) failed: %s", 
                fieldName,
                x.getClass().getName()));
    }
    System.out.println();
} 

... производит:

DoubleField comes back as: java.lang.Double
Value: 1.230000

TextField comes back as: java.lang.String
Value: 4.56
r.getDouble("TextField") failed - java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
Double.parseDouble(r.getString("TextField")) succeeded. Value: 4.560000

Если вы не можете получить Double.parseDouble() проанализировать строковые значения из вашей базы данных, то либо

  • они содержат "забавные персонажи", которые не видны из размещенных вами образцов, или
  • ты делаешь это неправильно.

Дополнительная информация: ваш пример файла

Jackcess возвращает CURRENTGAC как String, потому что это текстовое поле в таблице:

TableDesign.png

Следующий код Java...

Table t = db.getTable("NTEP SAMPLES LIST");
int countNotNull = 0;
int countAtLeast12 = 0;
for (Row r : t) {
    String s = r.getString("CURRENTGAC");
    if (s != null) {
        countNotNull++;
        Double d = Double.parseDouble(s);
        if (d >= 12.00) {
            countAtLeast12++;
        }
    }
}
System.out.println(String.format(
        "Scan complete. Found %d non-null CURRENTGAC values, %d of which were >= 12.00.", 
        countNotNull, 
        countAtLeast12));

... производит...

Scan complete. Found 100 non-null CURRENTGAC values, 62 of which were >= 12.00.
Другие вопросы по тегам