Использование 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, потому что это текстовое поле в таблице:
Следующий код 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.