2015-03-08

CSV ファイルを読み込んで JavaFX の TableView に表示する(改)

CSV ファイルを読み込んで TableView に表示させるサンプルを前回紹介しましたが、サンプルの完成度が低かったので、手直しをしたものを掲載しました。

動作環境は次の通りです。

  • OS: WIndows 8.1 (64bit)
  • Java: Java SE 1.8.0_40-b25
  • IDE: NetBeans IDE 8.0.2
リスト:TableViewSample.java 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package tableviewsample;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.Callback;
 
public class TableViewSample extends Application {
 
    public static void main(String[] args) {
        launch(args);
    }
 
    ObservableList<String> headers = FXCollections.observableArrayList();
    ObservableList<ObservableList> data = FXCollections.observableArrayList();
 
    TableView<ObservableList> table;
 
    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group(), 600, 400);
        stage.setTitle("CSV Read Sample");
 
        MenuBar menuBar = new MenuBar();
        generateMenu(menuBar, stage);
 
        table = new TableView();
 
        VBox vbox = new VBox();
        vbox.getChildren().addAll(menuBar, table);
        vbox.prefWidthProperty().bind(scene.widthProperty());
        vbox.prefHeightProperty().bind(scene.heightProperty());
        table.prefHeightProperty().bind(vbox.heightProperty());
        ((Group) scene.getRoot()).getChildren().addAll(vbox);
 
        stage.setScene(scene);
        stage.show();
    }
 
    private void generateMenu(MenuBar menuBar, Stage stage) {
        // Menu File
        Menu menuFile = new Menu("File");
        menuBar.getMenus().addAll(menuFile);
 
        // MenuItem Exit
        MenuItem open = new MenuItem("Open");
        open.setOnAction((ActionEvent t) -> {
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("Open CSV File");
            fileChooser.getExtensionFilters().addAll(
                    new FileChooser.ExtensionFilter("CSV", "*.csv"),
                    new FileChooser.ExtensionFilter("All", "*.*")
            );
             
            File file = fileChooser.showOpenDialog(stage);
            if (file != null) {
                readCSV(file);
                open.setDisable(true);
            }
        });
 
        // MenuItem Exit
        MenuItem exit = new MenuItem("Exit");
        exit.setOnAction((ActionEvent t) -> {
            System.exit(0);
        });
 
        menuFile.getItems().addAll(open, new SeparatorMenuItem(), exit);
    }
 
    void readCSV(File file) {
        try {
            if (checkBeforeReadfile(file)) {
                FileInputStream in = new FileInputStream(file);
//                InputStreamReader sr = new InputStreamReader(in, "UTF-8");
                InputStreamReader sr = new InputStreamReader(in, "Shift_JIS");
                BufferedReader br = new BufferedReader(sr);
 
                String line;
                boolean isHeader = true;
                while ((line = br.readLine()) != null) {
                    StringTokenizer token = new StringTokenizer(line, ",");
                    ObservableList<String> lineList = FXCollections.observableArrayList();
 
                    if (isHeader) {
                        while (token.hasMoreTokens()) {
                            headers.add(token.nextToken());
                        }
                        isHeader = false;
                    } else {
                        while (token.hasMoreTokens()) {
                            lineList.add(token.nextToken());
                        }
                        data.add(lineList);
                    }
                }
            } else {
                System.out.println("No file exists or can't open.");
            }
        } catch (FileNotFoundException e) {
            System.out.println("FileNotFoundException : " + e.getMessage());
        } catch (IOException e) {
            System.out.println("IOException : " + e.getMessage());
        }
 
        generateTable();
 
    }
 
    private void generateTable() {
        int idx = 0;
        TableColumn[] column = new TableColumn[headers.size()];
        for (String colName : headers) {
            column[idx] = new TableColumn(colName);
            column[idx].setCellValueFactory(new SetCellProperty(idx));
            idx++;
        }
        table.getColumns().addAll(column);
 
        table.setItems(data); // finally add data to tableview
    }
 
    boolean checkBeforeReadfile(File file) {
        if (file.exists()) {
            if (file.isFile() && file.canRead()) {
                return true;
            }
        }
        return false;
    }
 
    private static class SetCellProperty implements Callback<CellDataFeatures<ObservableList, String>, ObservableValue<String>> {
 
        private final int i;
 
        public SetCellProperty(int i) {
            this.i = i;
        }
 
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param) {
            return new SimpleStringProperty(param.getValue().get(i).toString());
        }
    }
}

実行例を以下に示しました。郵便番号データダウンロード 住所の郵便番号(ローマ字) zip形式 - 日本郵便 からダウンロードした CSV ファイルにヘッダー情報をつけるなどの加工をしておいて読み込んでみました。

参考サイト

  1. Updated: Dynamic TableView Data From Database « Java and FX

 

0 件のコメント: