2010-08-10 18 views
23

(sin incluir ninguna biblioteca externa.)Retire la extensión del archivo en Java

¿Cuál es la forma más eficaz para eliminar la extensión de un nombre de archivo en Java, sin asumir nada del nombre de archivo?

Algunos ejemplos y resultados esperados: carpeta

  • > carpeta
  • hola.txt> hola
  • read.me> leer
  • hello.bkp.txt> hello.bkp
  • extraño ... nombre> raro.
  • .hidden> .hidden

(o debería ser el último que acaba de ocultos?)

Editar: La pregunta original supone que la entrada es un nombre de archivo (no una ruta de archivo) Puesto que algunas respuestas están hablando de rutas de archivos, tales funciones también deben trabajar en casos como:

  • rare.folder/hola> rare.folder/hola

Este caso particular se maneja muy bien por Sylvain La respuesta de M

+0

podría dividirla la cadena basada en ''. – Albinoswordfish

+0

Creo que falla al menos en dos de los casos anteriores. – hpique

+2

".oculto "no debe volverse" oculto " – ninesided

Respuesta

12

Voy a intentar esto usando la versión de dos arias de lastIndexOf para eliminar algún código de comprobación de casos especiales y, con suerte, hacer que la intención sea más legible. El crédito va a Justin 'jinguy' Nelson para proporcionar la base de este método:

public static String removeExtention(String filePath) { 
    // These first few lines the same as Justin's 
    File f = new File(filePath); 

    // if it's a directory, don't remove the extention 
    if (f.isDirectory()) return filePath; 

    String name = f.getName(); 

    // Now we know it's a file - don't need to do any special hidden 
    // checking or contains() checking because of: 
    final int lastPeriodPos = name.lastIndexOf('.'); 
    if (lastPeriodPos <= 0) 
    { 
     // No period after first character - return name as it was passed in 
     return filePath; 
    } 
    else 
    { 
     // Remove the last period and everything after it 
     File renamed = new File(f.getParent(), name.substring(0, lastPeriodPos)); 
     return renamed.getPath(); 
    } 
} 

Para mí esto es más claro que los archivos ocultos especial de la carcasa y los archivos que no contienen un punto. También se lee más claro a lo que entiendo que es su especificación; algo así como "eliminar el último punto y todo lo que lo sigue, suponiendo que exista y no sea el primer carácter del nombre de archivo".

Tenga en cuenta que este ejemplo también implica cadenas como entradas y salidas. Como la mayor parte de la abstracción requiere objetos File, sería marginalmente más claro si esos fueran también las entradas y salidas.

+0

Un nitpick: si su entrada es una ruta de archivo (como indica el nombre de la variable), esta solución falla en algunos casos. Ver la pregunta revisada. – hpique

+0

Ah, buen punto. He revisado la respuesta para que se devuelva la cadena de entrada en todos los casos en que detectamos que no se requiere ningún cambio; y si devolvemos una cadena modificada, esto se antepone a los directorios (si los hay) en la ruta de entrada. –

+0

Esta es de hecho una versión mejor mía, creo. – jjnguy

10

Esto tomará una ruta de archivo y luego devolverá el nuevo nombre del archivo sin la extensión.

