Java 查找并替换MS Access表行中不工作的文本

Java 查找并替换MS Access表行中不工作的文本,java,javafx,task,jackcess,Java,Javafx,Task,Jackcess,给定一个目录,我的应用程序使用jackcessapi遍历并加载.mdbmsaccessdbs。在每个数据库中,都有一个名为GCMT\u CMT\u PROPERTIES的表,其中有一个名为CMT\u data的列,其中包含一些文本。我还有一个Mapper对象(它本质上类似于Map,但允许重复键),当从字符串中替换某个单词时,我将其用作字典 因此,例如,如果mapper包含fox->dog,那么句子:“fox jumps”变成“dog jumps” 我将为这个项目设计如下: 1. Given a

给定一个目录,我的应用程序使用jackcessapi遍历并加载
.mdb
msaccessdbs。在每个数据库中,都有一个名为
GCMT\u CMT\u PROPERTIES
的表,其中有一个名为
CMT\u data
的列,其中包含一些文本。我还有一个
Mapper
对象(它本质上类似于
Map
,但允许重复键),当从字符串中替换某个单词时,我将其用作字典

因此,例如,如果
mapper
包含
fox->dog
,那么句子:
“fox jumps”
变成
“dog jumps”

我将为这个项目设计如下:

1. Given a directory, traverse all subdirectories and load all .mdb files into a File[].
2. For each db file in File[], create a Task<Void> called "TaskMdbUpdater" and pass it the db file. 
3. Dispatch and run each task as it is created (see 2. above).
更新1: 为了验证我的自定义
StringUtils.findAndReplace
逻辑,我执行了以下单元测试(在JUnit中),该测试正在通过:

@Test
    public void simpleReplacementTest() {
        // Construct a test mapper/dictionary
        List<aMap> aMaps = new ArrayList<aMap>();
        aMaps.add(new aMap(new String[] {"fox", "dog"})); // {K, V} = K -> V
        Mapper mapper = new Mapper(aMaps);

        // Perform replacement
        String corpus = "The fox jumps";
        String updatedCorpus = StringUtils.findAndReplace(corpus, mapper);
        assertEquals("The dog jumps", updatedCorpus);
    }
这是我日志中的一个小练习。正如你所看到的,在打开桌子之后,它似乎没有做任何事情,这让我有点困惑:

INFO (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Located the following directories under specified MOIS parent which contains an .mdb file:
[01_Parent_All_Safe_Test[ RV_DMS_0041RV_DMS_0001RV_DMS_0003RV_DMS_0005RV_DMS_0007RV_DMS_0012RV_DMS_0013RV_DMS_0014RV_DMS_0016RV_DMS_0017RV_DMS_0018RV_DMS_0020RV_DMS_0023RV_DMS_0025RV_DMS_0028RV_DMS_0029RV_DMS_0031RV_DMS_0033RV_DMS_0034RV_DMS_0035RV_DMS_0036RV_DMS_0038RV_DMS_0039RV_DMS_0040 ]]
...
DEBUG (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Created new task: NAMEMAP.logic.TaskMdbUpdater@4cfe46fe
DEBUG (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Created new worker: Thread[Thread-22,5,main]
DEBUG (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Set worker Thread[Thread-22,5,main] as daemon
DEBUG (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Dispatching worker: Thread[Thread-22,5,main]
...
DEBUG (16-02-2017 17:28:00) [Thread-22] NAMEMAP.logic.TaskMdbUpdater.call(): Opened database: RV_DMS_0023.mdb
DEBUG (16-02-2017 17:28:00) [Thread-22] NAMEMAP.logic.TaskMdbUpdater.call(): Opening table: GCMT_CMT_PROPERTIES
在这一点之后,日志中不再有任何条目,处理器在100%负载时出现峰值,直到我强制终止应用程序为止。这可能意味着程序会陷入无限while循环中-但是如果是这样,那么文件中不应该有日志条目吗

更新2


好的,通过将log
TRACE
打印到
stdio
中,我进一步缩小了问题的范围。我的
performFindAndReplaceOnString
似乎效率非常低,而且它永远不会超过这些dbs的第一行,因为它只是在磨磨长字符串。关于如何有效地为这个用例执行字符串替换,有什么建议吗

您是否确保在退出应用程序之前正确地
.close()
数据库对象?我相信是这样的。如果我可以提请您注意类的
调用
方法
任务的bupdater
,您可以看到我正在关闭在该方法开始时打开的
数据库
对象<代码>。。。catch(NoSuchElementException e){e.printStackTrace();}db.close();}catch(异常e){e.printStackTrace();}返回null您是否确认findAndReplace逻辑实际上正确修改了字符串?是的,我的单元测试通过了,请参阅上面的更新1^“关于如何有效地执行此用例的字符串替换的任何建议?”-一些想法。您是否确保
.close()
在您的应用程序退出之前,数据库对象是否正确运行?我相信是这样。如果我可以提请您注意类的
调用
方法
任务的bupdater
,您可以看到我正在关闭在该方法开始时打开的
数据库
对象<代码>。。。catch(NoSuchElementException e){e.printStackTrace();}db.close();}catch(异常e){e.printStackTrace();}返回null您是否确认findAndReplace逻辑实际上正确地修改了字符串?是的,我的单元测试通过了,请参阅上面的更新1^“关于如何有效地执行此用例的字符串替换的任何建议?”-一些想法。
/**
 * Updates a given .mdb database according to specifications defined internally.
 * @since 2.2
 */
public class TaskMdbUpdater extends Task<Void> {

    private final String TABLE_NAME = "GCMT_CMT_PROPERTIES";
    private final String COLUMN_NAME = "cmt_data";

    private DatabaseBuilder dbPackage;
    private Mapper mapper;

    public TaskMdbUpdater(DatabaseBuilder dbPack, Mapper mapper) {
        super();
        this.dbPackage = dbPack;
        this.mapper = mapper;
    }

    @Override
    protected Void call() {
        try {
//      Controller.dprint("TaskMdbUpdater", "Worker: " + Thread.currentThread().getName() + " running");

        // Open db and extract Table
        Database db = this.dbPackage
                .open();
        Logger.debug("Opened database: {}", db.getFile().getName());

        Table table = db.getTable(TABLE_NAME);
        Logger.debug("Opening table: {}", table.getName());

        Iterator<Row> tableRows = table.iterator();

//      Controller.dprint("TaskMdbUpdater", "Updating database: " + db.getFile().getName());

        int i=0;
        try {
            while( tableRows.hasNext() ) {

                // Row is basically a<code> Map<Column_Name, Value> </code>
                Row cRow = tableRows.next();
                Logger.trace("Current row: {}", cRow);

//              Controller.dprint(Thread.currentThread().getName(), "Database name: " + db.getFile().getName());
//              Controller.dprint("TaskMdbUpdater", "existing row: " + cRow.toString());
                String str = cRow.getString(COLUMN_NAME);
                Logger.trace("Row {} column field contents (before find/replace): {}", i, str);

                String newStr = performFindAndReplaceOnString(str);
                Logger.trace("Row {} column field contents (after find/replace): {}", i, newStr);

                cRow.put(COLUMN_NAME, newStr);
                Logger.debug("Updating field in row {}", i);

                Row newRow = table.updateRow(cRow); // <code>updateRow</code> returns the new, updated row. Ignoring this.
                Logger.debug("Calling updateRow on table with modified row");

//              Controller.dprint("TaskMdbUpdater", "new row: " + newRow.toString());
                i++;
                Logger.trace("i = {}", i);
            }
        } catch(NoSuchElementException e) {
//          e.printStackTrace();
            Logger.error("Thread has iterated past number of rows in table", e);
        }
        Logger.info("Iterated through {} rows in table {}", i, table.getName());

        db.close();
        Logger.debug("Closing database: {}", db.getFile().getName());

        } catch (Exception e) {
//          e.printStackTrace();
            Logger.error("An error occurred while attempting to update row value", e);
        }
        return null;
    }

    /**
     * @see javafx.concurrent.Task#failed()
     */
    @Override
    protected void failed() {
        super.failed();
        Logger.error("Task failed");
    }

    @Override
    protected void succeeded() {
        Logger.debug("Task succeeded");
    }

    private String performFindAndReplaceOnString(String str) {
//      Logger.trace("OLD: [" + str + "]");

        String updatedStr = null;
        for(int i=0; i<mapper.getMappings().size(); i++) {
            // loop through all parameter names in mapper to search for in str.
            updatedStr = findAndReplace(str, this.mapper);
        }
//      Logger.trace("NEW: [" + updatedStr + "]");
        return updatedStr;
    }
}
INFO (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Located the following directories under specified MOIS parent which contains an .mdb file:
[01_Parent_All_Safe_Test[ RV_DMS_0041RV_DMS_0001RV_DMS_0003RV_DMS_0005RV_DMS_0007RV_DMS_0012RV_DMS_0013RV_DMS_0014RV_DMS_0016RV_DMS_0017RV_DMS_0018RV_DMS_0020RV_DMS_0023RV_DMS_0025RV_DMS_0028RV_DMS_0029RV_DMS_0031RV_DMS_0033RV_DMS_0034RV_DMS_0035RV_DMS_0036RV_DMS_0038RV_DMS_0039RV_DMS_0040 ]]
...
DEBUG (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Created new task: NAMEMAP.logic.TaskMdbUpdater@4cfe46fe
DEBUG (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Created new worker: Thread[Thread-22,5,main]
DEBUG (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Set worker Thread[Thread-22,5,main] as daemon
DEBUG (16-02-2017 17:27:59) [Thread-9] NAMEMAP.logic.TaskDatabaseTaskDispatcher.call(): Dispatching worker: Thread[Thread-22,5,main]
...
DEBUG (16-02-2017 17:28:00) [Thread-22] NAMEMAP.logic.TaskMdbUpdater.call(): Opened database: RV_DMS_0023.mdb
DEBUG (16-02-2017 17:28:00) [Thread-22] NAMEMAP.logic.TaskMdbUpdater.call(): Opening table: GCMT_CMT_PROPERTIES