郑文亮
专心地钻研编程,每天进步一点点

  • 博客园
  • 首页
  • 新随笔
  • 联系
  • 管理
随笔-1610  文章-3  评论-570 

Java+Windows+ffmpeg实现视频转换

最近由于项目需要,研究了一下如何用Java实现视频转换,“着实”废了点心思,整理整理,写出给自己备忘下。

思路

由于之前没有没法过相关功能的经验,一开始来真不知道从哪里入手。当然,这个解决,google一下立马就发现了ffmpeg,网上讲解用Java+ffmpeg来进行视频转换的文章也不在少数,我主要参考的这篇文章。

上文提到的这篇文章,基本已经把开发流程什么的讲的很清楚了,这里总结下:

1)核心是利用ffmpeg进行视频转换,我们自己并不写转换视频的代码,只是调用ffmpeg,它会帮我们完成视频的转换。ffmpeg支持的类型有:asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等,这些类型,可以利用ffmpeg进行直接转换。ffmpeg不支持的类型有:wmv9,rm,rmvb等,这些类型需要先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式。

2)了解Java如何调用外部程序,这会是最困难的,也会是坑最多的地方。

3)根据我们的需求设置ffmpeg的参数。(这类文章网上已经有很多了,我也不用复制黏贴了,见这里)

代码

上文中提到的那篇文章中的代码其实已经写的很友好了,基本拿来就能用,不过仍然存在许多问题,接下来会讲到,下面是文中的代码:

  1 import java.io.File;  2 import java.util.ArrayList;  3 import java.util.Calendar;  4 import java.util.List;  5   6 public class ConvertVideo {  7   8     private final static String PATH = "c:\\ffmpeg\\input\\c.mp4";  9   10     public static void main(String[] args) {  11         if (!checkfile(PATH)) {  12             System.out.println(PATH + " is not file");  13             return;  14         }  15         if (process()) {  16             System.out.println("ok");  17         }  18     }  19   20     private static boolean process() {  21         int type = checkContentType();  22         boolean status = false;  23         if (type == 0) {  24             System.out.println("直接将文件转为flv文件");  25             status = processFLV(PATH);// 直接将文件转为flv文件  26         } else if (type == 1) {  27             String avifilepath = processAVI(type);  28             if (avifilepath == null)  29                 return false;// avi文件没有得到  30             status = processFLV(avifilepath);// 将avi转为flv  31         }  32         return status;  33     }  34   35     private static int checkContentType() {  36         String type = PATH.substring(PATH.lastIndexOf(".") + 1, PATH.length())  37                 .toLowerCase();  38         // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)  39         if (type.equals("avi")) {  40             return 0;  41         } else if (type.equals("mpg")) {  42             return 0;  43         } else if (type.equals("wmv")) {  44             return 0;  45         } else if (type.equals("3gp")) {  46             return 0;  47         } else if (type.equals("mov")) {  48             return 0;  49         } else if (type.equals("mp4")) {  50             return 0;  51         } else if (type.equals("asf")) {  52             return 0;  53         } else if (type.equals("asx")) {  54             return 0;  55         } else if (type.equals("flv")) {  56             return 0;  57         }  58         // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),  59         // 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.  60         else if (type.equals("wmv9")) {  61             return 1;  62         } else if (type.equals("rm")) {  63             return 1;  64         } else if (type.equals("rmvb")) {  65             return 1;  66         }  67         return 9;  68     }  69   70     private static boolean checkfile(String path) {  71         File file = new File(path);  72         if (!file.isFile()) {  73             return false;  74         }  75         return true;  76     }  77   78     // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.  79     private static String processAVI(int type) {  80         List<String> commend = new ArrayList<String>();  81         commend.add("c:\\ffmpeg\\mencoder");  82         commend.add(PATH);  83         commend.add("-oac");  84         commend.add("lavc");  85         commend.add("-lavcopts");  86         commend.add("acodec=mp3:abitrate=64");  87         commend.add("-ovc");  88         commend.add("xvid");  89         commend.add("-xvidencopts");  90         commend.add("bitrate=600");  91         commend.add("-of");  92         commend.add("avi");  93         commend.add("-o");  94         commend.add("c:\\ffmpeg\\output\\a.avi");  95         try {  96             ProcessBuilder builder = new ProcessBuilder();  97             builder.command(commend);  98             builder.start();  99             return "c:\\ffmpeg\\output\\a.avi";
100         } catch (Exception e) {
101             e.printStackTrace();
102             return null;
103         }
104     }
105
106     // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
107     private static boolean processFLV(String oldfilepath) {
108
109         if (!checkfile(PATH)) {
110             System.out.println(oldfilepath + " is not file");
111             return false;
112         }
113
114         // 文件命名
115         Calendar c = Calendar.getInstance();
116         String savename = String.valueOf(c.getTimeInMillis())+ Math.round(Math.random() * 100000);
117         List<String> commend = new ArrayList<String>();
118         commend.add("c:\\ffmpeg\\ffmpeg");
119         commend.add("-i");
120         commend.add(oldfilepath);
121         commend.add("-ab");
122         commend.add("56");
123         commend.add("-ar");
124         commend.add("22050");
125         commend.add("-qscale");
126         commend.add("8");
127         commend.add("-r");
128         commend.add("15");
129         commend.add("-s");
130         commend.add("600x500");
131         commend.add("c:\\ffmpeg\\output\\a.flv");
132
133         try {
134             Runtime runtime = Runtime.getRuntime();
135             Process proce = null;
136             String cmd = "";
137             String cut = "     c:\\ffmpeg\\ffmpeg.exe   -i   "
138                     + oldfilepath
139                     + "   -y   -f   image2   -ss   8   -t   0.001   -s   600x500   c:\\ffmpeg\\output\\"
140                     + "a.jpg";
141             String cutCmd = cmd + cut;
142             proce = runtime.exec(cutCmd);
143             ProcessBuilder builder = new ProcessBuilder(commend);
144              builder.command(commend);
145             builder.start();
146
147             return true;
148         } catch (Exception e) {
149             e.printStackTrace();
150             return false;
151         }
152     }
153 }

