viernes, 16 de septiembre de 2011

Archivos en Java y revertir un número

Últimamente he tocado poco Eclipse ya que he tenido un examen y me ha tenido bastante ocupado. Aun así, el foro en el que suelo comentar lo he seguido visitando y, a pesar de que no es algo extremadamente interesante, me vale para hacer una muy breve entrada y dejar algo por aquí que sea nuevo.

Por un lado alguien preguntó sobre comprobar si una cadena de texto era sufijo de otra, pero de forma recursiva. La verdad que es algo muy simple de comprobar ya que apenas tiene dificultad. El código es el siguiente:

public boolean sufijo(String c1, String c2){
	if(c1.length() == 0)
		return true;
	int aux = c1.length();
	if(c1.charAt(c1.length()-1) == c2.charAt(c2.length()-1))
		return sufijo(c1.substring(0, c1.length()-1), c2.substring(0, c2.length()-1));
	else
		return false;
}


Con este método, que devuelve true o false, conseguimos lo que queríamos realizar. La función lo que hace es comprobar que la cadena c1 es sufijo de c2. El caso base es bastante claro, sí la longitud de c1 es 0 es un sufijo (ya que sería una cadena vacía y teóricamente una cadena vacía es sufijo de cualquier cadena. Sí el tamaño no es 0 comprobamos que el último carácter de cada canea sea igual, sí es así, entonces hacemos return con lo que nos devuelva la función eliminando el último carácter puesto que ya hemos comprobado que son iguales. En caso de que no sean iguales es porque no es un sufijo y por tanto devolvemos false. Las llamadas recursivas terminarán en algún momento, puesto que en cada nueva llamada al método eliminamos un carácter a cada cadena.

Otra persona del foro colgó un trozo de código para hacer uso de archivos, más concretamente crear un archivo vacío con formato .txt e ingresar datos en su interior. Tras leer el código que propuso él le comenté que quizás sería mejor el código con el que respondí:

Crear un archivo vacío
File archivo2 = new File("rutaYNombreArchivo" + ".txt");
	    try {
			if(archivo2.createNewFile()){
                                 System.out.println("Archivo creado!");
                        }
		} catch (IOException e) {
			System.out.println("Imposible crear archivo");
		}


De esta forma tendríamos un archivo vacío creado en la ruta especificada en el constructor del objeto File. Creo que es mejor dejar la ruta de creación del objeto parametrizada, es decir, pasarle un parámetro con la ruta completa hasta el archivo a crear o leer, ya que si por ejemplo estableciesemos a la fuerza que la ruta inicial comenzase en D:\\ podríamos tener errores sí una persona que ejecutase nuestro código no tuviese dicho directorio.

El código no podría ser más sencillo, simplemente declaramos un objeto de tipo File pasandole como parámetro la ruta completa, posteriormente llamamos al método de la clase File createNewFile() el cual nos crea un archivo nuevo con el nombre especificado en la ruta. Es decir, si nuestra ruta fuese C:\\Users\\Usuario\\Documents\\Carpeta\\archivoNuevo.txt crearía en la carpeta "Carpeta" un archivo con el nombre "archivoNuevo.txt".

He de decir que probé intentar crear un archivo vacío en el directorio raíz C:\\ y me lanzó una excepción, supongo que al usar Windows 7 necesita privilegios de Administrador.

Por otro lado, a la hora de ingresar datos en el archivo creado sería tan sencillo como esto:
String linea;
FileReader lector = new FileReader(archivo);
BufferedReader br = new BufferedReader(lector);
FileWriter escritor = new FileWriter(archivo);
BufferedWriter ayudaEscritor= new BufferedWriter(escritor);

while((linea = br.readLine()) != null){
       ayudaEscritor.write(linea);
       ayudaEscritor.newLine();
}

for(int a=0;a<=datos.length-1;a++){
       ayudaEscritor.write(datos[a]); //datos es una variable de tipo String[].
       ayudaEscritor.newLine();
}
ayudaEscritor.close();


Este es un código ejemplo, ya que sería mucho más sencillo escribir los datos si por ejemplo fuese un StringBuffer o un String directamente y no necesitaríamos un bucle for.

Por último un método que sirve para eliminar un fichero (suponiendo que tengamos permisos del sistema suficientes para hacerlo), crearlo de nuevo e introducir en el datos.
public boolean guardar(String nombreTabla, String rutaArchivo){
       File archivo= new File (rutaArchivo);
	       try{
	       if(archivo.exists()){
	              if(archivo.delete()){
	                     if(archivo.createNewFile()){
	                            FileWriter escritor = new FileWriter(archivo);
	                            BufferedWriter auxescritor = new BufferedWriter(escritor);
	                            auxescritor.write("Esto es una prueba!!");
	                            auxescritor.close();
                                    return true;
	                     }
	                     else
	                            System.out.println("Imposible crear archivo vacío");
	              }
	              else
	                     System.out.println("Imposible borrar archivo");
	       }
	       else
	              System.out.println("El archivo no existe");
               return false;
	}catch(IOException e){
               System.out.println("Ha ocurrido una excepción");
               return false;
	}
}


Con este código primero crearíamos un objeto de tipo File con la ruta completa del archivo, antes de realizar la llamada a este método deberíamos comprobar que el parámetro que le pasamos sea algo con extensión .txt. En primer lugar comprobamos que el archivo exista (podríamos cambiar un poco la función para que, en caso de que no existiese, crease directamente el archivo, este cambio es muy simple) en caso de existir, lo eliminamos, si la eliminación ha sido correcta entonces creamos un archivo nuevo vacío, y procedemos a insertar los datos.

Por último, un miembro del foro propuso un "reto" por así decirlo en C++, era bastante sencillo. Os dejo el enunciado y la resolución.

Dado un número 0 <= n <= 10100 por la entrada estándar (stdin), se debe mostrar por la salida estándar (stdout) su número girado, tal que si los dígitos de n son a1, ..., an, los de su número girado serán an, ..., a1 (es la misma definición, formalizada un poco). Tened en cuenta por ejemplo que el girado de 100 es 001 y no 1.

Restricciones: No se pueden utilizar arrays, structs, strings, clases ni nada similar, tan sólo los tipos de variables básicos de C/C++, es decir int, char, long long, etc.


La solución es la siguiente:
public static void procedimiento() throws IOException{
	int caracter = System.in.read();
	if(Character.isDigit((char)caracter)){
		procedimiento();
		System.out.print((char)caracter);
	}
}
	 
public static void main(String[] args) throws IOException {
	procedimiento();
	System.out.println();
}


De esta forma podríamos realizar el inverso de un número de forma muy sencilla. La única pega que veo al método es si el número fuese extremadamente grande (y con extremadamente me refiero a un número enorme enorme enorme) pues podría hacer un overflow en la pila con tanta llamada recursiva.

Bueno, hasta aquí la publicación de hoy, espero que a alguien le sea interesante o de utilidad.

Saludos.

No hay comentarios:

Publicar un comentario