继续,写了一个小程序来练习网络编程+正则的使用,程序运行界面如下:
编程思路:界面——按钮事件——get提交数据——正则分析返回数据——JTable显示——JTable双击事件(打开后面的地址)。
1.界面(Main类)
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Main extends JFrame{
/**
* @param args
*/
private JButton sosuo;
private JTextField text;
public JTextArea jta;
private Table jsp;
private JPanel jp1;
private JLabel jb1;
private JLabel jb2;
private JLabel jb3;
public String[][] neirong;
public Main()
{
sosuo=new JButton("搜索");
text=new JTextField();
jsp=new Table();
jp1=new JPanel();
jb1=new JLabel();
jb2=new JLabel();
jb3=new JLabel("双击打开连接");
jp1.setLayout(new GridLayout(1,4));
jp1.add(jb1);
jp1.add(text);
jp1.add(sosuo);
jp1.add(jb2);
add(jb3,BorderLayout.SOUTH);
add(jp1,BorderLayout.NORTH);
add(jsp,BorderLayout.CENTER);
setSize(600,400);
//窗体居中显示
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
sosuo.addActionListener(new ActionListener(){
public void actionPerformed(final ActionEvent arg0){
String ssnr=new String();
ssnr=text.getText();
if(ssnr!="")
{
Test test=new Test();
neirong=test.parseHTML(ssnr);
jsp.setneirong(neirong);
}
}
});
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new Main();
}
}
:
相对比较简单,就不赘述。
2.数据的提交+正则分析返回数据:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public String getHTML(String key) throws IOException
{
StringBuilder sb=new StringBuilder();
//要对汉字进行URLEncoder编码
String path="http://www.baidu.com/s?tn=ichuner&lm=-1&word="+URLEncoder.encode(key,"gb2312")+"&rn=100";
URL url=new URL(path);
BufferedReader breader=new BufferedReader(new InputStreamReader(url.openStream()));
String line=null;
while((line=breader.readLine())!=null)
{
//System.out.println(new String(line.getBytes(),"UTF-8"));
sb.append(line);
}
return sb.toString();
}
public String[][] parseHTML(String key)
{
String page=null;
try
{
page=getHTML(key);
}
catch(Exception ex)
{
ex.printStackTrace();
}
/*try {
page=gettxt();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}*/
//System.out.println(page);
String[][] pageContent_list=new String[10][2];
if(page!=null)
{
//正则表达式
String regx="<div[^>]*\\s[iI][dD]=[\"\']?\\d{1,3}[\"\']?[^>]*>.*?href\\s*=\\s*\"(?<href>[^\"]*)\".*?<em>(?<biaoti>.*?)</a>";
//pattern和matcher是java中使用正则表达式的两个类
//pattern.COMMRNTS 参数代表 忽略所有的空白符,包括回车
Pattern pattern=Pattern.compile(regx,Pattern.COMMENTS );
Matcher matcher=pattern.matcher(page);
for(int i=0;i<10;i++)
{
if(matcher.find())
{
//获得table中的数据
String href=new String();
try {
href = new String(matcher.group("href").getBytes(),"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
String biaoti=new String();
try {
biaoti = new String(matcher.group("biaoti").getBytes(),"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
String table_content=matcher.group().toString();
//System.out.println("table_content: "+table_content);
pageContent_list[i][0]=biaoti;
pageContent_list[i][1]=href;
}
}
}
return pageContent_list;
}
public static void main(String[] args) {
Test test=new Test();
//test.parseHTML("百度");
String[][] str=test.parseHTML("百度");
for(int i=0;i<str.length;i++)
{
System.out.println("第"+(i+1)+"条结果:");
System.out.println("标题:"+str[i][0]);
try {
System.out.println("ur"+new String(str[i][1].getBytes(),"UTF-8"));
} catch (UnsupportedEncodingException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
public Test()
{
}
}
说明:pattern和matcher两个类的使用,感觉初学者没必要太深入,了解基础的使用就ok,后面用多了,去看仔细看官方API。
另外Pattern.compile函数:Pattern Pattern.compile(String regex, int flag)
flag的取值范围如下:
Pattern.CANON_EQ,当且仅当两个字符的"正规分解(canonical decomposition)"都完全相同的情况下,才认定匹配。比如用了这个标志之后,表达式"a\u030A"会匹配"?"。默认情况下,不考虑"规范相等性(canonical equivalence)"。
Pattern.CASE_INSENSITIVE(?i) 默认情况下,大小写不敏感的匹配只适用于US-ASCII字符集。这个标志能让表达式忽略大小写进行匹配。要想对Unicode字符进行大小不明感的匹 配,只要将UNICODE_CASE与这个标志合起来就行了。
Pattern.COMMENTS(?x) 在这种模式下,匹配时会忽略(正则表达式里的)空格字符(不是指表达式里的"\\s",而是指表达式里的空格,tab,回车之类)。注释从#开始,一直到这行结束。可以通过嵌入式的标志来启用Unix行模式。
Pattern.DOTALL(?s) 在这种模式下,表达式'.'可以匹配任意字符,包括表示一行的结束符。默认情况下,表达式'.'不匹配行的结束符。
Pattern.MULTILINE(?m)在这种模式下,'^'和'$'分别匹配一行的开始和结束。此外,'^'仍然匹配字符串的开始,'$'也匹配字符串的结束。默认情况下,这两个表达式仅仅匹配字符串的开始和结束。
Pattern.UNICODE_CASE(?u) 在这个模式下,如果你还启用了CASE_INSENSITIVE标志,那么它会对Unicode字符进行大小写不明感的匹配。默认情况下,大小写不敏感的匹配只适用于US-ASCII字符集。
Pattern.UNIX_LINES(?d) 在这个模式下,只有'\n'才被认作一行的中止,并且与'.','^',以及'$'进行匹配。
3.JTable显示结果:
import java.awt.Desktop;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class Table extends JScrollPane{
DefaultTableModel tmd;
JTable jt;
public Table()
{
String[] lieming={"序号","标题","链接"};
tmd=new DefaultTableModel(lieming,11);
jt=new JTable(tmd);
setViewportView(jt);
int[] columnWidth={50,400,150};
//设置列宽
for(int i=0;i<columnWidth.length;i++)
{
jt.getColumnModel().getColumn(i).setPreferredWidth(columnWidth[i]);
}
//表格不可编辑
jt.setEnabled(false);
//jt.setFillsViewportHeight(true);
jt.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int clickCount = e.getClickCount();
if (clickCount == 2) {
int row =((JTable)e.getSource()).rowAtPoint(e.getPoint());
int col=((JTable)e.getSource()).columnAtPoint(e.getPoint());
System.out.println("坐标:"+row+" "+col);
String href=(String)(tmd.getValueAt(row, 2));
URI url=null;
try {
url = new URI(href);
} catch (URISyntaxException e2) {
// TODO 自动生成的 catch 块
e2.printStackTrace();
}
try {
Desktop.getDesktop().browse(url);
} catch (IOException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
}
}
});
}
public void setneirong(String[][] neirong)
{
//清空原有表格
tmd.setRowCount(0);
String[] arr=new String[3];
for(int i=0;i<10;i++)
{
arr[0]=String.valueOf(i+1);
arr[1]=neirong[i][0];
arr[2]=neirong[i][1];
//添加新行
tmd.addRow(arr);
}
//更新表格
jt.invalidate();
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
}
}