接下来是我自己经过修改后的代码:

  1 import java.io.File;2 import java.io.IOException;3 import java.util.ArrayList;4 import java.util.Calendar;5 import java.util.List;6 public class ConvertVideo {7     8     private static String inputPath = "";9     10     private static String outputPath = "";11     12     private static String ffmpegPath = "";13     14     public static void main(String args[]) throws IOException {15         16         getPath();17         18         if (!checkfile(inputPath)) {19             System.out.println(inputPath + " is not file");20             return;21         }22         if (process()) {23             System.out.println("ok");24         }25     }26     27     private static void getPath() { // 先获取当前项目路径,在获得源文件、目标文件、转换器的路径28         File diretory = new File("");29         try {30             String currPath = diretory.getAbsolutePath();31             inputPath = currPath + "\\input\\test.wmv";32             outputPath = currPath + "\\output\\";33             ffmpegPath = currPath + "\\ffmpeg\\";34             System.out.println(currPath);35         }36         catch (Exception e) {37             System.out.println("getPath出错");38         }39     }40     41     private static boolean process() {42         int type = checkContentType();43         boolean status = false;44         if (type == 0) {45             System.out.println("直接转成flv格式");46             status = processFLV(inputPath);// 直接转成flv格式47         } else if (type == 1) {48             String avifilepath = processAVI(type);49             if (avifilepath == null)50                 return false;// 没有得到avi格式51             status = processFLV(avifilepath);// 将avi转成flv格式52         }53         return status;54     }55 56     private static int checkContentType() {57         String type = inputPath.substring(inputPath.lastIndexOf(".") + 1, inputPath.length())58                 .toLowerCase();59         // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)60         if (type.equals("avi")) {61             return 0;62         } else if (type.equals("mpg")) {63             return 0;64         } else if (type.equals("wmv")) {65             return 0;66         } else if (type.equals("3gp")) {67             return 0;68         } else if (type.equals("mov")) {69             return 0;70         } else if (type.equals("mp4")) {71             return 0;72         } else if (type.equals("asf")) {73             return 0;74         } else if (type.equals("asx")) {75             return 0;76         } else if (type.equals("flv")) {77             return 0;78         }79         // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),80         // 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.81         else if (type.equals("wmv9")) {82             return 1;83         } else if (type.equals("rm")) {84             return 1;85         } else if (type.equals("rmvb")) {86             return 1;87         }88         return 9;89     }90 91     private static boolean checkfile(String path) {92         File file = new File(path);93         if (!file.isFile()) {94             return false;95         }96         return true;97     }98 99     // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
100     private static String processAVI(int type) {
101         List<String> commend = new ArrayList<String>();
102         commend.add(ffmpegPath + "mencoder");
103         commend.add(inputPath);
104         commend.add("-oac");
105         commend.add("lavc");
106         commend.add("-lavcopts");
107         commend.add("acodec=mp3:abitrate=64");
108         commend.add("-ovc");
109         commend.add("xvid");
110         commend.add("-xvidencopts");
111         commend.add("bitrate=600");
112         commend.add("-of");
113         commend.add("avi");
114         commend.add("-o");
115         commend.add(outputPath + "a.avi");
116         try {
117             ProcessBuilder builder = new ProcessBuilder();
118             Process process = builder.command(commend).redirectErrorStream(true).start();
119             new PrintStream(process.getInputStream());
120             new PrintStream(process.getErrorStream());
121             process.waitFor();
122             return outputPath + "a.avi";
123         } catch (Exception e) {
124             e.printStackTrace();
125             return null;
126         }
127     }
128
129     // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
130     private static boolean processFLV(String oldfilepath) {
131
132         if (!checkfile(inputPath)) {
133             System.out.println(oldfilepath + " is not file");
134             return false;
135         }
136
137         List<String> command = new ArrayList<String>();
138         command.add(ffmpegPath + "ffmpeg");
139         command.add("-i");
140         command.add(oldfilepath);
141         command.add("-ab");
142         command.add("56");
143         command.add("-ar");
144         command.add("22050");
145         command.add("-qscale");
146         command.add("8");
147         command.add("-r");
148         command.add("15");
149         command.add("-s");
150         command.add("600x500");
151         command.add(outputPath + "a.flv");
152
153         try {
154
155             // 方案1
156 //            Process videoProcess = Runtime.getRuntime().exec(ffmpegPath + "ffmpeg -i " + oldfilepath
157 //                    + " -ab 56 -ar 22050 -qscale 8 -r 15 -s 600x500 "
158 //                    + outputPath + "a.flv");
159
160             // 方案2
161             Process videoProcess = new ProcessBuilder(command).redirectErrorStream(true).start();
162
163             new PrintStream(videoProcess.getErrorStream()).start();
164
165             new PrintStream(videoProcess.getInputStream()).start();
166
167             videoProcess.waitFor();
168
169             return true;
170         } catch (Exception e) {
171             e.printStackTrace();
172             return false;
173         }
174     }
175 }
176
177 class PrintStream extends Thread
178 {
179     java.io.InputStream __is = null;
180     public PrintStream(java.io.InputStream is)
181     {
182         __is = is;
183     }
184
185     public void run()
186     {
187         try
188         {
189             while(this != null)
190             {
191                 int _ch = __is.read();
192                 if(_ch != -1)
193                     System.out.print((char)_ch);
194                 else break;
195             }
196         }
197         catch (Exception e)
198         {
199             e.printStackTrace();
200         }
201     }
202 }

问题

原文的代码中有一个很大的问题,便是不知道视频转换到底什么时候结束。看原文中的这两处代码:

98行处

1 builder.command(commend);
2 builder.start();
3 return "c:\\ffmpeg\\output\\a.avi"; 

145行处

1 builder.start();
2
3 return true;

在进程开始之后,直接就返回结果了。要知道,这样的写法,是不会阻塞当前进程的,也就是说,当然程序返回的时候,转码程序(ffmpeg和mencoder)还在执行。如果需要mencoder进行中间转码,那原文中的写法会造成在avi文件还未转换完成时,程序就调用了ffmpeg进行转换。而对于最终的flv文件,我们也无法知道到底是什么时候转换好的,这显然是无法满足我们的业务需求的 。

解决方案

最先想到的办法自然就是阻塞当前进程(主进程),实例代码:

1 Process process = new ProcessBuilder(command).start();
2 process.waitFor();
3 return true;

采用这种的方案运行程序,发现视频转到十几秒的时候就不转了,但是程序还没返回,打开进程管理器一开,ffmpeg进程还在,内存还占着,但是CPU为0,如图:

当时不知道什么原因,在网上查了半天,才明白这是死锁了,但是不知道是什么原因造成的。当时就一直觉得死锁是waitFor()函数造成了,看来用它来判断子进程是否结果是不行了,所以又在网上查了半天其他判断子进程结束的办法(这里其实就已经走弯路了)。有人说可以用exitValue(),于是就有了下面的代码:

 1 Process process = new ProcessBuilder(command).start();2 while (true) {3     try {4         if (process.exitValue() == 0)5             break;6     }7     catch (IllegalThreadStateException e) {8         continue;9     }
10 }
11 return true;

当子进程没有结束的时候,如果执行exitValue()就会抛出异常,我采用的办法是捕获这个异常然后不去理他,直到程序结束exitValue()返回0为止。但是,还是失败了,出现的情况和用waitFor()方式时的一模一样,我才觉得可能是另外的原因,在去google,发现可能是是由于JVM只提供有限缓存空间,当外部程序(子进程)的输出流超出了这个有限空间而父进程又不读出这些数据,子进程会被阻塞waitFor()永远都不会返回,就会造成死锁。

官方解释:

Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

知道问题了就要对症下药(其实当时我也不知道这是不是就是我遇到的问题,只能各种打散弹了,打中了算)。关于如何读出子进程的输出流,如何解决这个死锁,网上的办法都大同小异,写的比较好的可以看这个地址。

于是程序被改成这样:

1 Process process = new ProcessBuilder(command).start();
2
3 new PrintStream(process.getInputStream()).start();
4
5 process.waitFor();

PrintStream类如下:

 1 class PrintStream extends Thread 2 {3     java.io.InputStream __is = null;4     public PrintStream(java.io.InputStream is) 5     {6         __is = is;7     } 8 9     public void run()
10     {
11         try
12         {
13             while(this != null)
14             {
15                 int _ch = __is.read();
16                 if(_ch != -1)
17                     System.out.print((char)_ch);
18                 else break;
19             }
20         }
21         catch (Exception e)
22         {
23             e.printStackTrace();
24         }
25     }
26 }

运行,发现还是不对,症状和之前的一模一样,我还以为是不是输出流太多了,一个线程读的不够快(好吧,真的很傻很天真,人被逼急了真的什么想法都有),于是我就再开了几个一模一样的线程,结果还是一样。

就在我快要放弃的时候,在百度知道上,看了个无关痛痒的例子,于是做了个小修改,在进程启动之前,重定向了下错误输出流,如下:

1 Process videoProcess = new ProcessBuilder(command).redirectErrorStream(true).start();
2
3 new PrintStream(videoProcess.getInputStream()).start();
4
5 videoProcess.waitFor();
6
7 return true;

然后,然后,然后就可以了,凌乱。。。

结论

其实有两种写法可以解决这个问题,这种事像我上面那样写,还有一种如下:

1 Process videoProcess = new ProcessBuilder(command).start();
2
3 new PrintStream(videoProcess.getErrorStream()).start();
4
5 new PrintStream(videoProcess.getInputStream()).start();
6
7 videoProcess.waitFor();
8
9 return true;

其实道理还是一样的,就是读出ffmpeg的输出流,避免ffmpeg的输出流塞满缓存造成死锁。但是不知道为什么,ffmpeg的输出信息是在错误输出流里面的,我看了下控制台打印结果,发现只是一些当前转换状态的信息,并没有错误,令人费解。

在Process类中,getInputStream用来获取进程的输出流,getOutputStream用来获取进程的输入流,getErrorStream用来获取进程的错误信息流。为了保险起见,在读出的时候,最好把子进程的输出流和错误流都读出来,这样可以保证清空缓存区。

其实,我深刻地感觉到,这些解决的问题的经历是标准的散弹式编程,打到哪算哪,以后引以为戒。

分类:JAVA
好文要顶关注我收藏该文

郑文亮

关注 - 12

粉丝 - 917

+加关注

0
0

« 上一篇:捕获和冒泡

» 下一篇:sqlserver2014内存数据库特性介绍

posted @2015-07-23 14:49郑文亮阅读(7149) 评论(1)编辑收藏

#1楼2018-02-05 17:00大漠飞鱼

请问博主会实时视频流视频转码么?将捕获到的摄像头视频转码之后再到页面播放。
支持(0)反对(0)

刷新评论刷新页面返回顶部
【推荐】超50万VC++源码: 大型工控、组态\仿真、建模CAD源码2018!

【活动】杭州云栖·2050大会-全世界年青人因科技而团聚-源点

【抢购】新注册用户域名抢购1元起
最新IT新闻:

·《旅行青蛙》将推出官方中文版:或和国内巨头合作

·谷歌要在硅谷地区打造新园区,当地居民担忧房价涨

·支付宝300里程可兑换红包:最高500元

·微信上线新功能:发票查验一键完成

·中兴AXON M图赏:双屏秒变平板

»更多新闻...
最新知识库文章:

·写给自学者的入门指南

·和程序员谈恋爱

·学会学习

·优秀技术人的管理陷阱

·作为一个程序员,数学对你到底有多重要

»更多知识库文章...

历史上的今天:

2014-07-23跟我一起玩转Sencha Touch 移动 WebApp 开发(一)

2013-07-23Hibernate的查询 HQL查询 查询某几列

2013-07-23BoneCP学习笔记

2011-07-23Android使用ksoap2调用C#webservice体会(转)

公告

昵称:郑文亮

园龄:7年

粉丝:917

关注:12

+加关注

< 2018年3月 >
25 26 27 28 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
1 2 3 4 5 6 7

随笔分类(1704)

  • Asp.Net(133)
  • asp.net MVC(19)
  • c#(54)
  • c# winform(17)
  • flash/flex(14)
  • Hadoop(16)
  • JAVA(106)
  • Json(9)
  • Jsp(9)
  • Linux(centos)(43)
  • Linux(ubuntu)(16)
  • lucene(34)
  • Microsoft Ajax
  • nginx(3)
  • node.js(1)
  • Others(45)
  • Phonegap/jQueryMobile(20)
  • phonejs(1)
  • PHP(30)
  • PowerBuild(5)
  • Python(16)
  • redis(3)
  • SharePoint
  • silverlight(1)
  • SmartGwt(16)
  • UML(3)
  • visual c++(73)
  • WCF(7)
  • webApp(1)
  • WebServices(7)
  • WF
  • WPF
  • 操作系统(44)
  • 辅助工具(7)
  • 架构设计(6)
  • 敏捷开发(2)
  • 苹果机器用(2)
  • 前台ExtJs(42)
  • 前台HTML/CSS(116)
  • 前台html5(26)
  • 前台javascript(117)
  • 前台jQuery(65)
  • 手机开发(Android)(180)
  • 手机开发(flash)(4)
  • 手机开发(iPhone)(196)
  • 数据库HBase(10)
  • 数据库MongoDb(17)
  • 数据库Mysql(14)
  • 数据库oracle(33)
  • 数据库SqlServer(28)
  • 随想(18)
  • 淘宝网(18)
  • 微信开发(3)
  • 物联网(20)
  • 项目管理(10)
  • 需要补充的(2)
  • 移动黄页(12)
  • 质量保证QA(10)

随笔档案(1610)

  • 2018年1月 (1)
  • 2017年3月 (1)
  • 2016年4月 (1)
  • 2016年3月 (1)
  • 2016年2月 (1)
  • 2016年1月 (2)
  • 2015年12月 (8)
  • 2015年11月 (11)
  • 2015年10月 (2)
  • 2015年9月 (5)
  • 2015年8月 (7)
  • 2015年7月 (16)
  • 2015年6月 (11)
  • 2015年5月 (7)
  • 2015年4月 (15)
  • 2015年3月 (13)
  • 2015年2月 (16)
  • 2015年1月 (1)
  • 2014年12月 (6)
  • 2014年11月 (6)
  • 2014年9月 (1)
  • 2014年7月 (56)
  • 2014年6月 (8)
  • 2014年5月 (51)
  • 2014年4月 (78)
  • 2014年3月 (57)
  • 2014年2月 (8)
  • 2014年1月 (39)
  • 2013年12月 (30)
  • 2013年11月 (23)
  • 2013年10月 (27)
  • 2013年9月 (18)
  • 2013年8月 (14)
  • 2013年7月 (32)
  • 2013年6月 (27)
  • 2013年5月 (1)
  • 2013年4月 (13)
  • 2013年3月 (19)
  • 2013年2月 (17)
  • 2013年1月 (55)
  • 2012年12月 (51)
  • 2012年11月 (86)
  • 2012年10月 (16)
  • 2012年9月 (13)
  • 2012年8月 (33)
  • 2012年7月 (47)
  • 2012年6月 (17)
  • 2012年5月 (31)
  • 2012年4月 (21)
  • 2012年3月 (105)
  • 2012年2月 (82)
  • 2012年1月 (19)
  • 2011年12月 (45)
  • 2011年11月 (29)
  • 2011年10月 (21)
  • 2011年9月 (32)
  • 2011年8月 (42)
  • 2011年7月 (42)
  • 2011年6月 (17)
  • 2011年5月 (6)
  • 2011年4月 (40)
  • 2011年3月 (55)
  • 2011年2月 (55)

HTML

  • android学习网址
  • asp.net网站开发
  • asp.net学习网站
  • c++
  • c语言教程
  • Flex中文视频教程
  • Gis系统
  • iPhone多视图开发案例纪实
  • iphone开发
  • iphone开发学习网址
  • iphone视频教程
  • JQuery操作cookie插件
  • js用法
  • sqlserver 视频学习
  • 关于地图
  • 网页知识
  • 学习HTML:iframe用法总结收藏
  • 学习Html的好地方(w3school)
  • 英语学习

javaweb中ffmpeg视频转码h264出现卡住不执行的解决办法(看到最后面就是答案了)相关推荐

  1. Android FFmpeg视频转码并保存到本地

    本文讲述在Android中, 如何将FFmpeg视频转码为YUV格式并保存到本地. 首先,我们基于上一篇文章 基于Android Studio3.2实现ffmpeg最简单的例子 来进行配置. 配置好之 ...

  2. java用ffmpeg转码_java运用FFMPEG视频转码技术.doc

    java运用FFMPEG视频转码技术 基于windows系统安装FFMPEG转码技术 软件特点: 被转视频基本不失真(支持超清.高清.标清): 转码速度比较现成转码软件快非常多(不管文件有多大,此软件 ...

  3. nodejs+ffmpeg视频转码

    nodejs+ffmpeg视频转码 const context = require("../core/node_core_ctx"); const {spawn,exec} =re ...

  4. 电脑摄像头未能创建连接服务器,电脑提示未能创建视频预览,请检查设备连接的原因及解决办法...

    电脑提示"未能创建视频预览,请检查设备连接"的原因及解决办法 发布时间:2012-05-29 10:49:26   作者:佚名   我要评论 不知道大家有没有遇到这样的情况,当打开 ...

  5. IOS 开发中 Whose view is not in the window hierarchy 错误的解决办法

    在 IOS 开发当中经常碰到 whose view is not in the window hierarchy 的错误,该错误简单的说,是由于 "ViewController" ...

  6. Pycharm中无法导入各种Python模块,pip不能更新的解决办法

    一.Pycharm中无法导入各种Python模块,pip不能更新的解决办法 1.先用python -m pip uninstall pip 将之前版本的pip卸载 2.在官网上下载pip压缩包,记得下 ...

  7. eclipse项目中关于导入的项目里提示HttpServletRequest 不能引用的解决办法

    eclipse项目中关于导入的项目里提示HttpServletRequest 不能引用的解决办法  当使用eclipse导入外部的web工程时,有时会提示HttpServletRequest, Ser ...

  8. 关于Win10 64位Cadence16.6中OrCAD Capture CIS导网表出现ERROR无效指针的解决办法

    ** 关于Win10 64位Cadence16.6中OrCAD Capture CIS导网表出现ERROR无效指针的解决办法 ***背景:在第一次使用Cadence原理图导网表,结果出现报错,PCB ...

  9. 在word中利用Endnote导入文献时提示“无法编辑range”的解决办法-基本上通过以下方法都可以解决

    在word中利用Endnote导入文献时提示"无法编辑range"的解决办法 注意:在处理这个问题之前,请复制word以备份我们要处理的word文件,否则后期如果我们调整了word ...

最新文章

  1. 小组级git服务器搭建
  2. 在Linux系统下查看ora错误
  3. 文件目录遍历的并发算法
  4. 物联网软件IoT.js、JerryScript、Smart.js、Calvin介绍
  5. linux access
  6. 并发下,使用redis防止数据重复插入(数据库未对表字段设置唯一情况下)
  7. C++中字符数组和字符串string
  8. 电脑能正常上网上网,某些软件不能上网
  9. 定了,6大领域93个开源任务,阿里开源导师带你参与中科院开源之夏2022
  10. 项目管理知识体系指南(十)项目风险管理
  11. qq发文件大小上限_QQ邮箱上传附件一般有限制吗?最大能发送多大的文件
  12. 那些堪比照片质感的PhotoRealistic Style Transfer系列
  13. 父爱如山,催泪微电影感动全网
  14. 【转】Web 设计中最常用的 10 种色调以及它们的示例
  15. Windows 8 的程序兼容性助手方案详述
  16. python里row是什么意思_row python
  17. 虚拟机 Ubuntu 14.04 LTS (64 bits) 下安装 Kurento v6 并运行 kurento-hello-world
  18. 用find在html中找字符串,Windows CMD中 find命令(字符串查找)
  19. 玩转论坛营销巧获永久自然流量
  20. 这是一份全面详细的Android 车载系统开发入门指南

热门文章

  1. Android专项测试性能篇整理
  2. UNIX编程艺术感觉这本书,挺好的,不知道大家看过没呢?
  3. c++ 旅行家的预算
  4. javaWeb重定向
  5. 基于51单片机的实时多任务操作系统(RTX51)使用教程
  6. opnet学习001,入门的好例子
  7. BSCI认证的相关认知
  8. @Autowired @Resource @Qualifier的区别
  9. Coding代码使用教程
  10. 数据库的多表连接查询 emp表,dept表,salgrade表