public static String removeExtention(String filePath) { 
    File f = new File(filePath); 
    // if it's a directory, don't remove the extention 
    if (fisDirectory()) return f.getName(); 
    String name = f.getName(); 
    // if it is a hidden file 
    if (name.startsWith(".")) { 
     // if there is no extn, do not rmove one... 
     if (name.lastIndexOf('.') == name.indexOf('.')) return name; 
    } 
    // if there is no extention, don't do anything 
    if (!name.contains(".") return name; 
    // Otherwise, remove the last 'extension type thing' 
    return name.substring(0, name.lastIndexOf('.')) 
} 

Las personas deben tener en cuenta que esto fue escrito en mi netbook, en la pequeña caja de editor de SO. Este código no es para producción. Solo está destinado al servidor como un buen primer intento, ejemplo de cómo eliminaría la extensión de un nombre de archivo.

+2

Querrá comprobar que 'name.lastIndexOf ('. ')! = -1', de lo contrario, la última llamada a 'subcadena' emitirá una excepción. Como hgpc dijo que no debía asumir nada sobre los nombres de los archivos, esto parece un caso que debería manejarse correctamente. –

+0

Esto también falla en el' raro ..name' example. –

+0

He solucionado ese problema. Probablemente todos lo vimos en th Es exactamente la misma hora. Gracias por señalar eso. – jjnguy

26

Usando io común de Apache http://commons.apache.org/io/

removeExtension public static String (cadena de nombre de archivo)

Para su información, el código fuente está aquí:

http://commons.apache.org/proper/commons-io/javadocs/api-release/src-html/org/apache/commons/io/FilenameUtils.html#line.1025

Arg, no tengo acabo de intentar algo ...

System.out.println(FilenameUtils.getExtension(".polop")); // polop 
System.out.println(FilenameUtils.removeExtension(".polop")); // empty string 

Por lo tanto, esta solución no parece ser muy buena ... Incluso con io común, que tendrá que jugar con removeExtension() getExtension() indexOfExtension() ...

+0

Debería haber mencionado que no puedo incluir bibliotecas externas, pero veré el código fuente común de io. – hpique

+1

Oh, está bien. En este caso, la respuesta de Justin es más útil ... –

+0

Esta biblioteca de Commons es el enfoque que terminé tomando. Edité la pregunta del OP para incluir también esta restricción. –

1

expresiones regulares para estas cosas son "suficientemente rápido" pero no eficiente si se compara con el método más simple que se pueda pensar: escanee la secuencia desde el final y trunque en el primer punto (no incluido). En Java, puede usar lastIndexOf y substring para tomar solo la parte que le interesa. El punto inicial debe considerarse como un caso especial y la última vez que aparece "." está al principio, la secuencia completa debería ser devuelta.

1

Conozco una expresión regular para hacerlo, pero en Java ¿tengo que escribir como 10 líneas de código para hacer una simple sustitución de expresiones regulares?

con y sin matar a los archivos ocultos:

^(.*)\..*$ 
^(..*)\..*$ 
0
filename.replace("$(.+)\.\\w+", "\1"); 
2

En realidad es muy fácil, asumiendo que tiene un nombre de archivo válido.

En los nombres de archivos de Windows, el carácter de punto solo se utiliza para designar una extensión. Así que quítate el punto y todo lo demás después.

En nombres de archivo unix el punto indica una extensión si está después del último separador ('/') y tiene al menos un carácter entre él y el último separador (y no es el primer carácter, si no hay separadores) Encuentre el último punto, vea si satisface las condiciones y quítelo y cualquier rastro de caracteres si lo hace.

Es importante que valide el nombre del archivo antes de hacer esto, ya que este algoritmo en un nombre de archivo invlaid puede hacer algo inesperado y generar un nombre de archivo válido. Por lo tanto, en Windows es posible que deba verificar que no haya una barra invertida, o dos puntos, después del punto.

Si no sabes de qué tipo de nombre de archivo estás tratando, tratarlos a todos como Unix te ayudará en gran medida.

+0

Debería mostrar el código en lugar de intentar escribir las condiciones en las palabras – Pacerier

1

Uso nueva Remover(). Remove (Cadena),

[email protected]:/tmp/stackoverflow> javac Remover.java && java Remover 
folder > folder 
hello.txt > hello 
read.me > read 
hello.bkp.txt > hello.bkp 
weird..name > weird. 
.hidden > .hidden 

Remover.java,

import java.util.*; 

public class Remover { 

    public static void main(String [] args){ 
     Map<String, String> tests = new LinkedHashMap<String, String>(); 
     tests.put("folder", "folder"); 
     tests.put("hello.txt", "hello"); 
     tests.put("read.me", "read"); 
     tests.put("hello.bkp.txt", "hello.bkp"); 
     tests.put("weird..name", "weird."); 
     tests.put(".hidden", ".hidden"); 

     Remover r = new Remover(); 
     for(String in: tests.keySet()){ 
      String actual = r.remove(in); 
      log(in+" > " +actual); 
      String expected = tests.get(in); 
      if(!expected.equals(actual)){ 
       throw new RuntimeException(); 
      } 
     } 
    } 

    private static void log(String s){ 
     System.out.println(s); 
    } 

    public String remove(String in){ 
     if(in == null) { 
      return null; 
     } 
     int p = in.lastIndexOf("."); 
     if(p <= 0){ 
      return in; 
     } 
     return in.substring(0, p); 
    } 
} 
+0

. Se produce un error en este caso nuevo: rare.folder/hello> rare.folder/hello –

2
int p=name.lastIndexOf('.'); 
if (p>0) 
    name=name.substring(0,p); 

dije "p> 0" en lugar de "p> = 0 "porque si el primer personaje es un período, presumiblemente no queremos borrar el nombre completo, como en el ejemplo" .hidden ".

¿Desea realmente actualizar el nombre del archivo en el disco o está hablando simplemente de manipularlo internamente?

+0

Just internally. – hpique

+0

Supongo que solo tiene el nombre de archivo aquí, es decir, no hay ninguna ruta. Veo que alguien más sacó esa pregunta. Manejar una ruta completa requeriría otro par de líneas de código. Todavía no es un gran problema. – Jay

0

La función remove() anterior debe ser reescrito para apoyar casos de prueba como LOST.DIR/myfile.txt

public static String removeExtension(String in) 
{ 
    int p = in.lastIndexOf("."); 
    if (p < 0) 
     return in; 

    int d = in.lastIndexOf(File.separator); 

    if (d < 0 && p == 0) 
     return in; 

    if (d >= 0 && d > p) 
     return in; 

    return in.substring(0, p); 
} 
Cuestiones relacionadas