2009-12-15 13 views
6

मुझे जावा प्रोग्राम के माध्यम से एक स्ट्रिंग चलाने की आवश्यकता है और फिर आउटपुट पुनर्प्राप्त करें। जावा प्रोग्राम मानक इनपुट के माध्यम से स्ट्रिंग स्वीकार करता है। निम्नलिखित काम करता है: $string सिर्फ कुछ के बारे में हो सकता है:मैं पर्ल से जावा कमांड में इनपुट कैसे पाइप कर सकता हूं?

my $output = `echo $string | java -jar java_program.jar`; 

एक समस्या है। इस समस्या के लिए एक अच्छा समाधान पर कोई विचार?

उत्तर

6

मैं सुझाव है कि आप IPC::Run3 मॉड्यूल को देखने के लिए। यह बहुत ही सरल इंटरफ़ेस का उपयोग करता है और STDERR और STDOUT प्राप्त करने की अनुमति देता है। यहाँ छोटा सा उदाहरण है:

use IPC::Run3; 
## store command output here 
my ($cmd_out, $cmd_err); 
my $cmd_input = "put your input string here"; 
run3([ 'java', '-jar', 'java_program.jar'], \$cmd_input, \$cmd_out, \$cmd_err); 
print "command output [$cmd_out] error [$cmd_err]\n"; 

IPC::Run3comparation with other modules देखें।

6

यदि आप सीपीएएन मॉड्यूल का उपयोग कर सकते हैं (और मुझे लगता है कि अधिकांश लोग कर सकते हैं), IPC::Run3 का उपयोग करने पर Ivan's answer देखें। यह आपको आवश्यक सब कुछ संभालना चाहिए।

यदि आप मॉड्यूल का उपयोग नहीं कर सकते हैं, तो यहां सादे वेनिला तरीके से चीजें कैसे करें। , हालांकि

open PIPE, "| java -jar java_program.jar"; 
print PIPE "$string"; 
close(PIPE); 

ऐसा लगता है कि आप वास्तव में आदेश के उत्पादन की जरूरत है:

आप एक पाइप का उपयोग कर सकते अपने इनपुट करने के लिए, और यह उन सभी कमांड लाइन के हवाले से मुद्दों से बचने होगा। IPC::Open2 (जावा प्रक्रिया से और कुछ) के साथ दो पाइप खोल सकता है, लेकिन आप एक ही समय में दोनों पाइपों से निपटने की कोशिश कर रहे डेडलॉक में खुद को डालने का जोखिम उठाते हैं।

आपने किसी फ़ाइल का जावा उत्पादन होने, तो उस फ़ाइल से पढ़ने से बचने कर सकते हैं:

open PIPE, "| java -jar java_program.jar > output.txt"; 
print PIPE "$string"; 
close(PIPE); 

open OUTPUT, "output.txt"; 
while (my $line = <OUTPUT>) { 
    # do something with $line 
} 
close(OUTPUT); 

अन्य विकल्प बातें दूसरी तरह के आसपास करना है। अस्थायी फ़ाइल में $ स्ट्रिंग रखो, तो जावा के लिए इनपुट के रूप में उपयोग:

open INPUT, "input.txt"; 
print INPUT "$string"; 
close(INPUT); 

open OUTPUT, "java -jar java_program.jar < input.txt |"; 
while (my $line = <OUTPUT>) { 
    # do something with the output 
} 
close(OUTPUT); 

ध्यान दें कि यह अस्थायी फ़ाइलों को ऐसा करने के लिए सबसे बड़ी तरीका नहीं है; मैंने सादगी के लिए output.txt और input.txt का उपयोग किया है। अस्थायी फ़ाइलों को अधिक स्वच्छ रूप से बनाने के लिए विभिन्न क्लीनर तरीकों के लिए File::Temp docs देखें।

+0

यह बहुत अच्छा लग रहा है लेकिन मैं आदेश का आउटपुट कैसे प्राप्त करूं? – spudly

+1

@ स्पूली, आप उस सिफारिश के साथ नहीं कर सकते हैं। आपको open2() का उपयोग करना होगा, "बिडरेक्शनल संचार" के लिए perldoc perlipc की जांच करें – jsoverson

