请教:如何将下面的程序code1改写成多线程的?直接实现Runnable接口,将根目录下的每一个目录建立一个线程?(但是出现了问题,就是建立的线程都是下载内容不完全就结束了。)
import java.io.IOException;
import java.text.ParseException;
import java.io.*;import com.enterprisedt.net.ftp.*;public class Crawler_Beta1 { static FileTransferClient ftpClient;
private final static int MAX_FIELDS = 20; public static void main(String[] args)
throws IOException, FTPException, ParseException{ String host = "*.*.*.*";
String username = "anonymous";
String password = "[email protected]";
PrintStream ps =
new PrintStream(new FileOutputStream(new File("E:/" + host + "_Beta1.txt")));
System.setOut(ps);
ftpClient = new FileTransferClient();
ftpClient.setRemoteHost(host);
ftpClient.setUserName(username);
ftpClient.setPassword(password);
ftpClient.getAdvancedSettings().setControlEncoding("GBK");
ftpClient.connect();
long startTime = System.currentTimeMillis();
System.out.println("目录: " + "/");
FTPFile[] rootFile = ftpClient.directoryList("/");
for(int i = 0; i < rootFile.length; i++){
done_FTP("/", rootFile[i]);
}
System.out.println("It takes: " +
((System.currentTimeMillis()-startTime)/1000) + " seconds.");
ftpClient.disconnect();
} private static void done_FTP(String rootName, FTPFile ftpFile)
throws IOException, FTPException, ParseException {
String fileName = ftpFile.getName();
//获得文件的属性说明,zzu_FTP显示目录标识为fields[2]=="<DIR>"
String[] fields = split(ftpFile.getRaw());
if(fields[2].equalsIgnoreCase("<DIR>")){
String tmpName = rootName + fileName;
System.out.println("Dir: " + tmpName);
FTPFile[] tmpFile = ftpClient.directoryList(tmpName);
for(FTPFile file : tmpFile){
done_FTP(tmpName + "/", file);
}
}else {
System.out.println("File: " + "+" + fileName);
}
}
private static void done(String rootName, FTPFile ftpFile)
throws IOException, FTPException, ParseException {
String fileName = ftpFile.getName();
//获得文件的属型说明,windows xp有9个属性
String[] fields = split(ftpFile.getRaw()); if (fields[0].charAt(0)=='d' && !fields[8].equalsIgnoreCase(".")
&& !fields[8].equalsIgnoreCase("..")){
System.out.println("目录: " + rootName + fileName);
FTPFile[] tmpFile = ftpClient.directoryList(rootName + fileName);
for(FTPFile file : tmpFile){
done(rootName + fileName + "/", file);
} }else if(fields[0].charAt(0)=='-'){
System.out.println("普通文件: " + rootName + fileName);
}else if(fields[0].charAt(0)=='l'){
System.out.println("链接文件: " + rootName + fileName);
}
}
//该方法在com.enterprisedt.net.ftp.FTPFileParser里面,也可以将类直接继承FTPFileParser类
protected static String[] split(String str) {
String[] fields = new String[MAX_FIELDS];
int pos = 0;
StringBuffer field = new StringBuffer();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (!Character.isWhitespace(ch))
field.append(ch);
else {
if (field.length()> 0) {
fields[pos++] = field.toString();
field.setLength(0);
}
}
} if (field.length() > 0) {
fields[pos++] = field.toString();
}
String[] result = new String[pos];
System.arraycopy(fields, 0, result, 0, pos);
return result;
}
}
import java.io.IOException;
import java.text.ParseException;
import java.io.*;import com.enterprisedt.net.ftp.*;public class Crawler_Beta1 { static FileTransferClient ftpClient;
private final static int MAX_FIELDS = 20; public static void main(String[] args)
throws IOException, FTPException, ParseException{ String host = "*.*.*.*";
String username = "anonymous";
String password = "[email protected]";
PrintStream ps =
new PrintStream(new FileOutputStream(new File("E:/" + host + "_Beta1.txt")));
System.setOut(ps);
ftpClient = new FileTransferClient();
ftpClient.setRemoteHost(host);
ftpClient.setUserName(username);
ftpClient.setPassword(password);
ftpClient.getAdvancedSettings().setControlEncoding("GBK");
ftpClient.connect();
long startTime = System.currentTimeMillis();
System.out.println("目录: " + "/");
FTPFile[] rootFile = ftpClient.directoryList("/");
for(int i = 0; i < rootFile.length; i++){
done_FTP("/", rootFile[i]);
}
System.out.println("It takes: " +
((System.currentTimeMillis()-startTime)/1000) + " seconds.");
ftpClient.disconnect();
} private static void done_FTP(String rootName, FTPFile ftpFile)
throws IOException, FTPException, ParseException {
String fileName = ftpFile.getName();
//获得文件的属性说明,zzu_FTP显示目录标识为fields[2]=="<DIR>"
String[] fields = split(ftpFile.getRaw());
if(fields[2].equalsIgnoreCase("<DIR>")){
String tmpName = rootName + fileName;
System.out.println("Dir: " + tmpName);
FTPFile[] tmpFile = ftpClient.directoryList(tmpName);
for(FTPFile file : tmpFile){
done_FTP(tmpName + "/", file);
}
}else {
System.out.println("File: " + "+" + fileName);
}
}
private static void done(String rootName, FTPFile ftpFile)
throws IOException, FTPException, ParseException {
String fileName = ftpFile.getName();
//获得文件的属型说明,windows xp有9个属性
String[] fields = split(ftpFile.getRaw()); if (fields[0].charAt(0)=='d' && !fields[8].equalsIgnoreCase(".")
&& !fields[8].equalsIgnoreCase("..")){
System.out.println("目录: " + rootName + fileName);
FTPFile[] tmpFile = ftpClient.directoryList(rootName + fileName);
for(FTPFile file : tmpFile){
done(rootName + fileName + "/", file);
} }else if(fields[0].charAt(0)=='-'){
System.out.println("普通文件: " + rootName + fileName);
}else if(fields[0].charAt(0)=='l'){
System.out.println("链接文件: " + rootName + fileName);
}
}
//该方法在com.enterprisedt.net.ftp.FTPFileParser里面,也可以将类直接继承FTPFileParser类
protected static String[] split(String str) {
String[] fields = new String[MAX_FIELDS];
int pos = 0;
StringBuffer field = new StringBuffer();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (!Character.isWhitespace(ch))
field.append(ch);
else {
if (field.length()> 0) {
fields[pos++] = field.toString();
field.setLength(0);
}
}
} if (field.length() > 0) {
fields[pos++] = field.toString();
}
String[] result = new String[pos];
System.arraycopy(fields, 0, result, 0, pos);
return result;
}
}
Crawler_Beta1 =========> CrawlerBeta1
done_FTP ---------> doneFtp
线程可以这样写new Thread(new Runnable() {
//这里面写你操作FTP 对象的代码即可。
}).start();
使用单线程的话,程序正常,能下载全部的内容。
但是我改写成多线程后(我是将根目录下的每一个第一级子目录作为一个线程来下载。但是下载的内容就不全,往往只下载到一半多的时候,线程就退出了。也没有报线程异常。)下面是我写的多线程,代码不规范,请各位见谅呵。
package FtpSearch.Beta3;import java.io.IOException;
import java.text.ParseException;
import java.io.*;import com.enterprisedt.net.ftp.*;public class Crawler_MultiThread_Beta3 implements Runnable{ FileTransferClient ftpClient;
private final static int MAX_FIELDS = 20; String rootName = "";
FTPFile ftpFile;
FileWriter fw;
public Crawler_MultiThread_Beta3(String rootName, FTPFile ftpFile,
FileWriter fw, FileTransferClient ftpClient)
throws FTPException, IOException{
this.rootName = rootName;
this.ftpFile = ftpFile;
this.fw = fw;
this.ftpClient = ftpClient;
}
public void run() {
try {
done_zzuFTP(this.rootName, this.ftpFile,
this.fw, this.ftpClient);
this.fw.write("" + System.currentTimeMillis() );
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args)
throws IOException, FTPException, ParseException{ String host = "*.*.*.*";
String username = "anonymous";
String password = "[email protected]"; FileTransferClient ftpClient1 = new FileTransferClient();
ftpClient1.setRemoteHost(host);
ftpClient1.setUserName(username);
ftpClient1.setPassword(password);
// ftpClient1.setTimeout(600000); ftpClient1.getAdvancedSettings().setControlEncoding("GBK");
ftpClient1.connect();
System.out.println("Start at: " +
System.currentTimeMillis() );
FTPFile[] rootFile = ftpClient1.directoryList("/");
for(int i = 0; i < rootFile.length; i++){ FileWriter fw = new FileWriter(new File("E:/Test1/"
+ rootFile[i].getName() + "_Beta3.txt"));
//这里我是将每一个子目录分别用一个线程下载,通过构造函数传入目录,文档的类型,文件流,
//和建立链接的ftpClient,所有线程共用ftpClient。
//好像也没有需要同步的操作啊,不明白哪儿错了
new Thread(new Crawler_MultiThread_Beta3("/" +
rootFile[i].getName(), rootFile[i],
fw, ftpClient1) ).start();
}
// ftpClient1.disconnect();
}
/**
*
* @param rootName 获取的根目录的路径
* @param ftpFile 该目录的文档列表
*/
private static void done_zzuFTP(String rootName, FTPFile ftpFile,
FileWriter fw, FileTransferClient ftpClient){
//获得文件的类型说明
String[] fields = split(ftpFile.getRaw());
if(fields[2].equalsIgnoreCase("<DIR>")){ try {
fw.append("Dir: " + rootName +
System.getProperty("line.separator"));
} catch (IOException e) {
e.printStackTrace();
}
FTPFile[] tmpFile;
try {
tmpFile = ftpClient.directoryList(rootName);
//递归下载子目录的内容
for(FTPFile file : tmpFile){
done_zzuFTP(rootName + "/" +
file.getName(), file, fw, ftpClient);
}
} catch (FTPException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}else {
try {
fw.append(" File: " + "+" +
ftpFile.getName() +
System.getProperty("line.separator"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
//该方法在com.enterprisedt.net.ftp.FTPFileParser里面,也可以将类直接继承FTPFileParser类
protected static String[] split(String str) {
String[] fields = new String[MAX_FIELDS];
int pos = 0;
StringBuffer field = new StringBuffer();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (!Character.isWhitespace(ch))
field.append(ch);
else {
if (field.length()> 0) {
fields[pos++] = field.toString();
field.setLength(0);
}
}
}
// pick up last field
if (field.length() > 0) {
fields[pos++] = field.toString();
}
String[] result = new String[pos];
System.arraycopy(fields, 0, result, 0, pos);
return result;
}
}
不知道你在那做的ftpClient1.disconnect();操作?
可是我没有结束线程的操作啊。com.enterprisedt库在这个网址下载,开源的。
http://www.enterprisedt.com/products/edtftpj/downloadlink.html其他的代码是完整的,测试的话,服务器地址需要自己建立本地或其他的地址了。