【问题标题】:JAVA output of exe file(executed with ProcessBuilder) does not redirected to consoleexe 文件的 JAVA 输出(使用 ProcessBuilder 执行)未重定向到控制台
【发布时间】:2020-11-07 03:52:38
【问题描述】:

我正在为读取用户剪贴板的 Windows 制作 Java 控制台应用程序,如果内容是 https://youtube.com 链接,则使用 youtube-dl 将音频下载到 mp3 文件。

我尝试使用ProcessBuilder 下载视频并将其转换为音频,但始终无法将 youtube-dl.exe 的输出重定向到控制台。

package com.awidesky.YoutubeClipboardAutoDownlader;

import java.io.File;
import java.io.FilenameFilter;
import java.lang.ProcessBuilder.Redirect;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class YoutubeAudioDownloader {

    private static final String youtubedlpath = new File("").getAbsolutePath() + "\\resources\\ffmpeg\\bin"; //Thread.currentThread().getContextClassLoader().getResource("ffmpeg/bin").getPath();
    private static File downloadPath;
    
    static {
        
        if (!new File(youtubedlpath + "\\youtube-dl.exe").exists()) { throw new Error("youtube-dl.exe does not exist!"); }

    }
    
    static void download(String url, String path) throws Exception {
        
        downloadPath = new File(path);
        
        try {
            
            //Main.log(downloadPath.getAbsolutePath());
            ProcessBuilder pb = new ProcessBuilder(youtubedlpath + "\\youtube-dl", "-x", "--audio-format", "mp3", "--audio-quality", "0",  url);
            pb.directory(new File(youtubedlpath));
            Process p = pb.start();
            pb.redirectError(Redirect.INHERIT);
            pb.redirectOutput(Redirect.INHERIT);

            /*
             * Thread stdout = new Thread(() -> {
             * 
             * BufferedReader br = new BufferedReader(new
             * InputStreamReader(p.getInputStream())); String line = null;
             * 
             * try {
             * 
             * while((line = br.readLine ()) != null) {
             * 
             * Main.log(line);
             * 
             * }
             * 
             * } catch (IOException e) {
             * 
             * // TODO Auto-generated catch block Main.log(e.toString());
             * 
             * }
             * 
             * });
             * 
             * Thread stderr = new Thread(() -> {
             * 
             * BufferedReader br = new BufferedReader(new
             * InputStreamReader(p.getErrorStream())); String line = null;
             * 
             * try {
             * 
             * while((line = br.readLine ()) != null) {
             * 
             * Main.log(line);
             * 
             * }
             * 
             * } catch (IOException e) {
             * 
             * // TODO Auto-generated catch block Main.log(e.toString());
             * 
             * }
             * 
             * });
             * 
             * stdout.start(); stderr.start();
             */
             
            p.waitFor();
            
            
            //Thread.currentThread().sleep(100);
            
            Main.log("founding downloaded file...");
            
            File[] fileList = new File(youtubedlpath).listFiles(new FilenameFilter() {
                
                @Override
                public boolean accept(File dir, String name) {
                    // TODO Auto-generated method stub
                    return name.endsWith("mp3");
                }
                
            });
            
            if(fileList.length ==0 ) { throw new RuntimeException("Didn't dowload any files!"); }
            
            for(File f : fileList) {
                
                Files.copy(f.toPath(), Paths.get(downloadPath.getAbsolutePath() + "\\" + f.getName()) ,StandardCopyOption.REPLACE_EXISTING);
                Files.delete(f.toPath());
                
            }
            
            Main.log("Done!");
            
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        
    }
    
}

如果我从Process p 获得InputStreamReader 并使用两个Threads 和while 进行打印,我可以从eclipse 中获得正确的输出,但是当我使用java -jar YoutubeClipBoardAutoDownlaoder.jar 启动时我无法获得任何输出。

当我使用pb.redirectError(Redirect.INHERIT); pb.redirectOutput(Redirect.INHERIT); 时, eclipse 控制台和 Windows 控制台都没有输出。 我哪里做错了?

  • 项目的全部代码是here,下面是它的主类。
package com.awidesky.YoutubeClipboardAutoDownlader;

import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.FlavorListener;
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JFileChooser;
import javax.swing.JFrame;

/** Main class */
public class Main {

    private static ExecutorService executorService = Executors.newFixedThreadPool(1);
    private static boolean isOkToStart = false; /** I don't know why but when you copied something, <code>flavorsChanged</code> invoked twice and we should ignore the first one. */
    
    public static void main(String[] args) throws Exception {

        JFileChooser jfc = new JFileChooser();
        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        jfc.setDialogTitle("Choose directory for saving music!");
        jfc.showDialog(new JFrame(), null);
        File dir = jfc.getSelectedFile();
        
        Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(new FlavorListener() { 
        
                @Override 
                public void flavorsChanged(FlavorEvent e) {

                    if (!isOkToStart) { isOkToStart = true; return; } 

                    System.err.println("CLIPBOARD CHANGED");
                    
                    executorService.submit(() -> {
                        
                        try {
                        
                            Thread.sleep(100);
                            
                            String data = (String)Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
                    
                            if (data.startsWith("https://www.youtu")) {
                      
                                log("Receved a link from your clipboard : " + data);
                                YoutubeAudioDownloader.download(data, dir.getAbsolutePath());

                            }
                        
                        } catch(Exception err) {
                        
                            log(err.toString());
                        
                        }
               
                    });
                    
                    isOkToStart = !isOkToStart;
                    
                }
        
        });
        
        log("Listning clipboard...");
        
    }
    
    
    public static void log(String data) {
        
        System.out.println(data);
        
    }

}

你可能会问我...

  1. 你必须使用 youtuve-dl 吗?

    -不。我使用它的唯一原因是我没有找到更好的从 youtube.com 下载音频的方法。

  2. 为什么只使用一个线程池?

    -避免在事件线程中花费很长时间,我认为当我执行多个 youtuve-dl.exe 时进程会崩溃(虽然不确定)

【问题讨论】:

    标签: java windows io console windows-console


    【解决方案1】:

    我搜索了几个星期,终于找到了。问题不是 I/O,而是包装。 由于我将.exefile(youtube-dlfile)放入了我的jar,Java 无法找到该文件。
    我将资源文件夹放在 .jar 之外,它运行良好。
    但是我还是不明白为什么jvm没有给我'''Error'''或'''Exception'''。(可能是I/O的问题?)

    【讨论】:

      【解决方案2】:

      您应该在进程开始之前重定向输出。

              pb.redirectError(Redirect.INHERIT);
              pb.redirectOutput(Redirect.INHERIT);
              Process p = pb.start();
      

      【讨论】:

      • 输出在 Eclipse 中正确打印,但在我开始导出 jar 文件时却没有……我认为 youtube-dl.exe 根本没有执行。但是当我从 eclipse 运行它时它运行得很好!
      • 也许我应该发布另一个关于将带有二进制文件的 eclipse 项目导出到 .jar 文件的问题...?
      • 这很奇怪......当运行“java -jar xxx.jar”时,你能在控制台上看到其他“System.out.println”文本吗?如果可以,请在您的问题中添加控制台输出
      • 我得到了这样的控制台输出: Listening clipboard... (new line) CLIPBOARD CHANGED (new line) 从剪贴板收到一个链接:youtube.com/blablabla 因为我无法获得更多输出(包括来自 youtube-dl 和 System.out 的那些(比如“完成!”)),我想当我运行“java -jar xxx.jar”时 youtube-dl.exe 没有执行。
      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      • 2013-12-07
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      相关资源
      最近更新 更多