Java - Comparar Archivos en Java

 
Vista:
sin imagen de perfil
Val: 9
Ha aumentado su posición en 5 puestos en Java (en relación al último mes)
Gráfica de Java

Comparar Archivos en Java

Publicado por franceso (4 intervenciones) el 01/05/2020 06:09:43
JAVA

Porfavor pueden ayudarme no se como hacer que ese boton de buscar palabras pueda hacer que busque las palabras de el archivo 1 en el archivo 2 y me cree un archivo que muestre palabras encontradas con un (si) y palabras no encontradas con (no).
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 9
Ha aumentado su posición en 5 puestos en Java (en relación al último mes)
Gráfica de Java

Comparar Archivos en Java

Publicado por franceso (4 intervenciones) el 01/05/2020 10:42:06
Buenas noches amigos quisiera comentarles un problema que tengo ya que soy nuevo en Java y quisiera que me brinden un apoyo porfavor ,eh adjuntado la interfaz de mi programa les explico un poco

Lo que quiero hacer es un programa basico su funcionamiento seria :

Seleccionar un archivo de texto con palabras que el usuario quiera encontrar en otro documento (Abrir1)

Seleccionar el archivo en donde quiere buscar las palabras que se encuentran en el archivo de texto seleccionado anteriormente (Abrir2)

Usar el boton buscar palabras, lo que haria que arranque y cree un nuevo archivo ubicado en el escritorio mostrando las palabras que encontro acompañadas de un(si) y las que no encontro acompañadas de un (no)

Muchas Gracias espero puedan ayudarme con este problema.

Buenas Noches
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Comparar Archivos en Java

Publicado por Kabuto (1381 intervenciones) el 01/05/2020 21:45:14
Hola, lo que puedes hacer es separar las palabras del archivo 1.
Puedes leer el archivo con BufferedReader que te dará lineas enteras en un String. Estas lineas puedes trocearlas con el metodo split() de la clase String.
Si suponemos que las palabras a buscar están separadas por espacios en blanco, usando split(" "); te dará un array de String con las palabras separadas de ESA LINEA.
Puedes guardar todas esas palabras en otra colección, mejor que sea dinámica porque no sabes cuántas palabras vas a tener. Puedes usar Vector o ArrayList por ejemplo.

Una vez tienes esas palabras, ahora lees el texto. En el texto no puedes saber con certeza si las palabras están separadas, por espacios, comas, puntos, guiones, símbolos.... por lo que split() no te puede ayudar de manera fiable.
Lo mejor es guardar las líneas completas, tal cual, en otro Vector/ArrayList distinto.

Ahora tendríamos palabras en un sitio y lineas de texto en otro.
¿Cómo empezar a buscar palabras en esas líneas? Lo mejor es usar expresiones regulares.

En otro bucle, con cada palabra construimos un nuevo patrón y comparamos en cada línea si hay coincidencia o no.

Tras comprobar todas las palabras, ya podríamos crear el nuevo archivo indicando que palabras se han encontrado y cuáles no.
Pero, ¿como marcamos las palabras encontradas de las que no?

Mira, he hecho un código para probarlo. Y me ha parecido que lo mejor es crear primero una clase Palabra.
Simplemente será un String y un booleano, para poder marcarla como encontrada o no.

Además le sobreescribo el método toString(), para usarlo luego al crear el archivo de resultados y que escriba la palabra acompañada de un SI o un NO según el valor del atributo boolean.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Palabra{
 
	private String palabra;
	private boolean encontrada;
 
	public Palabra(String palabra) {
		this.palabra = palabra;
		encontrada = false;
	}
 
	public String getPalabra() {
		return palabra;
	}
 
	public void setEncontrada(boolean encontrada) {
		this.encontrada = encontrada;
	}
 
	public boolean getEncontrada() {
		return encontrada;
	}
 
	@Override
	public String toString() {
		return palabra + (encontrada?" -> SI":" -> NO") + "\n";
	}
 
}


Entonces, cuando vaya a leer el archivo de palabras a buscar, crearé un objeto Palabra a partir de cada String obtenido.

A continuación voy a poner la parte del código que se encarga de leer archivos, comparar y crear archivo de resultados.
Es un poco extenso, aunque tan solo sigue los 4 pasos que he descrito antes, así que primero lo pongo por partes para mayor legibilidad.
He de decir, que para poder interactuar correctamente con la barra de progreso en la interfaz, esta parte del código será una clase que herede de Thread, es decir, será un hilo de ejecución paralelo al programa principal.

Voy por partes:

1
2
3
4
5
6
7
8
9
10
11
private class BuscarPalabras extends Thread {
 
