1

I am working with Jackcess to read and categorize an access database. It's simply meant to open the database, loop through each line, and print out individual row data to the console which meet certain conditions. It works fine, except for when I try to read numeric values. My code is below. (This code is built into a Swing GUI and gets executed when a jbutton is pressed.)

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);
        }

When the code is run I get the following error:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double

The following condition looks to be what is throwing the error.

row.getDouble("CURRENTGAC")>=12.00

It appears that when the data is read from the database, the program is reading everything as a string, even though some fields are numeric. I was attempting to cast this field as a double, but java doesn't seem to like that. I have tried using the Double.parseDouble() and Double.valueOf() commands to try converting the value (as mentioned here) but without success.

My question is, how can I convert these fields to numeric values? Is trying to type cast the way to go, or is there a different method I'm not aware of? You will also notice in the code that I created a cursor, but am not using it. The original plan was to use it for navigating through the database, but I found some example code from the jackcess webpage and decided to use that instead. Not sure if that was the right move or not, but it seemed like a simpler solution. Any help is much appreciated. Thanks.

EDIT:

To ensure the program was reading a string value from my database, I input the following code

row.get("CURRENTGAC").getClass().getName()

The output was java.lang.String, so this confirms that it is a string. As was suggested, I changed the following code

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;

The ouput to the console from these changes is below

|9.85| |11.76| |9.57| |12.98| |10.43| |13.08| |10.53| |11.46| ...

This output, although looks numeric, is still of the string type. So when I tried to run it with my conditional statement (which is commented out in the updated sample code) I still get the same java.lang.ClassCastException error that I was getting before.

Community
  • 1
  • 1
Rucker06
  • 13
  • 4
  • You can easily see if Jackcess really is returning a string by printing `row.get("CURRENTGAC").getClass().getName()` and seeing if it says `java.lang.String`. If that is the case, then have your application print `String.format("|%s|", row.getString("CURRENTGAC"))` and [edit] your question to show us what it looks like. – Gord Thompson May 15 '15 at 16:27
  • Apologies for the delay. My computer was having some security issues that were beyond the scope of this program, but are now fixed. My edits are now posted. Thanks for your assistance. – Rucker06 May 18 '15 at 18:36

1 Answers1

0

Jackcess does not return all values as strings. It will retrieve the fields (columns) of a table as the appropriate Java type for that Access field type. For example, with a test table named "Table1" ...

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

... the following Java code ...

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();
} 

... produces:

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

If you are unable to get Double.parseDouble() to parse the string values from your database then either

  • they contain "funny characters" that are not apparent from the samples you posted, or
  • you're doing it wrong.

Additional information re: your sample file

Jackcess is returning CURRENTGAC as String because it is a Text field in the table:

TableDesign.png

The following Java code ...

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));

... produces ...

Scan complete. Found 100 non-null CURRENTGAC values, 62 of which were >= 12.00.
Gord Thompson
  • 116,920
  • 32
  • 215
  • 418
  • Here is a [sample](http://wikisend.com/download/544616/myDatabase.accdb) of the database I am working with. I believe I was coding similarly to your example, but I could still very well could be doing it wrong. That's pretty much the point for posting it to this forum. If you can find any additional "funny characters", please let me know how you found those also. – Rucker06 May 19 '15 at 22:16
  • @Rucker06 The CURRENTGAC string values are perfectly fine and parse correctly. I have update my answer. – Gord Thompson May 20 '15 at 09:33