`

FtpUtil ftp工具类 过滤文件名

    博客分类:
  • java
 
阅读更多

工具类:

 

 

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import sun.net.TelnetInputStream;
import sun.net.TelnetOutputStream;
import sun.net.ftp.FtpClient;
import sun.net.ftp.FtpLoginException;

public class FtpUtil {


	/**
	 * @param args
	 */
	public static void main(String[] args) {
		FtpUtil ftp = new FtpUtil();
		ftp.connect("10.16.12.75", 21, "ftpusr", "ftpusr");
		try {
			// 上传目录下文件 并可以递归到子目录
			// ftp.upPathFile(new File("D:\\ALSC"), "ALSC/");
			// 下载目录下多个文件 并可以递归到子目录
			//ftp.downPathFile("/opt/ftp/outgoing/cs/", "D:/outgoing/csvc");
			
			// 切换目录
			ftp.setPath("/opt/ftp/book");
			System.out.println(ftp.getDir());
			for (String file : ftp.getFileNameList()) {
				System.out.println(file);
			}

			// 切换到父级目录
			ftp.up();
			
			// 创建多目录
			// ftp.createDir("aa/bb/cc");
			ftp.setPath("ftpTest");
			
			// 删除文件
			ftp.deleteFile("bbb.bmp");
			System.out.println(ftp.getDir());
			for (String file : ftp.getFileNameList()) {
				System.out.println(file);
			}
			// 上传 下载单个文件
			ftp.uploadFile("c:/aaa.bmp", "bbb.bmp");
			ftp.downloadFile("bbb.bmp", "c:/bbb");

			List<String> list = ftp.getFileList();
			for (String file : list) {
				System.out.println(file);
			}

			ftp.setPath("/opt/ftp/outgoing/cs");
			String patternStr = "^CSGET_[0-9]{4}_0085_"+"20120926"+"_[0-9]{3}";
			// 过滤,获取目录下的文件列表
			list = ftp.getFileList(new CSFilter(patternStr));
			for (String file : list) {
				System.out.println(file);
			}
			
			//下载 过滤后的文件
			ftp.downPathFile("/opt/ftp/outgoing/cs/", "D:/outgoing/csvc",new CSFilter(patternStr));

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		ftp.close();
	}
	
	private FtpClient ftpClient = null;

	/**
	 * 打开连接
	 * 
	 * @param hostname
	 * @param port
	 * @param username
	 * @param passwd
	 * @return
	 */
	public void connect(String hostname, int port, String username,
			String passwd) {
		String msg = "";
		try {
			ftpClient = new FtpClient(hostname, port);
			ftpClient.login(username, passwd);
			ftpClient.binary();
			msg = "连接成功!";
		} catch (FtpLoginException e) {
			msg = "登录主机失败,可能是用户名密码错误!";
			e.printStackTrace();
		} catch (IOException e) {
			msg = "登录主机失败,请检验端品是否正确!";
			e.printStackTrace();
		} catch (SecurityException e) {
			msg = "无权连接主机,主确认是否有权限连接主机!";
			e.printStackTrace();
		}
		System.out.println(msg);
	}

	/**
	 * 关闭连接
	 */
	public void close() {
		if (ftpClient == null) {
			return;
		}
		try {
			ftpClient.closeServer();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 重命名
	 * 
	 * @param oldName
	 * @param newName
	 * @return
	 */
	public boolean renameFile(String oldName, String newName) {
		boolean result = false;
		try {
			this.ftpClient.rename(oldName, newName);
			result = true;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 取得相对于当前连接目录的某个目录下所有文件列表
	 * 
	 * @param path
	 * @return
	 */
	public List getFileList(String path) {
		List list = new ArrayList();
		DataInputStream dis;
		try {
			dis = new DataInputStream(ftpClient.nameList(this.getDir() + path));
			String filename = "";
			while ((filename = dis.readLine()) != null) {
				list.add(filename);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * 读取文件列表
	 * 
	 * @return
	 * @throws IOException
	 */
	public List<String> getFileList() throws IOException {
		List<String> fileList = new ArrayList<String>();
		InputStreamReader isr = null;
		BufferedReader br = null;
		try {
			isr = new InputStreamReader(this.ftpClient.list());
			br = new BufferedReader(isr);
			String fileName = "";
			while (true) {
				fileName = br.readLine();
				if (fileName == null) {
					break;
				}
				fileList.add(fileName);
			}
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (isr != null) {
				try {
					isr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return fileList;
	}

	/**
	 * 读取文件列表
	 * 
	 * @return
	 * @throws IOException
	 */
	public List<String> getFileList(FileFilter filter) throws IOException {
		List<String> fileList = new ArrayList<String>();
		InputStreamReader isr = null;
		BufferedReader br = null;
		try {
			isr = new InputStreamReader(this.ftpClient.list());
			br = new BufferedReader(isr);
			String fileName = "";
			while (true) {
				fileName = br.readLine();
				if (fileName == null) {
					break;
				}
				if ((filter == null) || filter.accept(new File(fileName)))
					fileList.add(fileName);
			}
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (isr != null) {
				try {
					isr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return fileList;
	}

	/**
	 * 获取文件名列表
	 * 
	 * @return
	 * @throws IOException
	 */
	public List<String> getFileNameList() throws IOException {
		List<String> fileNameList = new ArrayList<String>();
		InputStreamReader isr = null;
		BufferedReader br = null;
		try {
			isr = new InputStreamReader(this.ftpClient.nameList(this.getDir()));
			br = new BufferedReader(isr);

			String fileName = "";
			while (true) {
				fileName = br.readLine();
				if (fileName == null) {
					break;
				}
				fileNameList.add(fileName);
			}
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (isr != null) {
				try {
					isr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return fileNameList;

	}

	/**
	 * 设置路径 切换目录
	 * 
	 * @param path
	 * @return
	 */
	public boolean setPath(String path) {
		if (this.ftpClient != null) {
			try {
				ftpClient.cd(path);
				return true;
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
		} else {
			return false;
		}
	}

	/**
	 * 判断是否为目录
	 * 
	 * @param line
	 * @return
	 */
	public boolean isDir(String line) {
		return line.startsWith("d");
	}

	/**
	 * 检查文件夹在当前目录下是否存在
	 * 
	 * @param dir
	 * @return
	 */
	public boolean isDirExist(String dir) {
		String pwd = "";
		try {
			pwd = ftpClient.pwd();
			ftpClient.cd(dir);
			ftpClient.cd(pwd);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 获取当前路径
	 * 
	 * @return
	 * @throws IOException
	 */
	public String getDir() throws IOException {
		return this.ftpClient.pwd();
	}

	/**
	 * 向上 切换到父级目录
	 * 
	 * @throws IOException
	 */
	public void up() throws IOException {
		if ("/".equals(ftpClient.pwd()) || "//".equals(ftpClient.pwd())) {
			return;
		}
		this.ftpClient.cdUp();
	}

	/**
	 * 删除文件
	 * 
	 * @param fileName
	 * @return
	 */
	public void deleteFile(String fileName) {
		ftpClient.sendServer("dele " + fileName + "\r\n");// 这个地方一定要注意 加上 \r\n
		try {
			if (ftpClient.readServerResponse() != 250)
				System.out.println("删除异常");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 在当前目录下创建文件夹
	 * 
	 * @param dir
	 * @return
	 * @throws Exception
	 */
	public boolean createDir(String dir) {
		try {
			ftpClient.ascii();
			StringTokenizer s = new StringTokenizer(dir, "/"); // sign
			s.countTokens();
			String pathName = ftpClient.pwd();
			while (s.hasMoreElements()) {
				pathName = pathName + "/" + (String) s.nextElement();
				try {
					ftpClient.sendServer("MKD " + pathName + "\r\n");
				} catch (Exception e) {
					e = null;
					return false;
				}
				ftpClient.readServerResponse();
			}
			ftpClient.binary();
			return true;
		} catch (IOException e1) {
			e1.printStackTrace();
			return false;
		}
	}

	/**
	 * 上传文件
	 * 
	 * @param localFile
	 * @param targetFileName
	 * @return
	 */
	public boolean uploadFile(String localFile, String targetFileName) {
		boolean result = false;
		if (this.ftpClient == null) {
			return false;
		}
		TelnetOutputStream tos = null;
		RandomAccessFile sendFile = null;
		DataOutputStream dos = null;
		try {
			File file = new File(localFile);
			sendFile = new RandomAccessFile(file, "r");
			sendFile.seek(0);
			tos = this.ftpClient.put(targetFileName);
			dos = new DataOutputStream(tos);
			int ch = 0;
			while (sendFile.getFilePointer() < sendFile.length()) {
				ch = sendFile.read();
				dos.write(ch);
			}
			result = true;
		} catch (Exception ex) {
			result = false;
		} finally {
			if (tos != null) {
				try {
					tos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (dos != null) {
				try {
					dos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (sendFile != null) {
				try {
					sendFile.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	/**
	 * 上传文件
	 * 
	 * @param localFile
	 * @param targetFileName
	 * @return
	 */
	public boolean uploadFile(File localFile, String targetFileName) {
		boolean result = false;
		if (this.ftpClient == null) {
			return false;
		}
		TelnetOutputStream tos = null;
		RandomAccessFile sendFile = null;
		DataOutputStream dos = null;
		try {
			sendFile = new RandomAccessFile(localFile, "r");
			sendFile.seek(0);
			tos = this.ftpClient.put(targetFileName);
			dos = new DataOutputStream(tos);
			int ch = 0;
			while (sendFile.getFilePointer() < sendFile.length()) {
				ch = sendFile.read();
				dos.write(ch);
			}
			result = true;
		} catch (Exception ex) {
			result = false;
		} finally {
			if (tos != null) {
				try {
					tos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (dos != null) {
				try {
					dos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (sendFile != null) {
				try {
					sendFile.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	/**
	 * 上传本地目录下的所有文件到服务器上
	 * 
	 * @param srcPath
	 * @param tagPath
	 * @param level
	 *            递归的级别
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
	public boolean upPathFile(File srcPathFile, String tagPath) {
		buildList(tagPath.substring(0, tagPath.lastIndexOf("/")));
		boolean result = true;

		try {
			File temp[] = srcPathFile.listFiles();
			for (int i = 0; i < temp.length; i++) {
				if (temp[i].isDirectory()) {
					if (tagPath.lastIndexOf('/') > 0) {
						result = upPathFile(temp[i], tagPath
								+ temp[i].getName() + "/");
					} else {
						result = upPathFile(temp[i], tagPath + "/"
								+ temp[i].getName() + "/");
					}
				} else {
					if (tagPath.lastIndexOf('/') > 0) {
						result = uploadFile(temp[i], tagPath
								+ temp[i].getName());
					} else {
						result = uploadFile(temp[i], tagPath + "/"
								+ temp[i].getName());
					}

				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * 下载文件
	 * 
	 * @param srcFileName
	 * @param targetFileName
	 * @return
	 */
	public boolean downloadFile(String srcFileName, String targetFileName) {
		if (this.ftpClient == null) {
			return false;
		}
		TelnetInputStream tis = null;
		RandomAccessFile getFile = null;
		boolean result = true;
		try {
			File file = new File(targetFileName);
			getFile = new RandomAccessFile(file, "rw");
			getFile.seek(0);
			tis = this.ftpClient.get(srcFileName);
			DataInputStream dis = new DataInputStream(tis);
			int ch = 0;
			while (true) {
				ch = dis.read();
				if (ch < 0) {
					break;
				}
				getFile.write(ch);
			}
			getFile.close();
		} catch (IOException e) {
			result = false;
		} finally {
			if (getFile != null) {
				try {
					getFile.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (tis != null) {
				try {
					tis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	/**
	 * 下载文件
	 * 
	 * @param srcFileName
	 * @param targetFileName
	 * @return
	 */
	public boolean downloadFile(String srcFileName, File targetFileName) {
		if (this.ftpClient == null) {
			return false;
		}
		TelnetInputStream tis = null;
		RandomAccessFile getFile = null;
		boolean result = true;
		try {
			getFile = new RandomAccessFile(targetFileName, "rw");
			getFile.seek(0);
			tis = this.ftpClient.get(srcFileName);
			DataInputStream dis = new DataInputStream(tis);
			int ch = 0;
			while (true) {
				ch = dis.read();
				if (ch < 0) {
					break;
				}
				getFile.write(ch);
			}
			getFile.close();
		} catch (IOException e) {
			result = false;
		} finally {
			if (getFile != null) {
				try {
					getFile.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (tis != null) {
				try {
					tis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	/**
	 * 下载远程目录下的所有文件到本地
	 * 
	 * @param srcPathFile
	 *            远程目录文件
	 * @param tagPath
	 *            本地存放目录
	 * @return
	 * @throws IOException
	 * @see [类、类#方法、类#成员]
	 */
	public boolean downPathFile(String srcPath, String tagPath)
			throws IOException {

		boolean result = true;

		File tagFile = new File(tagPath);
		tagFile.mkdirs();

		setPath(srcPath);
		String tempPath = "";
		List<String> list = getFileList();
		for (int i = 0; i < list.size(); i++) {
			String currPath = list.get(i);
			String fileName = getFileName(currPath);

			String currPathFul = getDir() + "/" + fileName;

			if (tagPath.lastIndexOf('/') > 0) {
				tempPath = tagPath
						+ currPathFul.substring(currPathFul.lastIndexOf("/"),
								currPathFul.length());
			} else {
				tempPath = tagPath
						+ "/"
						+ currPathFul.substring(currPathFul.lastIndexOf("/"),
								currPathFul.length());
			}

			if (isDir(currPath)) {
				srcPath = currPathFul + "/";
				downPathFile(srcPath, tempPath);
			} else {
				srcPath = currPathFul;
				downloadFile(srcPath, tempPath);
			}
		}

		return result;
	}

	/**
	 * 下载远程目录下的所有文件到本地,过滤规则
	 * 
	 * @param srcPathFile
	 *            远程目录文件
	 * @param tagPath
	 *            本地存放目录
	 * @param fileFilter
	 * 			  下载过滤文件
	 * @return
	 * @throws IOException
	 * @see [类、类#方法、类#成员]
	 */
	public boolean downPathFile(String srcPath, String tagPath,
			FileFilter fileFilter) throws IOException {

		boolean result = true;

		File tagFile = new File(tagPath);
		tagFile.mkdirs();

		setPath(srcPath);
		String tempPath = "";
		List<String> list = getFileList(fileFilter);
		for (int i = 0; i < list.size(); i++) {
			String currPath = list.get(i);
			String fileName = getFileName(currPath);

			String currPathFul = getDir() + "/" + fileName;

			if (tagPath.lastIndexOf('/') > 0) {
				tempPath = tagPath
						+ currPathFul.substring(currPathFul.lastIndexOf("/"),
								currPathFul.length());
			} else {
				tempPath = tagPath
						+ "/"
						+ currPathFul.substring(currPathFul.lastIndexOf("/"),
								currPathFul.length());
			}

			if (isDir(currPath)) {
				srcPath = currPathFul + "/";
				downPathFile(srcPath, tempPath, fileFilter);
			} else {
				srcPath = currPathFul;
				downloadFile(srcPath, tempPath);
			}
		}

		return result;
	}

	public String getFileName(String line) {
		int i;
		String filename = (String) parseLine(line).get(8);
		for (i = 9; i < parseLine(line).size(); i++) {
			filename = filename + " " + ((String) parseLine(line).get(i));
		}
		return filename;
	}

	// 处理getFileList取得的行信息
	private ArrayList parseLine(String line) {
		ArrayList s1 = new ArrayList();
		StringTokenizer st = new StringTokenizer(line, " ");
		while (st.hasMoreTokens()) {
			s1.add(st.nextToken());
		}
		return s1;
	}

	/**
	 * 从FTP文件服务器上下载文件SourceFileName,到本地destinationFileName 所有的文件名中都要求包括完整的路径名在内
	 * 
	 * @param SourceFileName
	 *            String
	 * @param destinationFileName
	 *            String
	 * @throws Exception
	 */
	public void downFile(String SourceFileName, String destinationFileName)
			throws Exception {
		ftpClient.binary(); // 一定要使用二进制模式
		TelnetInputStream ftpIn = ftpClient.get(SourceFileName);
		byte[] buf = new byte[204800];
		int bufsize = 0;
		FileOutputStream ftpOut = new FileOutputStream(destinationFileName);
		while ((bufsize = ftpIn.read(buf, 0, buf.length)) != -1) {
			ftpOut.write(buf, 0, bufsize);
		}
		ftpOut.close();
		ftpIn.close();
	}

	/**
	 * 从FTP文件服务器上下载文件,输出到字节数组中
	 * 
	 * @param SourceFileName
	 *            String
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] downFile(String SourceFileName) throws Exception {
		ftpClient.binary(); // 一定要使用二进制模式
		TelnetInputStream ftpIn = ftpClient.get(SourceFileName);
		ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
		byte[] buf = new byte[204800];
		int bufsize = 0;

		while ((bufsize = ftpIn.read(buf, 0, buf.length)) != -1) {
			byteOut.write(buf, 0, bufsize);
		}
		byte[] return_arraybyte = byteOut.toByteArray();
		byteOut.close();
		ftpIn.close();
		return return_arraybyte;
	}

	/**
	 * 上传文件到FTP服务器,destination路径以FTP服务器的"/"开始,带文件名、 上传文件只能使用二进制模式,
	 * 当文件存在时再次上传则会覆盖
	 * 
	 * @param source
	 *            String
	 * @param destination
	 *            String
	 * @throws Exception
	 */
	public void upFile(String source, String destination) throws Exception {
		buildList(destination.substring(0, destination.lastIndexOf("/")));
		ftpClient.binary(); // 此行代码必须放在buildList之后
		TelnetOutputStream ftpOut = ftpClient.put(destination);
		TelnetInputStream ftpIn = new TelnetInputStream(new FileInputStream(
				source), true);
		byte[] buf = new byte[204800];
		int bufsize = 0;
		while ((bufsize = ftpIn.read(buf, 0, buf.length)) != -1) {
			ftpOut.write(buf, 0, bufsize);
		}
		ftpIn.close();
		ftpOut.close();
	}

	/**
	 * JSP中的流上传到FTP服务器, 上传文件只能使用二进制模式,当文件存在时再次上传则会覆盖 字节数组做为文件的输入流,
	 * 此方法适用于JSP中通过request输入流来直接上传文件在RequestUpload类中调用了此方法,
	 * destination路径以FTP服务器的"/"开始,带文件名
	 * 
	 * @param sourceData
	 *            byte[]
	 * @param destination
	 *            String
	 * @throws Exception
	 */
	public void upFile(byte[] sourceData, String destination) throws Exception {
		buildList(destination.substring(0, destination.lastIndexOf("/")));
		ftpClient.binary(); // 此行代码必须放在buildList之后
		TelnetOutputStream ftpOut = ftpClient.put(destination);
		ftpOut.write(sourceData, 0, sourceData.length);
		// ftpOut.flush();
		ftpOut.close();
	}

	/**
	 * 在FTP服务器上建立指定的目录,当目录已经存在的情下不会影响目录下的文件,这样用以判断FTP
	 * 上传文件时保证目录的存在目录格式必须以"/"根目录开头
	 * 
	 * @param pathList
	 *            String
	 * @throws Exception
	 */
	public void buildList(String pathList) {
		try {
			ftpClient.ascii();

			StringTokenizer s = new StringTokenizer(pathList, "/"); // sign
			int count = s.countTokens();
			String pathName = "";
			while (s.hasMoreElements()) {
				pathName = pathName + (String) s.nextElement();
				try {
					ftpClient.sendServer("XMKD " + pathName + "\r\n");
				} catch (Exception e) {
					e = null;
				}
				int reply = ftpClient.readServerResponse();
				pathName = pathName + "/";
			}
			ftpClient.binary();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

}

 过滤:

 

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

public class CSFilter implements FileFilter {

	private String patternStr ;
	
	//"^CSGET_[0-9]{4}_0085_"+"20120926"+"_[0-9]{3}"
	private Pattern pattern ;

	public CSVCFilter(String str){
		this.patternStr = str;
		this.pattern = Pattern.compile(patternStr);
	}
	public boolean accept(File pathname) {
		String strName = pathname.getName();
		if (!isDir(strName)) {
			strName = getFileName(strName);
			System.out.println(strName);
			return pattern.matcher(strName).matches();
		}
		return true;
	}

	public boolean isDir(String strName) {
		return ((String) parseLine(strName).get(0)).indexOf("d") != -1;
	}

	public String getFileName(String line) {
		int i;
		String filename = (String) parseLine(line).get(8);
		for (i = 9; i < parseLine(line).size(); i++) {
			filename = filename + " " + ((String) parseLine(line).get(i));
		}
		return filename;
	}

	// 处理getFileList取得的行信息
	private ArrayList parseLine(String line) {
		ArrayList s1 = new ArrayList();
		StringTokenizer st = new StringTokenizer(line, " ");
		while (st.hasMoreTokens()) {
			s1.add(st.nextToken());
		}
		return s1;
	}

	public String getFileSize(String line) {
		return (String) parseLine(line).get(4);
	}

	public String getFileDate(String line) {
		ArrayList a = parseLine(line);
		return (String) a.get(5) + " " + (String) a.get(6) + " "
				+ (String) a.get(7);
	}

}

 

下载速度提升

 

public boolean downloadFile(String srcFileName, File targetFileName)
{
//.....

//下载速度太慢,用如下方式进行提升
                        byte[] recvbuf = new byte[1024];
			while((ch = dis.read(recvbuf)) > 0){
				getFile.write(recvbuf,0,ch);
			}

//			while (true) {
//				ch = dis.read();
//				if (ch < 0) {
//					break;
//				}
//				getFile.write(ch);
//			}



//...

}
 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics