응용 프로그램이 닫힐 때까지 콘솔 리디렉션이 작동하지 않음 (Java)

Steeviebops

우선, 저는이 일을 재미로만하고 어떤 식 으로든 프로가 아닙니다. 따라서 내 코드가 약간 엉성하더라도 놀라지 않을 것입니다!

콘솔 응용 프로그램을 위해 Java 11에서 GUI 래퍼를 작성하려고합니다. 내 계획은 BufferedReader를 사용하여 프로세스에서 stdOut 및 stdErr을 캡처하고 JTextArea에 표시하는 것이 었습니다. 명령 줄 매개 변수로 ArrayList를 채운 후 주 GUI 스레드에서이 스레드를 실행하고 있습니다. Ubuntu 또는 Fedora에서 완벽하게 작동하지만 Windows에서는 제대로 작동하지 않습니다. 크로스 컴파일 된 Windows 버전의 콘솔 응용 프로그램을 실행하려고하면 내 응용 프로그램은 콘솔 응용 프로그램이 닫힌 후에 만 ​​출력을 표시합니다. 또한 C (일반적으로 Hello를 표시하고 5 초 동안 기다린 다음 World를 표시 함)로 된 매우 간단한 Hello World 응용 프로그램으로 대체하려고 시도했으며 동일한 작업을 수행합니다. 그러나 ping.exe -t 8.8.8.8을 실행하도록 ArrayList를 변경하면 제대로 작동합니다.

내가 의심하는 것은 while 루프가 스레드를 차단하고 있지만 Linux에서 어떻게 작동하는지 그리고 Windows에서 ping.exe를 사용하는지 이해하지 못한다는 것입니다. 또한 Java의 Redirect stdin 및 stdout에서 코드를 시도하고 ProcessBuilder 에서 언급 한 inheritIO : 기본 스레드를 차단하지 않고 시작된 프로세스의 stdout 및 stderr 전달 하지만 동일한 문제가 있습니다. 어떤 아이디어?

    public class RunThread extends Thread {
    @Override
    public void run(){
        // Create process with the ArrayList we populated above
        ProcessBuilder pb = new ProcessBuilder(allArgs);
        pb.redirectErrorStream(true);

        // Clear the console
        txtConsoleOutput.setText("");

        // Try to start the process
        try {
            Process p = pb.start();                

            // Get the PID of the process we just started
            pid = p.pid(); 

            // Capture the output
            String cmdOutput;
            BufferedReader inputStream = new BufferedReader(new InputStreamReader(p.getInputStream()));

            // Get stdOut/stdErr of the process and display in the console
            while ((cmdOutput = inputStream.readLine()) != null) {
                txtConsoleOutput.append(cmdOutput + "\n");
            }
            inputStream.close();
        }
        catch (IOException ex) {
            JOptionPane.showMessageDialog(null,
                    "An error (" + ex + ") occurred while attempting to run.", AppName, JOptionPane.ERROR_MESSAGE);
        }

        // Clear the ArrayList so we can run again with a fresh set
        allArgs.clear();

    }
}

업데이트 @ControlAltDel에서 제공 한 코드와 @Holger의 조언을 기반으로 스레드로부터 안전하도록 다시 작성했지만 최종 결과는 동일합니다.

        SwingWorker <Void, String> RunTV = new SwingWorker <Void, String> () {
        @Override
        protected Void doInBackground() {
            // Create process with the ArrayList we populated above
            ProcessBuilder pb = new ProcessBuilder(allArgs);
            pb.directory(new File(hacktvDirectory));
            pb.redirectErrorStream(true); 
            // Try to start the process
            try {
                Process p = pb.start();                
                // Get the PID of the process we just started
                pid = p.pid();
                // Capture the output
                DataFetcher df = new DataFetcher(p.getInputStream(), new byte[1024], 0);
                FetcherListener fl = new FetcherListener() {
                    @Override
                    public void fetchedAll(byte[] bytes) {}
                    @Override
                    public void fetchedMore(byte[] bytes, int start, int end) {
                        publish(new String (bytes, start, end-start));
                    }
                };
                df.addFetcherListener(fl);
                new Thread(df).start();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            return null;
        } // End doInBackground

        // Update the GUI from this method.
        @Override
        protected void done() {
            // Revert button to say Run instead of Stop
            changeStopToRun();
            // Clear the ArrayList so we can run again with a fresh set
            allArgs.clear();                
        }
        // Update the GUI from this method.
        @Override
        protected void process(List<String> chunks) {
            // Here we receive the values from publish() and display
            // them in the console
            for (String o : chunks) {
                txtConsoleOutput.append(o);
                txtConsoleOutput.repaint();
            }
        }
    };
    RunTV.execute();
}

