关闭

Swing读大型文本文件

标签: 文件读写Swing与多线程
258人阅读 评论(0) 收藏 举报
分类:

Swing组件是采取单线程规则。如果在做某一个特别耗费时间的任务,则组件的更新操作将会被堵住。

例如,我定义了一个JButton 点击之后,然后添加一个监听器,当button被点击 发生 for(int i=0;i!=10000000;++i)  textArea.append(i+"\n");  完成对文本区数字添加。

如果你在此时点击窗口关闭按钮,你会发现,没有效果,原因就是当前线程堵塞在 button监听器中。

解决这个的办法就是对耗费时间的任务启用新的线程来做,同时对Swing的更新需要放在EventQueue.invokeLater()中。

例如上面的操作可以采用下面方式:

	button.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				Runnable r = new Runnable(){	//启用一个新的线程,完成耗费时间操作

					@Override
					public void run() {
						// TODO Auto-generated method stub
						for(int i=0;i<=100000000;++i)
						{
							Integer ie = new Integer(i);
							EventQueue.invokeLater(new Runnable(){	//由于对JTextArea 进行更新,所以放入事件队列中

								@Override
								public void run() {
									// TODO Auto-generated method stub
									textArea.append(ie+"\n");
								}
							});
							try {
								/*
								 * sleep()是主要是为了防止事件队列中一次放入太多textArea.append()事件,
								 * 而关闭事件得不到及时响应设置
								 */
								Thread.sleep(2);	
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
							
					}
					
				};
				new Thread(r).start();
				
			}});

对于文件操作也是一样,不过我省略了sleep , 但是下过还是可以接受的...

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;


public class SwingBigFile {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		EventQueue.invokeLater(new Runnable(){
			@Override
			public void run()
			{
				DemoFrame frame = new DemoFrame();
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setLocationByPlatform(true);
				frame.setVisible(true);
			}
		});
	}

}

class DemoFrame extends JFrame
{
	
	public DemoFrame()
	{
		textArea = new JTextArea(30,50);
		JScrollPane pane =  new JScrollPane(textArea);
		add(pane);
		chooser = null;
		
		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);
		
		JMenu fileMenu =  new JMenu("File");
		menuBar.add(fileMenu);
		
		JMenuItem openItem = new JMenuItem("Open");
		fileMenu.add(openItem);
		openItem.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e)
			{
				if(null== chooser || chooser.getParent()!=DemoFrame.this)
					chooser = new JFileChooser();
				chooser.setCurrentDirectory(new File("K:\\WorkSpace\\MyNotepad"));
				int iResult = chooser.showOpenDialog(DemoFrame.this);
				
				if(JFileChooser.APPROVE_OPTION==iResult)
				{
					Path path = chooser.getSelectedFile().toPath();
					try(FileChannel channel = FileChannel.open(path, StandardOpenOption.READ))
					{
						MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
						final int SIZE = 1024*1024;
						byte[] bytes = new byte[SIZE];
						Charset charset = Charset.forName("UTF-8"); 
						textArea.setText("");
						while(SIZE <= map.remaining())
						{
							map.get(bytes);
							CharBuffer cb = charset.decode(ByteBuffer.wrap(bytes));
							textArea.append(cb.toString());
						}
						
						if(map.hasRemaining())
						{
							bytes = new byte[map.remaining()];
							map.get(bytes);
							CharBuffer cb = charset.decode(ByteBuffer.wrap(bytes));
							textArea.append(cb.toString());
						}
						
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
						JOptionPane.showMessageDialog(DemoFrame.this, "open file failed!", "Error", JOptionPane.ERROR_MESSAGE);
						
					}
				}
			}
		});
		
		JMenuItem openNewItem = new JMenuItem("OpenNew");
		fileMenu.add(openNewItem);
		openNewItem.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				if(null== chooser || chooser.getParent()!=DemoFrame.this)
					chooser = new JFileChooser();
				chooser.setCurrentDirectory(new File("K:\\WorkSpace\\MyNotepad"));
				int iResult = chooser.showOpenDialog(DemoFrame.this);
				
				if(JFileChooser.APPROVE_OPTION==iResult)
				{
					Path path = chooser.getSelectedFile().toPath();
					textArea.setText("");
					ReadRunnable run = new ReadRunnable(path);
					new Thread(run).start();
				}
			}
			
		});
		
		
		pack();
	}
	
	private JTextArea textArea;
	private JFileChooser chooser;
	
	class ReadRunnable implements Runnable
	{
		public ReadRunnable( Path path)
		{
		
			this.path = path;
		}
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			try(FileChannel channel = FileChannel.open(path, StandardOpenOption.READ))
			{
				MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
				final int SIZE = 1024*20;	//这里不应该设置太大!1024 * 1024 堵塞
				byte[] bytes = new byte[SIZE];
				Charset charset = Charset.forName("GB2312"); 
				Boolean flag =false;
				
				while(SIZE <= map.remaining())
				{
					map.get(bytes);
					CharBuffer cb = charset.decode(ByteBuffer.wrap(bytes));
					EventQueue.invokeLater(new Runnable(){

						@Override
						public void run() {
							
							// TODO Auto-generated method stub
							textArea.append(cb.toString());
							//textArea.setCaretPosition(textArea.getCaretPosition());
						}
						
					});
					//Thread.sleep(10);
				}
				
				if(map.hasRemaining())
				{
					bytes = new byte[map.remaining()];
					map.get(bytes);
					CharBuffer cb = charset.decode(ByteBuffer.wrap(bytes));
					EventQueue.invokeLater(new Runnable(){

						@Override
						public void run() {
							// TODO Auto-generated method stub
							textArea.append(cb.toString());
						}
						
					});
				}
				//Thread.sleep(10);
				textArea.setCaretPosition(0);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
				JOptionPane.showMessageDialog(DemoFrame.this, "open file failed!", "Error", JOptionPane.ERROR_MESSAGE);
				
			} //catch (InterruptedException e) {
				// TODO Auto-generated catch block
				
			//}
		}
		
		private Path path;
	}

}


我用了20M的txt文本进行测试,效果良好。如果有乱码可以在Charset处进行设置文本编码





0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3168次
    • 积分:149
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:2篇
    • 译文:2篇
    • 评论:2条
    文章存档
    最新评论