有些网页是屏蔽了鼠标右键的,不让我们查看它的源代码或者不让我们点击鼠标右键,在此我们可以写一个程序,让它获得这个网页的流,然后我们不就什么都能看到了吗?此程序就是这样写的,先获得网页的输入流,然后得到这个输入流的一些参数,比如这个流的长度,这个流所使用的编码.然后根据这些参数来进行获取,并根据不同的情况提供不同的进度条,比如有些网页它的长度返回的是-1,这个时候就用一个无状态的进度条来表示,如果长度大于0的话,那就用可以实时显示目前读取网页的进度.正好借这个机会又把swing复习了一下.呵呵.
运行时的图片如下:
下面是代码.
/*
* Test4.java
*
* Created on 2007年9月27日, 下午3:05
*/
package test2;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
/**
*
* @author hadeslee
*/
public class Test4 extends javax.swing.JFrame {
private Task task; //只存在的一个方法
/** Creates new form Test4 */
public Test4() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception exe) {
exe.printStackTrace();
}
initComponents();
jpb.setStringPainted(true);
jpb.setVisible(false);
this.setLocationRelativeTo(null);
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
input = new javax.swing.JTextField();
jButton1 = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
output = new javax.swing.JTextArea();
jButton2 = new javax.swing.JButton();
jButton3 = new javax.swing.JButton();
jpb = new javax.swing.JProgressBar();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("查看网页源文件");
setResizable(false);
jLabel1.setForeground(new java.awt.Color(51, 51, 255));
jLabel1.setText("地址");
input.setForeground(new java.awt.Color(51, 51, 255));
input.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
inputActionPerformed(evt);
}
});
jButton1.setForeground(new java.awt.Color(51, 51, 255));
jButton1.setText("查看");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jScrollPane1.setBorder(javax.swing.BorderFactory.createTitledBorder("源文件"));
output.setColumns(20);
output.setEditable(false);
output.setLineWrap(true);
output.setRows(5);
output.setWrapStyleWord(true);
jScrollPane1.setViewportView(output);
jButton2.setText("保存");
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
jButton3.setText("退出");
jButton3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton3ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(input, javax.swing.GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton1))
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addComponent(jButton2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jpb, javax.swing.GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(jButton1)
.addComponent(input, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 223, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton2)
.addComponent(jButton3))
.addComponent(jpb, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
pack();
}// </editor-fold>
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if (task != null) {
task.cancel();
}
task = new Task(input.getText());
new Thread(task).start();
}
private void inputActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if (task != null) {
task.cancel();
}
task = new Task(input.getText());
new Thread(task).start();
}
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
System.exit(0);
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
doSave();
}
//用于保存的方法
private void doSave() {
String s = output.getText();
if (s == null || s.equals("")) {
JOptionPane.showMessageDialog(this, "当前没有东西可保存!!");
return;
}
JFileChooser jfc = new JFileChooser(".");
FileNameExtensionFilter txt = new FileNameExtensionFilter("文本文档(*.txt)", "txt");
FileNameExtensionFilter html = new FileNameExtensionFilter("网页文档(*.html)", "html", "htm");
jfc.addChoosableFileFilter(html);
jfc.addChoosableFileFilter(txt);
int i = jfc.showSaveDialog(this);
if (JFileChooser.APPROVE_OPTION == i) {
BufferedWriter bw = null;
try {
File f = jfc.getSelectedFile();
FileFilter filter = jfc.getFileFilter();
FileNameExtensionFilter ff = null;
//如果是可以匹配的,则匹配,否则的话,只能用户输入什么
//就是什么了,即使他不输入后缀名那也没办法了
if (filter instanceof FileNameExtensionFilter) {
ff = (FileNameExtensionFilter) filter;
String[] exts = ff.getExtensions();
boolean match = false;
for (String ext : exts) {
if (f.toString().toLowerCase().endsWith(ext.toLowerCase())) {
match = true;
break;
}
}
//如果没有匹配,则说明输入的时候,没有输入后缀名,我们要人工加上去
if (!match) {
f = new File(f.toString() + "." + exts[0]);
}
}
bw = new BufferedWriter(new FileWriter(f));
bw.write(s);
JOptionPane.showMessageDialog(this, "保存成功!!");
} catch (IOException ex) {
Logger.getLogger(Test4.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (bw != null) {
bw.close();
}
} catch (IOException ex) {
Logger.getLogger(Test4.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
//用于取源码的线程
private class Task implements Runnable {
//此任务是否已经取消了
private volatile boolean isCanceled;
private String s;
private int done; //已经完成的字节
private InputStream is; //连上的输入流,如果长时间没有动作,则流也要被强制关闭
private long time; //最新一次读流的时间
public Task(String s) {
this.s = s;
time = System.currentTimeMillis(); //初始化第一次的时间
new Thread() {
public void run() {
while (!isCanceled) {
try {
Thread.sleep(1000);
long now = System.currentTimeMillis();
//如果最后一次读成功字节到现在已经过了30秒钟了,则强行断之
if (now - time > 30000) {
isCanceled = true;
jpb.setIndeterminate(false);
jpb.setVisible(false);
is.close();
}
} catch (Exception ex) {
Logger.getLogger(Test4.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}.start();
}
public void run() {
validate(s);
}
//验证传入的字符串是否合法
private void validate(String s) {
try {
if (s == null || s.equals("")) {
JOptionPane.showMessageDialog(Test4.this, "网址不能为空!!");
input.requestFocus();
return;
} else if (s.startsWith("http://")) {
//什么都不要做
} else {
//如果没有加上http的前缀的话,我们帮他加上
s = "http://" + s;
}
if (isCanceled) {
return;
}
URL url = new URL(s);
viewSource(url);
} catch (MalformedURLException ex) {
Logger.getLogger(Test4.class.getName()).log(Level.SEVERE, null, ex);
JOptionPane.showMessageDialog(Test4.this, "域名解析出错!!");
}
}
//执行查看网页源文件的动作
private void viewSource(URL url) {
try {
jpb.setVisible(true);
jpb.setValue(0);
jpb.setString("");
HttpURLConnection http = (HttpURLConnection) url.openConnection();
//得到网页的内容长度,可能为-1
int length = http.getContentLength();
if (length != -1) {
jpb.setIndeterminate(false);
jpb.setMaximum(length);
jpb.setValue(0);
} else {
jpb.setString("");
jpb.setIndeterminate(true);
}
//中间再检查一下是否取消了本次任务,以免做无谓的功
if (isCanceled) {
return;
}
//得到网页的编码,可能没有指定,如果没有指定,就用默认的系统编码了
String contentType = http.getContentType();
String encoding = null; //将要使用的编码,它将从contentType里面去取
if (contentType != null) {
int index = contentType.indexOf("charset=");
if (index != -1) {
encoding = contentType.substring(index + 8).trim();
}
}
is = http.getInputStream();
//如果得到的长度是-1,则不知道什么时候会读完
//这个时候就可以边读边显示出来
if (length == -1) {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String temp = null;
output.setText(null);
while (br.ready()) {
time = System.currentTimeMillis();
temp = br.readLine();
if (isCanceled) {
return;
}
output.append(temp + "\r\n");
}
System.out.println("读到底了");
isCanceled = true;
jpb.setIndeterminate(false);
jpb.setVisible(false);
} else {
//如果知道长度多长,就可以显示一个进度条,等所有的字节都读完再显示
ByteArrayOutputStream bout = new ByteArrayOutputStream();
int data = -1;
while ((data = is.read()) != -1) {
if (isCanceled) {
return;
}
time = System.currentTimeMillis();
if (length > 0) {
done++;
jpb.setValue(done);
int rate = done * 100 / length;
jpb.setString("" + rate + "%");
}
bout.write(data);
//如果长度不为-1,并且已经读了这么多长度以后,就要断线了
if (done == length) {
String text = null;
byte[] b = bout.toByteArray();
if (encoding == null) {
text = new String(b);
} else {
text = new String(b, encoding);
}
if (!isCanceled) {
output.setText(text);
}
isCanceled = true;
jpb.setVisible(false);
return;
}
}
}
} catch (IOException ex) {
Logger.getLogger(Test4.class.getName()).log(Level.SEVERE, null, ex);
if (isCanceled) {
return;
} else {
JOptionPane.showMessageDialog(Test4.this, "打开网页失败!!");
}
} catch (Exception exe) {
if (isCanceled) {
return;
} else {
JOptionPane.showMessageDialog(Test4.this, "打开网页失败!!");
}
} finally {
try {
if (is != null) {
is.close();
}
jpb.setVisible(false);
} catch (IOException ex) {
Logger.getLogger(Test4.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void cancel() {
isCanceled = true;
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Test4().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JTextField input;
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JButton jButton3;
private javax.swing.JLabel jLabel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JProgressBar jpb;
private javax.swing.JTextArea output;
// End of variables declaration
}
我是用NetBeans写的,程序部份都有注释,界面部份是拖出来的,以前我很不喜欢拖控件的,所有的界面都是自己手写代码,后来发现NetBeans的拖控件功能确实很强,应该说是JAVA IDE里面最强的了.所以忍不住就用了一下,感觉不错,所以向大家推荐一下.可执行的JAR文件也一并附上,点击这里下载.欢迎大家提出问题.
JAVA运行环境是JDK6.0:)
尽管千里冰封
依然拥有晴空
你我共同品味JAVA的浓香.
posted on 2007-09-28 11:33
千里冰封 阅读(3061)
评论(8) 编辑 收藏 所属分类:
JAVASE