업데이트 10/11/2020 kriegaex의 게시물에 이어 이것을 다시 살펴 보았습니다. 안타깝게도 샘플 코드는 동일한 작업을 수행했지만 "예를 들어 샘플 프로그램이 println () 대신 System.out.print ()를 사용하면 출력이 버퍼링되기 때문에 콘솔에서 아무것도 볼 수 없습니다 . " 라는 주석 이 있습니다. 나와 함께 종을 울렸다.

래핑중인 프로그램의 소스에 액세스 할 수 있으며 C로 작성되었습니다. 콘솔에 비디오 해상도를 인쇄하는 다음 코드가 있습니다.

void vid_info(vid_t *s)
{
        fprintf(stderr, "Video: %dx%d %.2f fps (full frame %dx%d)\n",
                s->active_width, s->conf.active_lines,
                (double) s->conf.frame_rate_num / s->conf.frame_rate_den,
                s->width, s->conf.lines
        );

        fprintf(stderr, "Sample rate: %d\n", s->sample_rate);
}

fflush (stderr); 추가하면 두 번째 fprintf 문 아래에서 내 코드를 수정하지 않고 콘솔에 이러한 줄이 표시됩니다. 나는 이것이 왜 이것이없이 리눅스에서 작동하는지 이해하지 못한다. 그러나 적어도 나는 답을 알고있다.

크리 게 엑스

내 댓글 관련 정보 :

또 다른 생각 : Swing없이 이것을 재현하고 스트림에서 읽은 내용을 프로그램의 텍스트 콘솔로 덤핑 해 보셨습니까? ping다른 테스트 프로그램과는 작동 하지 않지만 다른 테스트 프로그램과는 작동 하지 않는 문제 는 후자가 단순히 버퍼링 된 스트림에 쓰기 만하고 가끔 (예 : 종료 할 때) 플러시되므로 자신의 프로그램에 대해 읽을 내용이 없다는 것입니다. 짧은 문자열보다 훨씬 큰 버퍼를 가진 스트림에 "Hello"+ "world"를 쓰면 그러한 동작이 발생할 수 있다고 생각합니다. ping그러나 직접 쓰고 플러시 할 수 있습니다.

예를 들어 샘플 프로그램이 System.out.print()대신을 사용 하는 println()경우 출력이 버퍼링되기 때문에 콘솔에 아무것도 표시되지 않습니다. 삽입 ( println()호출을 암시) BufferedWriter.flushBuffer()하거나 작성자의 버퍼를 직접 플러시 한 후에 만 첫 번째 프로세스의 콘솔에서 읽는 다른 프로그램이 무언가를 읽습니다.

콘솔에 쓰는 대상 애플리케이션 :

import java.util.Random;

public class TargetApp {
  public static void main(String[] args) throws InterruptedException {
    System.out.print("Hello ");
    Thread.sleep(1500);
    System.out.println("world!");
    Random random = new Random();
    for (int i = 0; i < 250; i++) {
      System.out.print("#");
      if (random.nextInt(20) == 0)
        System.out.println();
      Thread.sleep(50);
    }
  }
}

컨트롤러 애플리케이션, 대상 애플리케이션의 콘솔 출력 읽기 :

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

public class ControllerApp extends Thread {
  List<String> allArgs = Arrays.asList(
    //"ping", "-n", "3", "google.de"
    "java", "-cp", "bin", "TargetApp"
  );