    @Override
    public void run() {
        /*
         * Leeremos las lineas de cada archivo de texto y separaremos
         * las palabras individualmente en sendos Vector.
         */
 
        Vector<Palabra> palabras = new Vector<Palabra>(); //Palabras a buscar
        Vector<String> texto = new Vector<String>(); //Texto donde buscaremos

Como dije, es una clase Thread (interna a la clase principal del programa). Ahí declaro los dos Vector, uno de tipo Palabra y otro de tipo String donde guardaré las lineas del texto donde hay que buscar.

Tras esto, hago la lectura del archivo de palabras. En mi código, este archivo es un objeto File llamado arc1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
try {
    BufferedReader br = new BufferedReader(new FileReader(arc1));
    String linea = br.readLine();
    while (linea != null) {
        //Separamos palabras de esta linea.
        //Suponemos que en el texto estan separadas por un espacio en blanco
        String[] separadas = linea.split(" ");
        //Ahora las añadimos al Vector
        for (String pal: separadas)
            palabras.add(new Palabra(pal));
        //Siguiente linea
        linea = br.readLine();
    }
    br.close();
} catch (FileNotFoundException e) {
    mensajePopUp("No se encuentra archivo:\n" + arc1.getAbsolutePath());
    e.printStackTrace();
} catch (IOException e) {
    mensajePopUp("Error de acceso a archivo:\n" + arc1.getAbsolutePath());
    e.printStackTrace();
}
Como ves, leo linea del archivo y con split(" ") separo palabras en un array. Luego cojo esas palabras y creo objetos de mi clase Palabra para guardarlas en el Vector.

Fase 1 completada xD. Ahora hay que leer el archivo de texto. En mi código, es un File llamado arc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try {
    BufferedReader br = new BufferedReader(new FileReader(arc2));
    String linea = br.readLine();
    while (linea != null) {
        //En el Vector de texto metemos lineas enteras
        texto.add(linea);
        //Siguiente linea
        linea = br.readLine();
    }
    br.close();
} catch (FileNotFoundException e) {
    mensajePopUp("No se encuentra archivo:\n" + arc2.getAbsolutePath());
    e.printStackTrace();
} catch (IOException e) {
    mensajePopUp("Error de acceso a archivo:\n" + arc2.getAbsolutePath());
    e.printStackTrace();
}
Es similar al paso anterior, pero ahora no hacemos nada con split(). Guardamos las líneas enteras en el Vector de String.

Ahora viene el paso más importante. Buscar coincidencias.
Lo primero que hago es indicar a la barra de progreso cual es su valor máximo y reiniciarla a 0.
Como el progreso va a mostrar cada vez que termino de comprobar una palabra, pues su valor máximo depende de la cantidad de palabras que me haya dado el primer archivo, es decir, del tamaño que tenga el Vector de palabras.

Luego recorro cada una de estas palabras y creo un patrón con ellas.
Con este patrón, en un bucle anidado recorro todas las lineas del texto del archivo 2. Si el Matcher que analiza el patrón (la expresión regular) encuentra una coincidencia, entonces marco dicha palabra como encontrada.
Para entender esto hay que tener unas nociones mínimas de expresiones regulares y como usarlas en Java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
barraProgreso.setMaximum(palabras.size());
barraProgreso.setValue(0);
 
for (Palabra pal: palabras) {
    //Creamos patrón para la expresion regular con Palabra actual
    String patron = " \\b" + pal.getPalabra() + "\\b";
    //En el bucle anidado, recorremos cada linea del texto y comparamos
    for (String linea: texto) {
        Pattern patr = Pattern.compile(patron);
        Matcher mt = patr.matcher(linea);
        if (mt.find())
            pal.setEncontrada(true);
    }
    //Ya hemos terminado con esta palabra, aumentamos progreso
    try {
        Thread.sleep(100); //Ligero delay
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    barraProgreso.setValue(barraProgreso.getValue() + 1);
}
Tras cada palabra, actualizo barra de progreso y paso a la siguiente. Hago un ligero delay para que se vea la barra progresar. De lo contrario, todo ocurre rapidísimo y el usuario no verá la barra progresar.

Bien, llegados a este punto, los objetos Palabra del Vector ya están marcados unos como encontrados y otros como no. Es el momento de crear el archivo de resultados.
Para ello inicio un BufferedWriter con el archivo donde voy a guardar los resultados.
Recorro el vector de Palabra y a cada palabra invoco su método toString(), el cuál recuerdo que hemos sobreescrito para que muestre la palabra acompañada de SI o NO según su atributo.
1
2
3
4
5
6
7
8
9
10
11
try {
    result = new File("encontradas.txt");
    BufferedWriter bw = new BufferedWriter(new FileWriter(result));
    for (Palabra pal: palabras)
        bw.write(pal.toString());
    bw.close();
    campoArc3.setText(result.getAbsolutePath());
} catch (IOException e) {
    mensajePopUp("No se pudo grabar archivo de palabras encontradas en: " + result.getAbsolutePath());
    e.printStackTrace();
}
Además actualizo un JTextField llamado campoArc3, que es donde muestro al usuario la ruta donde puede encontrar este archivo que hemos creado.

Y ya está, eso es todo. Como digo son 4 pasos sencillos, parece que hay mucho código, debido a los obligatorios try catch cuando operamos con archivos, pero en realidad no es para tanto.

Entonces, si pongo a prueba mi programa con estas palabras:
1
2
3
4
5
6
coche familia avion saltar cachorro eliminar teclado camion verbena
perro gato pajaro liberado bicicleta bosque pantano pelota cabeza
mano pierna problema barriga ombligo cenar comer desayunar volar
telefono muerte vaso plato mesa silla cama tigre hermano
felino cuello barco guitarra elefante despertador concepto merienda
sonsacar cavidad nave inmortal inmortales humano veloz lento hola

Y este texto:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Un tigre que cuando cachorro habia sido capturado por humanos fue liberado luego de varios años de vida domestica.
La vida entre los hombres no habia menguado sus fuerzas ni sus instintos; en cuanto lo liberaron, corrio a la selva.
Ya en la espesura, sus hermanos teniéndolo otra vez entre ellos, le preguntaron:
 
-¿Que has aprendido?
 
El tigre medito sin prisa. Quería transmitirles algún concepto sabio, trascendente.
Recordó un comentario humano: "Los tigres no son inmortales. Creen que son inmortales porque ignoran la muerte, ignoran que morirán."
 
Ah, pensó el tigre para sus adentros, ese es un pensamiento que los sorprenderá: no somos inmortales, la vida no es eterna. -Aprendí esto- dijo por fin-. No somos inmortales solo ignoramos que alguna vez vamos a....
 
Los otros tigres no lo dejaron terminar de hablar, se abalanzaron sobre el, le mordieron el cuello y lo vieron desangrarse hasta morir.
Es el problema de los enfermos de muerte -dijo uno de los felinos-.
Se tornan resentidos y quieren contagiar a todos.''
 
Marcelo Birmajer, El tigre enfermo

Obtengo un archivo con este resultado:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
coche -> NO
familia -> NO
avion -> NO
saltar -> NO
cachorro -> SI
eliminar -> NO
teclado -> NO
camion -> NO
verbena -> NO
perro -> NO
gato -> NO
pajaro -> NO
liberado -> SI
bicicleta -> NO
bosque -> NO
pantano -> NO
pelota -> NO
cabeza -> NO
mano -> NO
pierna -> NO
problema -> SI
barriga -> NO
ombligo -> NO
cenar -> NO
comer -> NO
desayunar -> NO
volar -> NO
telefono -> NO
muerte -> SI
vaso -> NO
plato -> NO
mesa -> NO
silla -> NO
cama -> NO
tigre -> SI
hermano -> NO
felino -> NO
cuello -> SI
barco -> NO
guitarra -> NO
elefante -> NO
despertador -> NO
concepto -> SI
merienda -> NO
sonsacar -> NO
cavidad -> NO
nave -> NO
inmortal -> NO
inmortales -> SI
humano -> SI
veloz -> NO
lento -> NO
hola -> NO

Abajo te adjunto un zip, con las dos clases.
La clase Palabra y una clase main donde construyo el JFrame y contiene todo el código.
Lo adjunto todo para que lo veas funcionar y tal, pero vamos, la parte que te interesa entender para poder adaptarla a tu programa son los 4 pasos que he comentado aquí.
Échale un vistazo y pregunta cualquier cosa que no entiendas.
Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil
Val: 9
Ha aumentado su posición en 5 puestos en Java (en relación al último mes)
Gráfica de Java

Comparar Archivos en Java

Publicado por franceso (4 intervenciones) el 02/05/2020 01:03:56
Hermano Eres el mejor realmente eh entendido mas esto no se si tienes alguna red social o un correo donde pueda hacerte una consulta ya que me causa un poco de problemas al tener uqe plasmarlo en el neatbeans ay que soy un poco principiante
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Comparar Archivos en Java

Publicado por Kabuto (1381 intervenciones) el 02/05/2020 17:56:12
No tengo ninguna red social y de todos modos no me gusta tratar estos asuntos por privado.
Prefiero que se haga aquí, en el foro público, donde todo el mundo puedo verlo, unos para aprender y otros aportar distintas soluciones u opiniones.

Plantea aquí tus dudas. Y yo, y/o otros compañeros que saben mucho más que yo, te ayudaremos en lo que podamos.

Por cierto, ahora me fijo que en la imagen que pusiste de ejemplo, parece que quieres buscar las palabras en un archivo PDF.
De ser así, fíjate que ahí ahora mismo no sabría como ayudarte. Nunca he hecho lecturas de archivos PDF con Java.

El código que hice es para archivos de texto plano.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil
Val: 9
Ha aumentado su posición en 5 puestos en Java (en relación al último mes)
Gráfica de Java

Comparar Archivos en Java

Publicado por franceso (4 intervenciones) el 03/05/2020 04:41:39
Bro Gracias a la ayuda que me diste pude hacer funcionar el programa ,en realidad si pudiera leer archivos excel de tipo(Workbook)seria mejor pero por ahora estoy haciendo que lea texto plano como estas diciendo pero tengo un problema y es que eh tratado de seleccionar un archivo de tamaño 20mb y lo que paso es que se crasheo y no lee el archivo que seleccione, quisiera saber si habria alguna optimizacion que hacerle para que lea el archivo de 20mb ya que cuando lo selecciono la memoria de mi pc empieza a ser usada demasiado supongo que es porque tiene que leer un archivo bastante grande linea por linea pero espere aproximadamente 1 hora y media para que lo lea y no lo leia asi que trate con un archivo de 2mb y paso lo mismo, mismo tiempo y no lo leyo
Te adjunto el codigo con el programa funcionando y con los archivos que intento leer a ver si me puedes ayudar con ese problema
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Rodrigo
Val: 2.041
Plata
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Comparar Archivos en Java

Publicado por Rodrigo (623 intervenciones) el 03/05/2020 07:26:17
No he visto el contenido del ultimo envio que has incluido, considerare que tomaste los codigos presentados previamente por Kabuto.

Ese codigo es posible que optimizar de varias maneras.

Esta el ciclo que recorre la palabras y por cada una de ellas se recorre el archivo completo, y por cada linea se crea el patron.
Primera optimizacion: no crear el patron dentro del ciclo, sino fuera de el.
Solo ese cambio podrias producir un cambio.

Segunda Optimizacion, no seguir leyendo el archivo si ya se encontro la palabra.

Esos 2 cambios ya deberian tener un mejor tiempo de ejecucion de lo que ya tienes.

Tercera optimizacion, que es alternativa a las otras 2: no hacer el ciclo del archivo dentro del ciclo de palabras, sino hacerlo al reves, el ciclo de palabras dentro del ciclo del archivo. Esto aparentemente no ofrece ninguna optimizacion, pero este segundo ciclo deberia tener una condicion que evalue si la palabra ya fue encontrada antes y no preguntar nunca mas si ella ya fue descubierta antes.

Algo asi:

1
2
3
4
5
6
7
8
9
10
11
for (String linea: texto) {
    for (Palabra pal: palabras) {
        if(!pal.getEncontrada()) {
            //Creamos patrón para la expresion regular con Palabra actual
            String patron = " \\b" + pal.getPalabra() + "\\b";
            Pattern patr = Pattern.compile(patron);
            Matcher mt = patr.matcher(linea);
            pal.setEncontrada(mt.find());
        }
    }
}

4ta optimizacion: Dejar de iterar ambos ciclos si ya todas las palabras han sido encontradas.
5ta optimizacion: Que la clase Palabra compile y mantenga el patron, para no tener que crearlo cada vez que se itere.

En ese caso, el codigo podria quedar asi:

1
2
3
4
5
6
7
for (String linea: texto) {
    for (Palabra pal: palabras) {
        if(!pal.getEncontrada()) {
            pal.evaluar(texto);
        }
    }
}

suponiendo que la funcion evaluar existe en la clase Palabra, toma el texto y revisa si la palabra esta contenida o no, y cambia el valor interno de encontrada.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Rodrigo
Val: 2.041
Plata
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Comparar Archivos en Java

Publicado por Rodrigo (623 intervenciones) el 03/05/2020 08:00:24
Me acabo de dar cuenta que es posible optimizar el uso de memoria tambien.
El vector texto no es necesario crearlo.
La logica que aparece mas arriba se puede poner al interior del ciclo que lee el archivo.
En vez de guardar las lineas del archivo en el vector, se pregunta si alguna de las palabras aparece en esa linea, y luego se descarta la linea.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar