2

私はここ数日、この問題に頭を悩ませてきました。私はグーグルの全力を尽くしました、そして私は私の問題を解読することができる私より経験豊富な(ハハを見つけるのは難しいことではありません)誰かをここで見つけることができることを望んでいます。

シナリオ:SwingGUIを実装するJavaアプレットを開発しました。背景作業:アプレットは、大きな「電話帳」Excelファイル(.csv)からレコードを収集し、それらをマップデータ構造に格納します。電話帳には約106,000のレコードが含まれており、34,586番目のレコードで、意味をなさないArrayIndexOutOfBoundsExceptionが発生します。例外は、個人のWebサイトでアプレットを実行している場合にのみ発生します。IDE(NetBeans)でテストし、ローカルマシンで.htmlファイル(アプレットを含むファイル)を実行している間、アプレットはエラーなしで完全に正常に実行されます。私のウェブサイトで実行中にスローされる出力と例外は次のとおりです(スペースを節約するためにほとんどのレコードを切り取りました)。

Javaコンソール

Kary,Webber,2826 East 12th Ave.,Memphis,TN,38168,901-749-1834
Erinn,Rocha,2132 East Main Ave.,Memphis,TN,38168,865-414-5105
Gina,Lane,71 South First St. Apt. 11,Memphis,TN,38168,731-485-1129
Patsy,Hart,661 East 11th St.
java.lang.ArrayIndexOutOfBoundsException: 3
at Implementation.PersonnelDatabase.addRecordFromFields(PersonnelDatabase.java:192)
at Implementation.PersonnelDatabase.initDBFromFile(PersonnelDatabase.java:215)
at Implementation.PersonnelDatabase.processData(PersonnelDatabase.java:239)
at Implementation.PersonnelDatabaseApplet$2.doInBackground(PersonnelDatabaseApplet.java:78)
at Implementation.PersonnelDatabaseApplet$2.doInBackground(PersonnelDatabaseApplet.java:69)
at javax.swing.SwingWorker$1.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at javax.swing.SwingWorker.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

ご覧のとおり、34,586番目のレコード(Patsy、Hartで始まる)では、アドレスの途中で出力されます。完全な記録は次のとおりです:Patsy、Hart、661 East 11thSt.Apt。195、テネシー州メンフィス、38168,555-555-5555。

以下は、例外によって最も論理的に影響を受けるコードのセクションです。

HTMLファイルのオブジェクトタグ

<object type="application/x-java-applet" height="400" width="300">
  <param name="codebase" value="classes" />
  <param name="code" value="Implementation/PersonnelDatabaseApplet.class" />
  <param name="archive" value="PersonnelDatabase.jar" />
  Applet failed to run. No Java plug-in was found.
</object>

PersonnelDatabaseクラス(バックグラウンドデータを処理します):

/*
 * Create a new record using an appropriately ordered set of fields and add it to the data base
 */
public void addRecordFromFields(String[] fields)
{
    // Read record attributes in, one at a time
    Record thisRecord = new Record();
    thisRecord.setFirstName(fields[0]);
    thisRecord.setLastName(fields[1]);
    thisRecord.setAddress(fields[2]);
    thisRecord.setCity(fields[3]);
    thisRecord.setState(fields[4]);
    thisRecord.setZipCode(fields[5]);
    thisRecord.setPhoneNo(fields[6]);
    addRecord(thisRecord);
}

// O( n )
/**
 * Destroy the current data base and load new data from a file.
 * @param filename the file to use as a source
 * @throws IOException: Either file not found or IO error
 */
public void initDBFromFile(URL url) throws IOException
{
    // Open and read the file
    InputStream in = url.openStream();
    BufferedReader filein = new BufferedReader(new InputStreamReader(in));
    // Read record file, parse lines, and add records to data base
    String line = filein.readLine();
    while(line != null) {
        System.err.println(line);
        String[] fields = line.split(",");
        addRecordFromFields(fields);
        line = filein.readLine();
    }
    filein.close();
}

/**
 * Loads the default library and provides for interaction with the data
 * via the JPanel GUI inputs.
 * @param args
 * @throws IOException 
 */
public String processData(String input, int selection, URL url)
{
    //Create the main library object
    PersonnelDatabase dbiLib = new PersonnelDatabase();
    System.err.println(url);
    // Try to read the default library
    try
    {
        dbiLib.initDBFromFile(url);
    }
    catch (IOException e)
    {
        System.err.println("File IO Error");
        e.printStackTrace();
        System.exit(1);
    }
    // Queries can be simulated by typing into the console in Eclipse, and using Ctrl-d (Ctrl-z in Windows) when finished.
    // For example: "searchLastName,Smith" would print a list of all people with the last name of Smith.
    Iterable<Record> result = null;
    String[] fields = new String[2];
    if (input.contains(",")) {
        fields = input.split(",");
    }

    switch(selection) {
        case 0: result = dbiLib.searchByFirstName(input); break;
        case 1: result = dbiLib.searchByLastName(input); break;
        case 2: result = dbiLib.searchByFullName(fields[0].trim(), fields[1].trim()); break;
        case 3: result = dbiLib.searchByCity(input); break;
        case 4: result = dbiLib.searchByState(input); break;
        case 5: result = dbiLib.searchByCityState(fields[0].trim(), fields[1].trim()); break;
        case 6: result = dbiLib.searchByZip(input); break;
        case 7: result = dbiLib.searchByPhoneNumber(input); break;
        case 8: String[] newFields = new String[fields.length-1];
                System.arraycopy(fields, 1, newFields, 0, fields.length-1);
                dbiLib.addRecordFromFields(newFields);
                return "Record added successfully!\nEnter a query or add another record.";
        default: return "Invalid query.\nEnter another query or add a record.";
    }

PersonnelDatabaseAppletクラス(GUIを初期化し、入力を収集し、出力を表示します):

public void init() {
    /* Create and display the applet */
    try {
        java.awt.EventQueue.invokeAndWait(new Runnable() {

            @Override
            public void run() {
                initComponents();
            }
        });
    } catch (Exception e) {
        System.err.println("Creation of GUI did not successfully complete.");
    }
}

// Process inputs in the background.
SwingWorker worker = new SwingWorker<String, Void>() {
    @Override
    public String doInBackground() {
        URL url = null;
        try {
            url = new URL(getCodeBase(), fileToRead);
        }
        catch(MalformedURLException e){}
        personnelDatabase = new PersonnelDatabase();
        final String output = personnelDatabase.processData(input, selection, url);
        return output;
    }

    @Override
    public void done() {
        processingLabel.setVisible(true);
        try {
            textToDisplay = get(15, TimeUnit.SECONDS);
        } catch (InterruptedException ignore) {
            ignore.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            String why = null;
            Throwable cause = e.getCause();
            if(cause != null) {
                why = cause.getMessage();
                cause.printStackTrace();
            } else {
                why = e.getMessage();
                e.printStackTrace();
            }
            System.err.println("Error retrieving request: " + why);
            }
        if(worker.isDone() && textToDisplay != null) {
            processingLabel.setVisible(false);
            outputTextArea.setText(textToDisplay);
        }
    }
};

private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
selection = searchComboBox.getSelectedIndex();
input = valueTextField.getText();
processingLabel.setVisible(true);

worker.execute();

}

私の個人ウェブサイト上のアプレットへのリンク: http ://www.ryan-taylor.me/Applied%20Maps/build/PersonnelDatabaseApplet.html

このプログラムはNetBeansで正常に実行され、ローカルマシンでhtmlを実行すると、エラーはExcelデータ自体とは関係がないと確信しています。Swing(スレッド)と関係があると思いますが、よくわかりません。SwingWorkerを使用してSwingスレッド間でデータを転送できるように変更を加えましたが、うまくいきませんでした。私はそれを実装するときに私が何かを逃した可能性が常にあると思います。

jarに署名することも考えましたが、処理しているファイルはローカルマシンではなくオンラインで保存されているため、実際の必要性はわかりませんでした。

誰か提案があれば、私はそれを大いに感謝します!

4

3 に答える 3

3

3入力行には3つのフィールドしか含まれておらず、実際に存在することを確認せずに4番目のフィールド(インデックス3)にアクセスしようとしているため、範囲外の配列インデックスはです。エラーは

thisRecord.setCity(fields[3]);

配列fieldsには3つの要素しかないためです。で

    String[] fields = line.split(",");
    addRecordFromFields(fields);

あなたがに着くとき

Patsy,Hart,661 East 11th St.

配列fieldsは3つのエントリのみで作成されます。

フィールド数が一定であると予想される場合は、適切なフィールド数を持たない入力行を拒否する必要があります。フィールドの数が変化する可能性がある場合は、返される実際の数を確認し、実際に存在する要素のみを抽出する必要があります。

于 2013-01-04T02:08:10.417 に答える
2

ブラウザでアプレットを実行すると、何かが原因でファイルが切り捨てられているようです。私の推測では、Webサーバーからファイルをフェッチしていて、サーバーまたはブラウザーのいずれかがサイレントにダウンロード制限を適用していると思います。(または、アップロード時にファイルが切り捨てられた可能性があります...)

于 2013-01-04T02:22:48.523 に答える
1

ネットワーク遅延によって公開されている、あなたworkerと別のスレッド間のデータ競合が疑われます。2つのことが綿密な調査に耐えることができます。

  1. 最初のスレッドinvokeAndWait()でそれ以上の処理が行われない限り、GUIの初期化に使用することは合理的です。

  2. たとえば、イベントディスパッチスレッドに記録する方法として、workerを呼び出さないのは珍しいことです。publish()process()

于 2013-01-04T03:07:23.547 に答える