2010-11-01 8 views
5

Estoy peleando con el error de espacios en el método de ejecución Runtime de Java. Esto es lo único sobre este problema: el comando que intento ejecutar es una cadena entrante y puede o no tener espacios y no necesariamente en un formato específico. De cualquier manera, necesito ejecutarlo. Si no hay espacios, estoy bien; si hay espacios, no soy tan bueno.Usando el comando de ejecución de Java cuando no se sabe si hay espacios

¿Cómo puedo tener en cuenta ambas circunstancias?

Información de bonificación sin cargo adicional: Uno de los grandes problemas parece ser que estoy tratando de llamar a un ejecutable en c: \ archivos de programa \ blablabla ... y el ejecutivo parece dividirse en el espacio después de 'c :\programa'. Estoy seguro de que también surgirán otros problemas para los parámetros.

Aquí hay un ejemplo más específico de los tipos de cadenas que podría obtener. Eso debería aclarar algunas de la confusión:

  • c: \ SomeApp \ someapp.exe
  • c: \ SomeApp \ someapp.exe -someParam = foo
  • c: \ archivos de programa \ SomeApp \ SomeApp .exe
  • c: \ archivos de programa \ SomeApp \ someapp.exe -someParam = bar

El primero funciona bien porque no tiene espacios. El segundo incluso está bien porque se divide en el espacio y utiliza el primero como comando y el segundo como parámetro. El tercer y cuarto ejemplo se dividen en el primer espacio, usan 'C: \ program' y el comando, 'archivos ...' y (en el caso de la cuarta cadena) '-someParam = bar' como parámetros.

+0

¿Puede hacer algo de preprocesamiento de la cadena entrante? Si es así, puede usar Runtime.exec (String) [] cmdarray) método que manejará espacios para usted, suponiendo que usted puede romper la cadena entrante por argumentos – Benn

+4

Garbage In, Garbage Out; no puede analizar una cadena sin sentido. Asegúrese de que el remitente escape de los espacios que desea retener, o poner las cadenas que se ejecutan juntas entre comillas, solo al hacerlo, su problema pasa de ser imposible a bastante difícil. –

Respuesta

4

Bien, tengo algo funcionando haciendo algo como esto. Por favor, dígame si hay un problema con este enfoque:

 

try{ 
    String[] command = {"cmd", "/c", getMySuperAwesomeString()}; 
    Runtime.getRuntime().exec(command); 
}catch(IOExecption ioe){ 
    System.err.println("I'm borken"); 
} 
 

En una nota relacionada, debería utilizar ProcessBuilder en su lugar?

+0

Esto probablemente funcione, dependiendo del proceso que está comenzando. Si funciona, probablemente sea más flexible que mi respuesta (y con menos codificación). Solo está descargando la parte difícil de descifrar los argumentos en el shell cmd :) No debería necesitar ProcessBuilder a menos que desee iniciar un montón de procesos similares, ya que se encontraría con los mismos problemas de tokenización. – Benn

+0

Sí, de cualquier manera estás haciendo suposiciones, ¿verdad? ¡Gracias por tu contribución! – Dave

+0

Sí, esto es lo que tenía que hacer en un microservicio, era un verdadero rascador de cabeza, pero este método parece mucho más robusto. – wired00

0

Tal vez estoy pensando demasiado simple, pero podría funcionar?

Runtime.exec(commandstring.split(" ")); 

(Estoy asumiendo que desea que el comando a ser ejecutado como si se ejecuta en una cáscara más o menos.)

+2

Creo que está pensando en algo así como 'comando C: \ Documents and Settings \ user \ datafile.dat ', que no desearía interpretar como' ["comando", "C: \ Documents", "y", "Settings \ user \ datafile.dat"] ' – Benn

+0

Sí, lo tiene. Haré eso más claro en mi pregunta. – Dave

0

Yo te puedo asumir preproceso la cadena de entrada. En ese caso, se puede ver si tiene una entrada con espacios con:

if("string with possible spaces".contains(" ")) { 
    System.out.println("yay"); 
} 

Tenga en cuenta que esto funcionará sólo si hay un carácter de espacio real en su entrada. Si quieres ser más profunda, asumiendo caracteres de tabulación o saltos de línea son posibles entradas, puede utilizar una expresión regular:

String s = ".+\\s.+"; 
Pattern p = Pattern.compile(s); 

Matcher m = p.matcher("string with possible spaces or tabs"); 
if(m.matches()) { 
    System.out.println("yay"); 
} 