+0

विंडोज सिस्टम पर ओपन 2 या ओपन 3 के कई उपयोग इस तथ्य से मोटे तौर पर बाधित हैं कि आप केवल Win32 पर सॉकेट के खिलाफ 'चयन' कर सकते हैं। यदि आप विंडोज़ या ब्लॉकिंग पर नहीं हैं तो ठीक है, तो ओपन 2 या ओपन 3 आपके लिए चाल कर सकता है। – daotoad

1

बिल्टिन आईपीसी :: ओपन 2 मॉड्यूल बाहरी फ़ाइल के बिना बिडरेक्शनल-पाइपिंग को संभालने के लिए एक फ़ंक्शन प्रदान करता है।

2

क्या आपने IPC::Run देखा है?

सिंटेक्स इस के समान क्या आप देख रहे हैं हो सकता है:

use IPC::Run qw(run); 
my $input = $string; 
my ($out, $err); 
run ["java -jar java_program.jar"], \$input, \$out, \$err; 
2

अपने खोल की तरह एक पाइपलाइन बनाएं।

यहाँ हमारे डरावना स्ट्रिंग है:

my $str = "foo * ~ bar \0 baz *"; 

हम अपने पाइपलाइन पीछे की ओर का निर्माण करेंगे, इसलिए पहले हम जावा प्रोग्राम से उत्पादन इकट्ठा:

my $pid1 = open my $fh1, "-|"; 
die "$0: fork: $!" unless defined $pid1; 

if ($pid1) { 
    # grab output from Java program 
    while (<$fh1>) { 
    chomp; 
    my @c = unpack "C*" => $_; 
    print "$_\n => @c\n"; 
    } 
} 

नोट पर्ल के open करने के लिए विशेष "-|" तर्क ऑपरेटर।

आप कमांड '-' पर एक पाइप को खोलते हैं, यानी, या तो '|-' या 2-तर्क (या 1-तर्क) open() के फार्म के साथ '-|', तब वहाँ एक अंतर्निहित fork किया, और वापसी मान है open बच्चे की प्रक्रिया में बच्चे की पिड है, और 0 बच्चे की प्रक्रिया के भीतर है ... फ़ाइलशैली सामान्य रूप से माता-पिता के लिए व्यवहार करती है, लेकिन उस फ़ाइल के लिए i/o को STDOUT/STDIN से बाल प्रक्रिया में पाइप किया गया है।

unpack पाइप से पढ़ने वाले डेटा की सामग्री में देखने के लिए है।

अपने कार्यक्रम में, आप जावा प्रोग्राम को चलाने के लिए चाहता हूँ, लेकिन नीचे दिए गए कोड को एक उचित प्रतिकृति का उपयोग करता है:

else { 
    my $pid2 = open my $fh2, "-|"; 
    die "$0: fork: $!" unless defined $pid2; 

    if ($pid2) { 
    $| = 1; 
    open STDIN, "<&=" . fileno($fh2) 
     or die "$0: dup: $!"; 

    # exec "java", "-jar", "java_program.jar"; 

    # simulate Java program 
    exec "perl", "-pe", q(
     BEGIN { $" = "][" } 
     my @a = split " ", scalar reverse $_; 
     $_ = "[@a]\n"; 
    ); 
    die "$0: exec failed"; 
    } 

अंत में, विनम्र पोता बस डरावना स्ट्रिंग (जो मानक पर आता है प्रिंट जावा प्रोग्राम का इनपुट) और बाहर निकलता है। $| को एक वास्तविक मान पर सेट करना वर्तमान में चयनित फ़ाइल हैंडल को फ़्लश करता है और इसे अनबफर मोड में रखता है।

else { 
    print $str; 
    $| = 1; 
    exit 0; 
    } 
} 

इसका उत्पादन:

 
$ ./try 
[*][zab][][rab][~][*][oof] 
    => 91 42 93 91 122 97 98 93 91 0 93 91 114 97 98 93 91 126 93 91 42 93 91 111 111 102 93 

ध्यान दें कि NUL यात्रा बच जाता है।

संबंधित मुद्दे

 संबंधित मुद्दे