  @Override
  public void run() {
    try (
      BufferedReader inputStream = new BufferedReader(
        new InputStreamReader(
          new ProcessBuilder(allArgs)
            .redirectErrorStream(true)
            .start()
            .getInputStream()
        )
      )
    ) {
      String cmdOutput;
      while ((cmdOutput = inputStream.readLine()) != null) {
        System.out.println(cmdOutput);
      }
    }
    catch (IOException ex) {
      throw new RuntimeException(ex);
    }
  }

  public static void main(String[] args) throws InterruptedException {
    new ControllerApp().start();
  }
}

를 실행 ControllerApp하면 "Hello"및 "world!"가 표시되지 않습니다. 별도로하지만 한 번에. "#"문자열도 마찬가지입니다. 다른 프로그램의 버퍼 플러시 동작에 따라 청크 단위로 읽습니다. 또한 다음 프로토콜을 50ms마다 "#"문자의 연속 스트림이 아닌 중지 및 이동 방식으로 작성하고 있음을 알 수 있습니다.

Hello world!
#####
#################
############
####
#############
##########################################
###############
################
#################
######
##########
######
#######
############################################
#########
#################
##########

따라서 이것이 귀하의 문제 TargetApp라면 ControllerApp. 그러면 스윙과도 관련이 없습니다.


업데이트 :TargetApp 다음 두 줄을 주석 처리하여 종료 후에 만 마지막 출력을 보는 동작을 에뮬레이트 할 수 있다는 것을 언급하는 것을 잊었습니다 .

//      if (random.nextInt(20) == 0)
//        System.out.println();

그러면 콘솔 로그는 다음과 같이 표시됩니다. 긴 "#"줄은 TargetApp종료 될 때만 인쇄 됩니다.

Hello world!
##########################################################################################################################################################################################################################################################

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

콘솔의 직렬 포트 응용 프로그램이 작동하지 않음

분류에서Dev

C # 콘솔 응용 프로그램 exe 파일이 시작되지 않음

분류에서Dev

Windows 8.1에서 C # 콘솔 응용 프로그램이 인쇄되지 않음

분류에서Dev

Weblogic 콘솔에 응용 프로그램이 표시되지 않음

분류에서Dev

GUI 응용 프로그램이 잘 작동하는 동시에 콘솔 Android Java 응용 프로그램이 ODEX 파일없이 작동하지 않는 이유는 무엇입니까?

분류에서Dev

C # 콘솔 응용 프로그램이 자동으로 닫히지 않도록하려면 어떻게해야합니까?

분류에서Dev

"시작 응용 프로그램"이 작동하지 않음

분류에서Dev

Windows 8 용 Visual Studio 2012에서 win32 콘솔 응용 프로그램 옵션이 표시되지 않음

분류에서Dev

Windows 8 용 Visual Studio 2012에서 win32 콘솔 응용 프로그램 옵션이 표시되지 않음

분류에서Dev

외부 Excel 응용 프로그램이 닫힐 때까지 C # 양식 비활성화

분류에서Dev

C # 프로그램이 작동하지 않음, 빈 콘솔 출력

분류에서Dev

그놈 터미널이 닫힐 때까지 Java 프로그램을 일시 중지하는 방법

분류에서Dev

Java Spring 리턴 리디렉션이 작동하지 않음

분류에서Dev

로그인 후 시작 응용 프로그램이 작동하지 않음

분류에서Dev

C # 콘솔 응용 프로그램에서 작동하지 않는 SlowCheetah

분류에서Dev

클릭 할 때까지 응용 프로그램 표시기 아이콘이 변경되지 않음

분류에서Dev

프로그램이 콘솔에 출력되지 않음

분류에서Dev

빌드 서버의 콘솔 응용 프로그램에서 MSBuild가 작동하지 않음

분류에서Dev

창이 닫힐 때 Java Swing JTable TableModel setValueAt ()이 호출되지 않음

분류에서Dev

프로그램이 닫힐 때 끊어지는 루프

분류에서Dev

프로그램이 닫힐 때 끊어지는 루프