Editar: Usted puede utilizar el código que he proporcionado para detectar si hay espacios en la entrada . Si no hay, no tienes que hacer nada. Si tiene espacios, la situación es un poco más compleja. Al leer las respuestas de otras personas y su pregunta revisada, solo puedo suponer que la entrada que tiene espacios debe citarse, por lo que el espaciado no estropeará la ejecución del comando estándar.En hay espacios, debe:

  1. verifique si hay cualquier cita en su entrada
  2. si los hay, escapar de ellos (modificar " a \")
  3. rodean la entrada con comillas (some input convierte "some input")

en última instancia, que desea la entrada como para convertirse en some "funky" input"some \"funky\" input".

Nota: tenga cuidado con las comillas simples ('). Trata con ellos apropiadamente.

+0

Podría dividirlo, pero ¿qué haría con las piezas individuales? Simplemente no sabría lo que tengo después de separarlos. – Dave

0

Estoy asumiendo que este es el error que está luchando:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4506936

http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=8582245ba20fa4da33ac0967e858?bug_id=4491217

Ellos dicen que la solución sería:

Usar un JRE que no se encuentra en una ruta que contiene espacios.

Uso proceso público exec (String [] cmdarray, String [] envp) throws IOException

y poner el comando y los parámetros en una matriz separada. De esta forma, no trataría de incluirlo y usar el espacio como separador.

+0

Nuestro JRE no se encuentra en una ruta que contiene espacios. – Dave

+0

En el otro error, dicen que debe colocar todos los argumentos en el espacio separado: para resumir, la única manera segura es colocar cada argumento en un espacio separado en la matriz de argumentos. Por lo tanto, use http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Runtime.html#exec%28java.lang.String [],% 20java.lang.String [] % 29. Corregiré la publicación original. –

+0

El problema es que no sé qué es una discusión y qué no. – Dave

4

Voy a hacer realidad esta respuesta en lugar de un comentario: (del J2SE 1.5, Runtime.exec(String[]))

Asumiendo que puede procesar previamente, utilice una matriz de cadenas para aliviar los problemas con los espacios en los comandos, la siguiente debería funcionar:

String[] args = {"C:\Program Files\app\app.exe","C:\Data Files\data1.dat"}; 
Runtime.exec(args); 

a partir de ahí depende de ser capaz de averiguar lo que es un espacio entre dos comandos y lo que es un espacio en un camino.

EDITAR

Esto funcionará si los espacios aparecen en el camino del ejecutable, pero no le ayudará en espacios en los argumentos.

String input = "c:\\program files\\someapp\\someapp.exe -someParam=bar"; 
int firstSplit = input.indexOf(".exe") + 4; //account for length of ".exe" 
String command = input.substring(0,firstSplit); 
String args = input.substring(firstSplit).trim(); //trim off extraneous whitespace 
String[] argarray = args.split(" "); 
String[] cmdargs = new String[argarray.length + 1]; 
cmdargs[0] = command; 
for (int i = 0; i < argarray.length; i++) { 
    cmdargs[i+1] = argarray[i]; 
} 
Runtime.exec(cmdargs); 

Tenga en cuenta que esto es todavía bastante frágil (y sólo funciona para exe, no de murciélago o cualquier otra cosa). Si necesita contabilizar espacios en los argumentos, necesitará hacer más procesamiento en la cadena args o en argarray. La solución adecuada es hacer que sus usuarios (o el proceso de entrada) diferencien adecuadamente todos los argumentos.

+0

Me gustaría hacer algo como esto, pero no tengo manera de saber con certeza dónde romper la cadena de comandos. – Dave

+0

Eso hace que las cosas sean desafortunadas, si no imposibles. Sin embargo, podrías adivinarlo: (a partir de tu edición) si los espacios solo ocurren en la ruta al ejecutable, preprocesa para llevar todo a ".exe" como un comando, y luego haz un String.split (" ") en las opciones restantes. Si las opciones mismas o los argumentos pueden contener espacios, se volverán dolorosos. Editaré mi respuesta para mostrar un ejemplo de eso. – Benn

+0

Solución interesante. Lo tendré en cuenta. – Dave

1

Ejemplo para ejecutar un archivo JAR con espacios en la ubicación del archivo:

String qoutation = "\"" 
String path = "C:\\JAR File\\File.jar" 
Runtime.getRuntime().exec("java -jar " + quotation + path + quotation); 

Esto ejecuta el comando: java-jar "C: \ archivo JAR \ archivo.jar"

Cuando la barra invertida \ aparece en una cadena que se usa como escape, lo que hace que el programa lo omita. Esto nos permite utilizar las comillas "en la cadena, no para iniciar/cerrar la cadena.

Cuestiones relacionadas