Указатель NULL
- это тот, который указывает на никуда. Когда вы разыскиваете указатель p
, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p
является нулевым указателем, местоположение, хранящееся в p
, является nowhere
, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception
.
В общем, это потому, что что-то не было правильно инициализировано.
Perl:
$output = `foo`;
ДОБАВИЛ: Это - действительно многоканальная связь. Вышеупомянутое является также допустимым PHP, и Ruby, например, использует ту же нотацию обратной галочки также.
from subprocess import check_output as qx
output = qx(['ls', '-lt'])
Извлечение subprocess.check_output()
от subprocess.py или адаптируют что-то подобное:
import subprocess
def cmd_output(args, **kwds):
kwds.setdefault("stdout", subprocess.PIPE)
kwds.setdefault("stderr", subprocess.STDOUT)
p = subprocess.Popen(args, **kwds)
return p.communicate()[0]
print cmd_output("ls -lt".split())
подпроцесс модуль был в stdlib с тех пор 2.4.
Предоставленный, это не меньшее (со всех доступных языков), но не должно случаться так что подробное.
Эта версия грязна. Исключения должны быть обработаны, чтение может быть улучшено. Это должно только показать, как версия Java могла запуститься.
Process p = Runtime.getRuntime().exec( "cmd /c " + command );
InputStream i = p.getInputStream();
StringBuilder sb = new StringBuilder();
for( int c = 0 ; ( c = i.read() ) > -1 ; ) {
sb.append( ( char ) c );
}
Полная программа ниже.
import java.io.*;
public class Test {
public static void main ( String [] args ) throws IOException {
String result = execute( args[0] );
System.out.println( result );
}
private static String execute( String command ) throws IOException {
Process p = Runtime.getRuntime().exec( "cmd /c " + command );
InputStream i = p.getInputStream();
StringBuilder sb = new StringBuilder();
for( int c = 0 ; ( c = i.read() ) > -1 ; ) {
sb.append( ( char ) c );
}
i.close();
return sb.toString();
}
}
Образец ouput (использование команды типа)
C:\oreyes\samples\java\readinput>java Test "type hello.txt"
This is a sample file
with some
lines
Демонстрационный вывод (dir)
C:\oreyes\samples\java\readinput>java Test "dir"
El volumen de la unidad C no tiene etiqueta.
El número de serie del volumen es:
Directorio de C:\oreyes\samples\java\readinput
12/16/2008 05:51 PM <DIR> .
12/16/2008 05:51 PM <DIR> ..
12/16/2008 05:50 PM 42 hello.txt
12/16/2008 05:38 PM 1,209 Test.class
12/16/2008 05:47 PM 682 Test.java
3 archivos 1,933 bytes
2 dirs 840 bytes libres
Попытка любой
java Test netstat
java Test tasklist
java Test "taskkill /pid 416"
РЕДАКТИРОВАНИЕ
я должен признать, что я не на 100% уверен, что это - "лучший" способ сделать это. Не стесняйтесь отправлять ссылки и/или код, чтобы показать, как он может быть улучшен или что случилось с этим.
stream := open("ls", "p")
while line := read(stream) do {
# stuff
}
документы называют это каналом. Одна из хороших вещей - то, что это заставляет вывод быть похожим, Вы просто читаете файл. Это также означает, что можно записать в stdin приложения, если Вы должны.
Perl, иначе:
use IPC::Run3
my ($stdout, $stderr);
run3 ['ls'], undef, \$stdout, \$stderr
or die "ls failed";
Полезный, потому что можно подать ввод команд и возвратить и stderr и stdout отдельно. Нигде рядом столь же аккуратный/страшный/медленный/тревожащий как IPC::Run
, который может настроить каналы к подпрограммам.
Почему нет все еще никакого c# парня здесь:)
Это - то, как сделать это в C#. Встроенный путь.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "cmd";
p.StartInfo.Arguments = "/c dir";
p.Start();
string res = p.StandardOutput.ReadToEnd();
Console.WriteLine(res);
}
}
}
В C на Posix совместимые системы:
#include <stdio.h>
FILE* stream = popen("/path/to/program", "rw");
fprintf(stream, "foo\n"); /* Use like you would a file stream. */
fclose(stream);
C (с glibc
расширение):
#define _GNU_SOURCE
#include <stdio.h>
int main() {
char *s = NULL;
FILE *p = popen("ls", "r");
getdelim(&s, NULL, '\0', p);
pclose(p);
printf("%s", s);
return 0;
}
Хорошо, не действительно краткий или чистый. Это - жизнь в C...
В PHP
$output = `ls`;
или
$output = shell_exec('ls');
Еще один путь (или 2!) в Perl....
open my $pipe, 'ps |';
my @output = < $pipe >;
say @output;
открывают может также быть записан как так...
open my $pipe, '-|', 'ps'
Несколько лет назад я записал плагин для jEdit, который взаимодействовал через интерфейс к исходному приложению. Это - то, что я раньше получал потоки от рабочего исполняемого файла. Только вещь, оставленная сделать, while((String s = stdout.readLine())!=null){...}
:
/* File: IOControl.java
*
* created: 10 July 2003
* author: dsm
*/
package org.jpop.io;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
/**
* Controls the I/O for a process. When using the std[in|out|err] streams, they must all be put on
* different threads to avoid blocking!
*
* @author dsm
* @version 1.5
*/
public class IOControl extends Object {
private Process process;
private BufferedReader stdout;
private BufferedReader stderr;
private PrintStream stdin;
/**
* Constructor for the IOControl object
*
* @param process The process to control I/O for
*/
public IOControl(Process process) {
this.process = process;
this.stdin = new PrintStream(process.getOutputStream());
this.stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
this.stderr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
}
/**
* Gets the stdin attribute of the IOControl object
*
* @return The stdin value
*/
public PrintStream getStdin() {
return this.stdin;
}
/**
* Gets the stdout attribute of the IOControl object
*
* @return The stdout value
*/
public BufferedReader getStdout() {
return this.stdout;
}
/**
* Gets the stderr attribute of the IOControl object
*
* @return The stderr value
*/
public BufferedReader getStderr() {
return this.stderr;
}
/**
* Gets the process attribute of the IOControl object. To monitor the process (as opposed to
* just letting it run by itself) its necessary to create a thread like this: <pre>
*. IOControl ioc;
*.
*. new Thread(){
*. public void run(){
*. while(true){ // only necessary if you want the process to respawn
*. try{
*. ioc = new IOControl(Runtime.getRuntime().exec("procname"));
*. // add some code to handle the IO streams
*. ioc.getProcess().waitFor();
*. }catch(InterruptedException ie){
*. // deal with exception
*. }catch(IOException ioe){
*. // deal with exception
*. }
*.
*. // a break condition can be included here to terminate the loop
*. } // only necessary if you want the process to respawn
*. }
*. }.start();
* </pre>
*
* @return The process value
*/
public Process getProcess() {
return this.process;
}
}
Ну, так как это системно-зависимо, существует много языков, которые не имеют встроенной обертки для различных системных вызовов необходимой.
, Например, сам язык Common LISP не был разработан для работы любой определенной системы. SBCL (Стальная реализация языка Common LISP Банков), тем не менее, обеспечивает расширение для подобных Unix систем, также, как и большинство других реализаций CL. Это является намного более "могущественным", чем просто получение вывода, конечно (Вы управляете рабочим процессом, может определить все виды направлений потока, и т.д., совещаться к руководству SBCL, главе 6.3), но легко записать немного макроса для этой определенной цели:
(defmacro with-input-from-command ((stream-name command args) &body body) "Binds the output stream of command to stream-name, then executes the body in an implicit progn." `(with-open-stream (,stream-name (sb-ext:process-output (sb-ext:run-program ,command ,args :search t :output :stream))) ,@body))
Теперь, можно использовать его как это:
(with-input-from-command (ls "ls" '("-l")) ;;do fancy stuff with the ls stream )
, Возможно, Вы хотите хлебать все это в одну строку. Макрос тривиален (хотя, возможно, более краткий код возможен):
(defmacro syslurp (command args) "Returns the output from command as a string. command is to be supplied as string, args as a list of strings." (let ((istream (gensym)) (ostream (gensym)) (line (gensym))) `(with-input-from-command (,istream ,command ,args) (with-output-to-string (,ostream) (loop (let ((,line (read-line ,istream nil))) (when (null ,line) (return)) (write-line ,line ,ostream)))))))
Теперь можно получить строку с этим вызовом:
(syslurp "ls" '("-l"))
В оболочке
OUTPUT=`ls`
или альтернативно
OUTPUT=$(ls)
Этот второй метод лучше, потому что это позволяет вложение, но не поддерживается всеми оболочками, в отличие от первого метода.
Haskell:
import Control.Exception
import System.IO
import System.Process
main = bracket (runInteractiveCommand "ls") close $ \(_, hOut, _, _) -> do
output <- hGetContents hOut
putStr output
where close (hIn, hOut, hErr, pid) =
mapM_ hClose [hIn, hOut, hErr] >> waitForProcess pid
С MissingH установил:
import System.Cmd.Utils
main = do
(pid, output) <- pipeFrom "ls" []
putStr output
forceSuccess pid
Это - легкая операция на языках "связующего звена" как Perl и Ruby, но Haskell не.
Альтернативный метод в жемчуге
$output = qx/ls/;
Это имело преимущество, которое можно выбрать разделители, позволив использовать 'в команде (хотя, по моему скромному мнению, необходимо пересмотреть дизайн, если действительно необходимо сделать это). Другое важное преимущество состоит в том, что, если Вы используете одинарные кавычки в качестве разделителя, переменные не будут интерполированы (очень полезное)
Ruby: или обратные галочки или '%x' встроенный синтаксис.
puts `ls`;
puts %x{ls};
Еще один способ сделать это в Perl (TIMTOWTDI)
$output = <<`END`;
ls
END
Это специально полезно при встраивании относительно большого сценария оболочки в программу
Perl [По требованию Alexman и dreeves - видит комментарии - Вы найдете в этом страница DZones Java Snippet полная версия независимый от OS для того, чтобы сделать, в этом экземпляре, 'ls'. Это - прямой ответ на их проблема кода .
то, Что следует ниже, является просто ядром: Runtime.exec, плюс 2 потока для слушания stdout и stderr.]
Java, "Простой!":
E:\classes\com\javaworld\jpitfalls\article2>java GoodWindowsExec "dir *.java"
Executing cmd.exe /C dir *.java
...
Или в коде Java
String output = GoodWindowsExec.execute("dir");
, Но сделать это, необходимо кодировать...
... это является смущающим.
import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
InputStream is;
String type;
StringBuffer output = new StringBuffer();
StreamGobbler(InputStream is, String type)
{
this.is = is;
this.type = type;
}
public void run()
{
try
{
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(type + ">" + line);
output.append(line+"\r\n")
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
public String getOutput()
{
return this.output.toString();
}
}
public class GoodWindowsExec
{
public static void main(String args[])
{
if (args.length < 1)
{
System.out.println("USAGE: java GoodWindowsExec <cmd>");
System.exit(1);
}
}
public static String execute(String aCommand)
{
String output = "";
try
{
String osName = System.getProperty("os.name" );
String[] cmd = new String[3];
if( osName.equals( "Windows 95" ) )
{
cmd[0] = "command.com" ;
cmd[1] = "/C" ;
cmd[2] = aCommand;
}
else if( osName.startsWith( "Windows" ) )
{
cmd[0] = "cmd.exe" ;
cmd[1] = "/C" ;
cmd[2] = aCommand;
}
Runtime rt = Runtime.getRuntime();
System.out.println("Executing " + cmd[0] + " " + cmd[1]
+ " " + cmd[2]);
Process proc = rt.exec(cmd);
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");
// any output?
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT");
// kick them off
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
output = outputGobbler.getOutput();
System.out.println("Final output: " + output);
} catch (Throwable t)
{
t.printStackTrace();
}
return output;
}
}
C# 3.0, менее подробный, чем этот :
using System;
using System.Diagnostics;
class Program
{
static void Main()
{
var info = new ProcessStartInfo("cmd", "/c dir") { UseShellExecute = false, RedirectStandardOutput = true };
Console.WriteLine(Process.Start(info).StandardOutput.ReadToEnd());
}
}
Протест: Производственный код должен правильно расположить объект Процесса...
Вот еще один способ Lisp:
(defun execute (program parameters &optional (buffer-size 1000))
(let ((proc (sb-ext:run-program program parameters :search t :output :stream))
(output (make-array buffer-size :adjustable t :fill-pointer t
:element-type 'character)))
(with-open-stream (stream (sb-ext:process-output proc))
(setf (fill-pointer output) (read-sequence output stream)))
output))
Затем, чтобы получить вашу строку:
(execute "cat" '("/etc/hosts"))
Если вы хотите запустить команду, которая выводит большой объем информации в STDOUT, вы можете запустить ее примерно так:
(execute "big-writer" '("some" "parameters") 1000000)
Последний параметр заранее выделяет большой объем места для вывода из big-writer. Я предполагаю, что эта функция может быть быстрее, чем чтение выходного потока по одной строке за раз.
Clozure Common Lisp:
(with-output-to-string (stream)
(run-program "ls" '("-l") :output stream))
LispWorks
(with-output-to-string (*standard-output*)
(sys:call-system-showing-output "ls -l" :prefix "" :show-cmd nil))