분류에서Dev

콘솔 응용 프로그램에서 디버깅하지 않고 시작하면 Visual Studio가 지연됨

분류에서Dev

Java : 응용 프로그램을 종료하지 않고 파일 디렉토리에 이미지 저장

분류에서Dev

특정 값을 업데이트하고 스크롤하지 않는 콘솔 응용 프로그램

분류에서Dev

Internet Explorer 10에서 Aurelia TypeScript 응용 프로그램이 작동하지 않음

분류에서Dev

응용 프로그램이 올바르게 작동하지 않음 C #

분류에서Dev

응용 프로그램이 작동하지 않습니다

분류에서Dev

내 응용 프로그램이 닫힐 때 어떻게 발사 의도를 유발하는?

분류에서Dev

코드는 콘솔 응용 프로그램에서 작동하지만 ASP.NET 응용 프로그램에서는 작동하지 않습니다.

Related 관련 기사

  1. 1

    콘솔의 직렬 포트 응용 프로그램이 작동하지 않음

  2. 2

    C # 콘솔 응용 프로그램 exe 파일이 시작되지 않음

  3. 3

    Windows 8.1에서 C # 콘솔 응용 프로그램이 인쇄되지 않음

  4. 4

    Weblogic 콘솔에 응용 프로그램이 표시되지 않음

  5. 5

    GUI 응용 프로그램이 잘 작동하는 동시에 콘솔 Android Java 응용 프로그램이 ODEX 파일없이 작동하지 않는 이유는 무엇입니까?

  6. 6

    C # 콘솔 응용 프로그램이 자동으로 닫히지 않도록하려면 어떻게해야합니까?

  7. 7

    "시작 응용 프로그램"이 작동하지 않음

  8. 8

    Windows 8 용 Visual Studio 2012에서 win32 콘솔 응용 프로그램 옵션이 표시되지 않음

  9. 9

    Windows 8 용 Visual Studio 2012에서 win32 콘솔 응용 프로그램 옵션이 표시되지 않음

  10. 10

    외부 Excel 응용 프로그램이 닫힐 때까지 C # 양식 비활성화

  11. 11

    C # 프로그램이 작동하지 않음, 빈 콘솔 출력

  12. 12

    그놈 터미널이 닫힐 때까지 Java 프로그램을 일시 중지하는 방법

  13. 13

    Java Spring 리턴 리디렉션이 작동하지 않음

  14. 14

    로그인 후 시작 응용 프로그램이 작동하지 않음

  15. 15

    C # 콘솔 응용 프로그램에서 작동하지 않는 SlowCheetah

  16. 16

    클릭 할 때까지 응용 프로그램 표시기 아이콘이 변경되지 않음

  17. 17

    프로그램이 콘솔에 출력되지 않음

  18. 18

    빌드 서버의 콘솔 응용 프로그램에서 MSBuild가 작동하지 않음

  19. 19

    창이 닫힐 때 Java Swing JTable TableModel setValueAt ()이 호출되지 않음

  20. 20

    프로그램이 닫힐 때 끊어지는 루프

  21. 21

    프로그램이 닫힐 때 끊어지는 루프

  22. 22

    콘솔 응용 프로그램에서 디버깅하지 않고 시작하면 Visual Studio가 지연됨

  23. 23

    Java : 응용 프로그램을 종료하지 않고 파일 디렉토리에 이미지 저장

  24. 24

    특정 값을 업데이트하고 스크롤하지 않는 콘솔 응용 프로그램

  25. 25

    Internet Explorer 10에서 Aurelia TypeScript 응용 프로그램이 작동하지 않음

  26. 26

    응용 프로그램이 올바르게 작동하지 않음 C #

  27. 27

    응용 프로그램이 작동하지 않습니다

  28. 28

    내 응용 프로그램이 닫힐 때 어떻게 발사 의도를 유발하는?

  29. 29

    코드는 콘솔 응용 프로그램에서 작동하지만 ASP.NET 응용 프로그램에서는 작동하지 않습니다.

뜨겁다태그

보관