1. 程式人生 > >SwingWork + 執行緒池 +JTable +java寫入中文亂碼-- 一個swing的小應用

SwingWork + 執行緒池 +JTable +java寫入中文亂碼-- 一個swing的小應用

這幾天因為業務需求需要開發一個批量訂購業務的小工具,之前一直是通過程式碼處理,想著做個圖形介面的小工具會更方便點

於是用swing做了這個小工具。因為需要http請求訂購介面,所以使用了swing中的執行緒工具SwingWork,這個類的用法和安卓的非同步訊息處理比較類似,同樣是開啟執行緒執行後臺任務,並能將處理結果更新到UI。 這個小應用裡是將http請求訂購介面後返回的訂購結果實時的更新到swing的JTable中

因為批量訂購資料量較大,所以使用了執行緒池

最後判斷執行緒池中所有任務是否執行完畢,並用IO流生成訂購日誌。注意對寫入中文亂碼的處理

比較簡單,介面比較醜~~ 直接上原始碼


public class ServiceOrder extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;
	private ExecutorService pool;
	JLabel info;
	JTextField fileName;
	JButton improt;
	JButton open;
	JButton start;
	JTextArea count;
	JTextArea errort;;

	JTable table;
	JScrollPane scrollPane;
	DefaultTableModel defaultModel;

	JPanel j1;
	JPanel j2;
	JPanel j3;
	JPanel j4;
	JPanel j5;

	JFileChooser filechoose = new JFileChooser();
	FileFilter filter;
	Vector<String> head;
	// 定義異常訂購資料總數
	int errorcount = 0;
	//定義一次匯入處理完成標識(匯入處理完成後不能開始處理第二次,除非重新匯入)
	boolean ordered =false;

	public ServiceOrder() {
		j1 = new JPanel();
		j1.setPreferredSize(new Dimension(700, 30));
		FlowLayout fl1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
		j1.setLayout(fl1);
		info = new JLabel("匯入要處理的賬號");
		j1.add(info);

		j2 = new JPanel();
		j2.setPreferredSize(new Dimension(700, 50));
		FlowLayout fl2 = new FlowLayout(FlowLayout.CENTER, 10, 10);
		j2.setLayout(fl2);
		fileName = new JTextField(40);
		improt = new JButton("匯入");
		open = new JButton("開啟");
		open.addActionListener(this);
		improt.addActionListener(this);
		j2.add(fileName);
		j2.add(open);
		j2.add(improt);

		j3 = new JPanel();
		j3.setPreferredSize(new Dimension(720, 380));

		head = new Vector<String>();
		head.add("賬號");
		head.add("來源");
		head.add("型別");
		head.add("產品");
		head.add("平臺");
		head.add("處理結果");
		head.add("處理時間");
		defaultModel = new DefaultTableModel(null, head);
		table = new JTable(defaultModel);
		table.setPreferredScrollableViewportSize(new Dimension(700, 350));
		scrollPane = new JScrollPane(table);
		this.getContentPane().add(scrollPane, BorderLayout.CENTER);
		j3.add(scrollPane);

		j4 = new JPanel();
		j4.setPreferredSize(new Dimension(700, 30));
		start = new JButton("開始");
		start.addActionListener(this);
		FlowLayout fl4 = new FlowLayout(FlowLayout.CENTER);
		j4.setLayout(fl4);
		j4.add(start);

		j5 = new JPanel();
		j5.setPreferredSize(new Dimension(700, 30));
		j5.setLayout(fl1);
		count = new JTextArea();
		errort = new JTextArea();
		j5.add(count);
		j5.add(errort);

		FlowLayout fl5 = new FlowLayout(FlowLayout.CENTER);
		setLayout(fl5);
		add(j1);
		add(j2);
		add(j3);
		add(j5);
		add(j4);
		setTitle("批量訂購");
		setSize(800, 620);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);

		// 設定開啟檔案/
		filechoose.setFileSelectionMode(JFileChooser.FILES_ONLY);// 設定選擇模式,只可以選擇檔案
		String extj[] = { "txt" };
		filter = new FileNameExtensionFilter("txt", extj);
		filechoose.setFileFilter(filter);// 設定檔案字尾過濾器
	}

	public static void main(String[] args) {
		new ServiceOrder();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		int retval;
		String selection = e.getActionCommand();
		if (selection.equals("開啟")) {
			retval = filechoose.showOpenDialog(this);// 顯示"儲存檔案"對話方塊
			if (retval == JFileChooser.APPROVE_OPTION) {// 若成功開啟
				File file = filechoose.getSelectedFile();// 得到選擇的檔案
				fileName.setText(file.getPath());
				// 清空表格資料
				while (defaultModel.getRowCount() > 0) {
					defaultModel.removeRow(defaultModel.getRowCount() - 1);
				}
				count.setText("");
				errort.setText("");
			}

		} else if (selection.equals("匯入")) {
			ordered =false;
			errorcount = 0;
			errort.setText("");
			String name = fileName.getText();
			File file = new File(name);
			if (DateUtils.isBlank(name) || !file.exists()) {
				JOptionPane.showMessageDialog(ServiceOrder.this, "沒有選擇檔案或檔案不存在", "提示",
						JOptionPane.ERROR_MESSAGE);
			} else {
				// 匯入之前清空表格資料
				while (defaultModel.getRowCount() > 0) {
					defaultModel.removeRow(defaultModel.getRowCount() - 1);
				}
				FileReader fileReader;
				try {
					fileReader = new FileReader(file);
					BufferedReader bufferedReader = new BufferedReader(
							fileReader);

					int lineCount = 0;
					String line = null;

					while ((line = bufferedReader.readLine()) != null) {
						if (DateUtils.isNotBlank(line)) {
							String[] temps = line.split("\\|");
							Vector<String> row = new Vector<String>();
							row.add(temps[0].trim());
							row.add(temps[1].trim());
							row.add(temps[2].trim());
							row.add(temps[3].trim());
							row.add(temps[4].trim());
							defaultModel.addRow(row);
							lineCount++;
						}
					}
					fileReader.close();
					bufferedReader.close();
					count.setText("共匯入" + lineCount + "條資料");

				} catch (FileNotFoundException e1) {
					e1.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		} else if (selection.equals("開始")) {
			pool = Executors.newFixedThreadPool(5);//初始化執行緒池
			if(!ordered){
				Vector<Vector<String>> data = defaultModel.getDataVector();
				if (data == null) {
					JOptionPane.showMessageDialog(ServiceOrder.this, "沒有要處理的資料", "提示",
							JOptionPane.ERROR_MESSAGE);
				} else {
					start.setText("正在處理");
					start.setEnabled(false);
					improt.setEnabled(false);
					open.setEnabled(false);
					fileName.setVisible(false);

					for (int i = 0; i < data.size(); i++) {
						final int j = i;
						// 多執行緒發起訂購
						pool.execute(new SwingWorker<String[], Void>() {
							@Override
							protected String[] doInBackground() throws Exception {
								// 發起訂購
								JSONObject resultinfo = OrderClient.order(data
										.get(j));
								String results = "";
								if (resultinfo == null) {
									results = "處理異常";
									synchronized (this) {
										errorcount++;
									}
								} else {
									if ("0".equals(resultinfo.getString("result"))) {
										results = "成功";
									} else {
										results = "失敗!錯誤碼"
												+ resultinfo.getString("result");
									}
								}
								String time = DateUtils.formatString(new Date(),
										DateUtils.DATE_FORMAT_YMDHMS);
								String[] temps = new String[3];
								temps[0] = results;
								temps[1] = time;
								temps[2] = j + "";
								return temps;
							}

							@Override
							protected void done() {
								// 獲得doInBackground()返回資料
								String[] result = null;
								try {
									result = get();
								} catch (InterruptedException e) {
									e.printStackTrace();
								} catch (ExecutionException e) {
									e.printStackTrace();
								}
								// 處理結果更新到表格
								defaultModel.setValueAt(result[0],
										Integer.valueOf(result[2]), 5);
								defaultModel.setValueAt(result[1],
										Integer.valueOf(result[2]), 6);
							}

						});
					}
					// 新增所有任務處理完成監聽
					success();
				}
			}else{
				JOptionPane.showMessageDialog(ServiceOrder.this, "匯入資料已處理完成,請重新匯入", "提示",
						JOptionPane.ERROR_MESSAGE);
			}
			
		}
	}

	// 判斷是否所有任務都執行完成,生成處理日誌
	private void success() {
		pool.shutdown();
		SwingWorker<String, Void> work = new SwingWorker<String, Void>() {
			@Override
			protected String doInBackground() throws Exception {
				while (true) {
					if (pool.isTerminated()) {
						break;
					}
					Thread.sleep(1000);
				}
				// 生成訂購結果日誌
				BufferedWriter bufferedWriter = null;
				try {
					File f = new File(fileName.getText()
							+ "_log_"
							+ DateUtils.formatString(new Date(),
									DateUtils.DATE_FORMATE_LX_YMDHMS) + ".txt"); 
					if (!f.exists()) { 
					    f.createNewFile(); 
					} 
					bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f),"GBK"));
					bufferedWriter
							.write("userid | uoid | action | productId |desc | result | addtime");
					bufferedWriter.newLine();
					
					Vector<Vector<String>> data = defaultModel.getDataVector();
					for (Vector<String> vector : data) {
						bufferedWriter.write(vector.get(0) + "|"
								+ vector.get(1) + "|" + vector.get(2)
								+ "|" + vector.get(3) + "|"
								+ vector.get(4) + "|" +vector.get(5) + "|" + vector.get(6));
						bufferedWriter.newLine();
					}
					
				} catch (IOException e1) {
					e1.printStackTrace();
				} finally {
					try {
						if (bufferedWriter != null) {
							bufferedWriter.flush();
							bufferedWriter.close();
						}
					} catch (IOException ex) {
						ex.printStackTrace();
					}
				}
				return null;
			}

			@Override
			protected void done() {
				JOptionPane.showMessageDialog(ServiceOrder.this, "處理完成!", "提示",
						JOptionPane.ERROR_MESSAGE);
				errort.setText("  處理異常共" + errorcount + "條");
				start.setText("開始");
				start.setEnabled(true);
				improt.setEnabled(true);
				open.setEnabled(true);
				fileName.setVisible(true);
				ordered= true;//標識一次匯入處理完成
			}

		};
		work.execute();
	}
}
匯入要處理的檔案格式: (訂購介面需要的引數)

0000000412|9999|1|000011|HUYYU
0000000413|9999|1|000000|HUIUIIU

生成的訂購日誌:

userid | uoid | action | productId |desc| result | addtime
0000000412|9999|1|000001|HUYYU|失敗!錯誤碼501|2015-11-23 10:53:43
0000000413|9999|1|000000|HUIUIIU|失敗!錯誤碼501|2015-11-23 10:53:43