🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
1. Runtime.getRuntime().exec(cmd) > 1. 这个方法执行外部命令,会生成一个新的进程去运行调用的程序,并返回一个java.lang.Process对象,该对象可以得到之前开启的进程的运行结果,还可以操作进程的输入输出流。 > 2. 注意在被调用脚本中,其中的一些路径问题,有的时候在脚本的环境中,配置的路径执行可能没问题,在调用时某些配置文件不写全路径可能出现问题 ~~~ package JPythons; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * Created by dailin on 2017/11/6. */ public class JavaCallPython { /** * * @param file 脚本路径 * @param param 调用脚本函数 * @throws IOException */ public void callPython(String file,String param) throws IOException { String cmd = "python " + file + " " + param; Process proc=Runtime.getRuntime().exec(cmd); //执行py文件 InputStreamReader stdin=new InputStreamReader(proc.getInputStream(),"GBK"); BufferedReader input = new BufferedReader(stdin); String line = null; while((line=input.readLine())!=null ){ System.out.println(line);//得到输出 } } } ~~~ 2. Process对象有以下几个方法: > 1. destroy()      杀死这个子进程 > 2. exitValue()      得到进程运行结束后的返回状态 > 3. waitFor()       得到进程运行结束后的返回状态,如果进程未运行完毕则等待知道执行完毕 > 4. getInputStream()  得到进程的标准输出信息流 > 5. getErrorStream()  得到进程的错误输出信息流 > 6. getOutputStream() 得到进程的输入流 > 现在来讲讲exitValue(),当线程没有执行完毕时调用此方法会跑出IllegalThreadStateException异常,最直接的解决方法就是用waitFor()方法代替。 > 但是waitFor()方法也有很明显的弊端,因为java程序给进程的输出流分配的缓冲区是很小的,有时候当进程输出信息很大的时候回导致缓冲区被填满,如果不及时处理程序会阻塞。如果程序没有对进程的输出流处理的会就会导致执行exec()的线程永远阻塞,进程也不会执行下去直到输出流被处理或者java程序结束。 > 解决的方法就是处理缓冲区中的信息,开两个线程分别去处理标准输出流和错误输出流。 public class ExecTest { public static void main(String[] args) throws IOException, InterruptedException {   String cmd = "cmd /c dir c:\\windows";   final Process process = Runtime.getRuntime().exec(cmd);   printMessage(process.getInputStream());   printMessage(process.getErrorStream());   int value = process.waitFor();   System.out.println(value); } private static void printMessage(final InputStream input) {   new Thread(new Runnable() {   public void run() {     Reader reader = new InputStreamReader(input);     BufferedReader bf = new BufferedReader(reader);     String line = null;     try {     while((line=bf.readLine())!=null) {     System.out.println(line);     }     } catch (IOException e) {     e.printStackTrace();     }  }   }).start(); } } > 如上程序,读取进程的输出信息并打印到控制台就不会发生阻塞,程序能正常的结束。cmd命令不能需要加上cmd /c才能执行,不然java会去path中找dir.exe.在windows一般字符集编码为GBK,需要在转换成Reader的时候指定为GBK编码. 2. python脚本 ~~~ #coding=utf-8 import redis import re from config import * from fdfs_client.client import * import pymysql import traceback # 先把fastdfs导入到本地文件列表 def allFiles(): path = FDFS_STOREPATH rounds = 1 fdfspath = 'group1/M00' with open(LOCAL_FILE,'w') as file_url: for dirpath, dirnames, filenames in os.walk(path): if rounds == 1: rounds+=1 elif (dirpath == path + '/sync'): continue else: for file in filenames: try: paths = re.search(REGEX,dirpath).group(1) fullpath = os.path.join(fdfspath + paths, file) print(fullpath) file_url.write(fullpath + '\n') except: pass rounds+=1 file_url.close() # 把本地文件导入到Redis def toRedis(): redis_client = getRedisClient() with open(LOCAL_FILE, 'r') as logfile: for line in logfile: print(line) redis_client.sadd(FDFS_REDIS_KEY,line.replace('\n', '')) logfile.close() # 直接把fastdfs数据导入到Redis def allFilesToRedis(): redis_client = getRedisClient() path = FDFS_STOREPATH rounds = 1 fdfspath = 'group1/M00' for dirpath, dirnames, filenames in os.walk(path): if rounds == 1: rounds += 1 elif (dirpath == path + '/sync'): continue else: for file in filenames: try: paths = re.search(REGEX, dirpath).group(1) fullpath = os.path.join(fdfspath + paths, file) print(fullpath) redis_client.sadd(FDFS_REDIS_KEY,fullpath) except: pass rounds += 1 # 求交集,并保存为一个set def intersection(): print('==========求交集==========') redis_client = getRedisClient() redis_client.sinterstore(SINTER_KEY,FDFS_REDIS_KEY,MYSQL_REDIS_KEY) # 求差集,并保存为一个set def difference(): redis_client = getRedisClient() redis_client.sdiffstore(DIFF_KEY,FDFS_REDIS_KEY,MYSQL_REDIS_KEY) def getRedisClient(): return redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT,password=REDIS_PASSWORD) # 从Redis中查询差集,并在fastdfs中删除文件 def deleteFdfs(): redis_client = getRedisClient() print('删除%s'%DIFF_KEY) results = redis_client.smembers(DIFF_KEY) fdfs_client = Fdfs_client(FDFS_CLIENT_CONF) print('1') for file in results: print('2') file_str = file.decode() print(file_str) fdfs_client.delete_file(file_str) def info(): client = getRedisClient() mysql_num = client.scard(MYSQL_REDIS_KEY) fdfs_num = client.scard(FDFS_REDIS_KEY) sinter_num = client.scard(SINTER_KEY) diff_num = client.scard(DIFF_KEY) print("mysql中图片:%d" %mysql_num) print("fastdfs中图片:%d" %fdfs_num) print("mysql与fastdfs交集中图片:%d" %sinter_num) print("mysql与fastdfs差集图片:%d" %diff_num) def mysqlToRedis(): db = pymysql.connect(MYSQL_HOST,MYSQL_USER,MYSQL_PASSWORD,MYSQL_DB) cursor = db.cursor() sql = ('select * from %s' %MYSQL_VIEW) redis_client = getRedisClient() try: cursor.execute(sql) results = cursor.fetchall() for row in results: url = row[0] if (len(url)!=0): print(url) redis_client.sadd(MYSQL_REDIS_KEY,url) except : traceback.print_exc() db.close() # if __name__ == '__main__': # if(sys.argv[1] == 'filetolocal'): # allFiles() # elif(sys.argv[1] == 'fdfs-toredis'): # allFilesToRedis() # elif(sys.argv[1] == 'sinter'): # intersection() # elif(sys.argv[1] == 'delete'): # deleteFdfs() # elif(sys.argv[1] == 'info'): # info() # elif(sys.argv[1] == 'diff'): # difference() # elif (sys.argv[1] == 'mysql-redis'): # mysqlToRedis() # else: # print("USAGE:filetolocal|fdfs-redis|sinter|diff|delete|mysql-redis|info") def main(): if (sys.argv[1] == 'filetolocal'): allFiles() elif (sys.argv[1] == 'fdfs-toredis'): allFilesToRedis() elif (sys.argv[1] == 'sinter'): intersection() elif (sys.argv[1] == 'delete'): deleteFdfs() elif (sys.argv[1] == 'info'): info() elif (sys.argv[1] == 'diff'): difference() elif (sys.argv[1] == 'mysql-redis'): mysqlToRedis() else: print("USAGE:filetolocal|fdfs-redis|sinter|diff|delete|mysql-redis|info") main() ~~~