Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - Kabuto

Páginas: 1 ... 39 40 41 42 43 [44] 45 46 47 48 49 50
861
Para trazar esto.... se necesita papel, lápiz y bebidas azucaradas para tener combustible en la sesera ja ja...

Viendo tu explicación, ahora me doy cuenta de lo evidente.
Que en cuanto un arbol tiene al menos dos hojas, entonces se dará esta condicion:
Código: [Seleccionar]
else if (izq != null && der != null)
return izq.cuentaHojas(hojas) + der.cuentaHojas(hojas);
y se retornará, al menos, una suma de resultados: 1 + 1.

Si hay 3 hojas, se retornaría una suma recursiva (los parentesis representan la suma recursiva):
 (1 + 1) + 1 si la ramificacion más profunda está por la izquierda,
 1 + (1 + 1) si estuviese por la derecha.

Si hay 4 hojas: (1 + 1) + (1 + 1)

5 hojas: ((1 + 1) + 1) + (1 + 1) si la ramificación más profunda estuviese a la izquierda

etc...

En definitiva, excepto cuando solo hay una hoja en todo el arbol, a partir de dos o más hojas siempre tendremos sumas y más sumas recursivas.

De ahí que no se cumpla mi inicial temor de que solo iba a recibir un 0 incrementado en 1.
Yo no veía en qué momento ese 0 incrementado en 1, llegaría a ser un 1 incrementado a 2, y luego un 2 incrementado a 3, etc....
Y es que esto no ocurre nunca, y de hecho ¡¡no hace falta que ocurra!!
Lo que recibimos son una suma de muchos 0 incrementados en 1.

Y por ello, el método funciona perfectamente, ¡¡oh yeah!!

De hecho funciona así precisamente porque el dato primitivo se está pasando "por valor"
Si estuviese pasandose "por referencia", ocurriría un despropósito.
Y lo acabo de comprobar modificando los metodos para en lugar de pasarle un 0 como int primitivo, pasarle un vector int[] que contiene el 0.

Cambio en clase Nodo:
Código: [Seleccionar]
public int cuentaHojas(int[] hojas) {
if (izq == null && der == null)
return ++hojas[0];//No hay nodos, es una hoja
else if (izq != null && der != null)
return izq.cuentaHojas(hojas) + der.cuentaHojas(hojas);
else if (izq != null && der == null)
return izq.cuentaHojas(hojas);
else
return der.cuentaHojas(hojas);
}

Cambio en clase Arbol:
Código: [Seleccionar]
public int contarHojas() {
int[] v = {0};
return raiz.cuentaHojas(v);
}

De este modo, el conteo de hojas falla y me dice que hay 10, en lugar de 4.


Y yo que ayer pensaba que quizás me funcionaba porque de algún modo el 0 int primitivo estaba pasándose "por referencia"...

Vaya giros inesperados da la vida ja ja ja ...

Muy didáctico ha sido este ejercicio. Un saludo.

862
La verdad es que es muy interesante.

Y también me fascina el potencial de la Recursividad.

De hecho, aún sigo dándole vueltas a este método:
Código: [Seleccionar]
public int cuentaHojas(int hojas) {
if (izq == null && der == null)
return ++hojas;//No hay nodos, es una hoja
else if (izq != null && der != null)
return izq.cuentaHojas(hojas) + der.cuentaHojas(hojas);
else if (izq != null && der == null)
return izq.cuentaHojas(hojas);
else
return der.cuentaHojas(hojas);
}

Está escrito por mí, y funciona perfectamente... pero cuando lo escribí estaba seguro de que no iba a funcionar. De que no podía ser tan fácil.
Este método siempre se invoca desde la clase Arbol sobre el nodo raiz, pasándole un int con valor 0.
Al ser un tipo de dato primitivo, y que por lo tanto se pasa "por valor" y no "por referencia", estaba convencido que daba igual por cuantas ramificaciones viajase.
Al final me llegaría retornado un valor 1, ya que al encontrar una "hoja", el valor se incrementa.
Pero el resto de "hojas" no saben (o eso creo...) que las otras "hojas" han incrementado ese valor.
Cuando una "hoja" incrementa, retorna el valor, no lo transfiere a otras invocaciones del método para que vayan acumulándose los incrementos.
Así que en teoría todas las "hojas" existentes reciben un 0 y lo incrementan en 1.
Por esto pensaba que iba a recibir un 1 sin importar cuantas hojas hubiesen realmente.

Pero no..., resulta que recibimos todos los incrementos debidamente acumulados.... y aún no estoy seguro de por qué.... xDD
Intento hacer una "traza mental" de este código pero no soy capaz, es dificil con tantas llamadas recursivas. Además trabajo varias horas al dia y me deja bastante incapacitado mentalmente je je...

A ver si el domingo con calma, me lo miro bien como es el proceso que se lleva a cabo con este código.

¿Es quizás que la variable int se pasa "por valor" en la primera invocación inicial que hacemos en el nodo raiz, pero a partir de ahí el resto de invocaciones recursivas lo reciben "por referencia"?
No se si tiene sentido esto que digo... Me voy a dormir.

863
Aprender a programar desde cero / Re:Arboles Binarios en java
« en: 10 de Julio 2018, 22:11 »
Hola,

Nunca habia trabajado con arboles binarios en programación, así que esta consulta ha despertado mi curiosidad y he creado mi propio código para representar un Arbol Binario, obteniendo también una posible solución a tu consulta sobre obtener una LinkedList con los "nodos hoja".
Aunque claro, la solución que yo doy está adaptada a mi código, que podría ser radicalmente distinto al tuyo y a los tipos de clases que estes utilizando.
Aún así, quizás te sirva al menos de inspiración.

En mi caso, creo que he conseguido una representación bastante simple de un arbol.
Aquí la auténtica magia está en hacer buen uso de la "recursividad" para poder viajar a través de los nodos del arbol obteniendo la información que podamos necesitar.

Tan solo he necesitado tres clases: Nodo, Arbol y una clase Test con el main() para crear el arbol y ver si consigo datos correctos de él.

Para comprobar si mi código funciona he tomado como referencia los valores de ejemplo que puso el maestro Ogramar en el otro post que habéis enlazado.


Con esta serie de prueba (60 75 66 85 42 14 73 72 2 54) el árbol que genera sería este:



Así es fácil comprobar si estoy obteniendo los resultados correctos.

Una vez creado el arbol, le pido que me informe de la altura (empezando a contar desde 0 para el "nivel raiz" ), de la cantidad de nodos totales, cantidad de nodos hoja y una lista de los valores de los nodos hoja obtenidos mediante una LinkedList.
Aparentemente parece que obtengo los resultados correctos en la consola de salida:
Citar
Altura del arbol(1er nivel es 0): 4
Cantidad de nodos: 10
Cantidad de hojas: 4
Los valores de los nodos hoja son : 2 54 72 85


Así que doy por hecho que mi código es correcto, y eso que la "recursividad" es algo que tengo bastante verde..., de hecho el método para contar "nodos hoja" no esperaba que funcionase tal y como lo he escrito je je..

Bien, aquí os dejo mis clases para que las probéis, comentéis y a ver si hay suerte y pueden seros útiles.

La clase Nodo es la más importante. Sus atributos son un valor entero y dos objetos más de la misma clase Nodo, es decir, dos "nodos hijos", los cuales se inician como null al principio y luego se instanciarán en nuevos nodos si el "nodo padre" recibe el valor adecuado.
Lo realmente importante, son los métodos, que como dije antes con la magia de la recursividad se consiguen maravillas con unas pocas lineas de código.
Lo cierto es que casi hay más lineas de comentarios documentando la clase, que lineas de código....

Clase Nodo:
Código: [Seleccionar]
package arbol;

import java.util.LinkedList;

public final class Nodo {

private int valor;
private Nodo izq;
private Nodo der;

public Nodo(int valor) {
this.valor = valor;
izq = null;
der = null;
}

public int getValor() {
return valor;
}

/**
* Este es el método más importante ya que es donde se decide a que lado se ramificará
* el nodo segun el valor recibido y a que altura del arbol se situará.<br>
* Por ello este metodo recibe dos argumentos: el valor para un nuevo nodo y la altura incial.<br>
* Esta altura se irá incrementando según descendemos por el arbol binario hasta poder crear un nuevo nodo
* con el valor proporcionado. La altura incrementada será retornada para así poder controlar hasta que altura
* hemos tenido que descender y así la clase <b>Arbol</b> tendrá un control en tiempo real de su altura actual.<br><br>
* El proceso consiste en comparar el valor recibido con el valor de este nodo: si es menor se ramificará a la izquierda y
* si es mayor se ramificará a la derecha. En el caso de que el valor recibido sea IGUAL al del nodo actual, no se creará
* ningún nodo nuevo.<br><br>
* Al ramificar a un lado u otro, lo que hacemos es preguntar si por ese lado hay ya un nodo o no.<br>
* Si no lo hay (encontramos un null en lugar de un nodo), creamos un nuevo <b>Nodo</b> y devolvemos la <i>altura</i> incrementada.<br>
* Si existe ya un <b>Nodo</b>, hacemos una llamada recursiva de este método pasando el valor y también la <i>altura</i> incrementada.<br>
* <br>De este modo, el valor irá pasando de nodo en nodo de manera recursiva hasta encontrar un sitio donde colocarse y retornaremos
* el valor de la altura incrementada según la cantidad de niveles (llamadas recursivas) que hayamos avanzado.
* @param v Valor recibido para crear un nuevo nodo.
* @param altura La altura del arbol en la que nos encontramos intentando crear un nuevo nodo. Este valor se incrementará según se
* desciende por el arbol hasta encontrar un hueco donde crear el nodo.
* @return Valor de la altura hasta que hemos tenido que descender hasta conseguir crear un nuevo nodo.
*/
public int recibeValor(int v, int altura) {
if (valor > v) {
if (izq == null)
{
izq = new Nodo(v);
return ++altura;//Puesto que se ha creado un nuevo nodo, se incrementa la altura recibida inicialmente
}
else
return izq.recibeValor(v, ++altura);//Llamada recursiva, imcrementamos la altura ya que pasamos al siguiente nivel del arbol
}
else if (valor < v) {
if (der == null)
{
der = new Nodo(v);
return ++altura;
}
else
return der.recibeValor(v, ++altura);
}
else
return altura;//En el caso de recibir un valor IGUAL al del nodo actual, cuyo caso no se crea nuevo nodo
}

/**
* Este metodo "viaja" a través del arbol contando los nodos existentes.<br>
* Para ello comprueba si existen o no "nodos hijos" a izquierda y derecha.
* Si encuentra nodos hijos, hace una llamada recursiva de este método para seguir
* buscando nodos por cada ramificación donde existan nodos.
* @return Cantidad de nodos encontrados a partir del nodo donde se invoca al método.
*/
public int cuentaNodos() {
if (izq == null && der == null)
return 0;//No hay nodos, es una hoja
else if (izq != null && der != null)
return 2 + izq.cuentaNodos() + der.cuentaNodos();//Tiene 2 nodos. Sumamos 2 + las nodos que encontremos a continuacion
else if (izq != null && der == null)
return 1 + izq.cuentaNodos(); //Solo 1 nodo, el izquierdo. Sumamos 1 más los nodos que vayamos encontrando
else
return 1 + der.cuentaNodos();//Solo 1 nodo, el derecho.

}

/**
* Este metodo "viaja" a través del arbol contando las "hojas" existentes.<br>
* Una "hoja" es un nodo del cual no cuelga ningún otro nodo, por lo cual usaremos
* una variable que se irá pasando recursivamente a traves de las ramificaciones hasta encontrar
* hojas que será cuando se incremente el valor de la variable contador.<br>
* Esta variable contador se pasa como argumento desde la clase <b>Arbol</b> incializada a 0 y
* finalmente es recogida con todos los incrementos ocurridos al encontrar hojas.
* @param hojas Contador de hojas que se va pasando recursivamente por cada nodo.
* @return Cantidad de hojas encontradas desde el nodo donde se ha invocado el método.
*/
public int cuentaHojas(int hojas) {
if (izq == null && der == null)
return ++hojas;//No hay nodos, es una hoja
else if (izq != null && der != null)
return izq.cuentaHojas(hojas) + der.cuentaHojas(hojas);
else if (izq != null && der == null)
return izq.cuentaHojas(hojas);
else
return der.cuentaHojas(hojas);
}

/**
* Este metodo "viaja" a través del arbol recopilando el valor de los "nodos hoja" existentes.<br>
* EStos valores se almacenan en una LinkedList invocada desde la clase <b>Arbol</b> e irá viajando
* de manera recursiva por todas las ramificaciones del arbol buscando "nodos hoja" y obteniendo su valor.
* @param lista Listado de valores de los "nodos hoja"
*/
public void listarHojas(LinkedList<Integer> lista) {
if (izq == null && der == null) {
lista.add(valor);
}
else if (izq != null && der != null)
{
izq.listarHojas(lista);
der.listarHojas(lista);
}
else if (izq != null && der == null)
izq.listarHojas(lista);
else
der.listarHojas(lista);
}
}

El método recibeValor() es el más interesante. Es quién, cuando el arbol recibe un nuevo valor entero, decide por donde ha de ramificarse el arbol y hasta que nivel para crear el nuevo nodo.
Además para facilitar la tarea de conocer la "altura" del arbol, este método informa hasta que nivel ha descendido para poder crear el nodo.
Este dato lo recibe la clase Arbol y así cada vez que se crea un nuevo nodo, sabe si su altura ha aumentado o no.

Los siguientes métodos de la clase Nodo son muy similares en estructura, solo cambia el tipo de operacion a realizar.


Pasamos a la Clase Arbol
Código: [Seleccionar]
package arbol;

import java.util.LinkedList;

public final class Arbol {

private Nodo raiz;
private int altura;

public Arbol(int valor) {
raiz = new Nodo(valor);
altura = 0;
}

public int getAltura() {
return altura;
}

public void insertarValor(int valor) {
int alturaAlcanzada = raiz.recibeValor(valor, 0);//El control de altura comienza desde 0
/*
* Actualizamos la altura del arbol según el valor recibido.
* Si para crear el nuevo nodo se ha alcanzado una altura superior
* a la altura actual del arbol, es que el arbol "ha crecido" y se ha de actualizar.
*/
if (alturaAlcanzada > altura)
altura = alturaAlcanzada;
}

public int contarNodos() {
return 1 + raiz.cuentaNodos();
}

public int contarHojas() {
return raiz.cuentaHojas(0);
}

public LinkedList<Integer> getListadoHojas() {
LinkedList<Integer> listadoHojas = new LinkedList<Integer>();
raiz.listarHojas(listadoHojas);
return listadoHojas;
}
}

Clase muy, muy simple.
Sus atributos son un "nodo raiz" (que a su vez contiene subnodos que se irán ramificando) y un entero para controlar en todo momento la altura actual del arbol.
Este atributo no es estrictamente necesario, pero simplifica el hecho de obtener después este dato.

Sus métodos no hacen gran cosa, tan solo pedir al objeto Nodo que haga el "trabajo duro" y retornar los datos obtenidos.

El método getListadoHojas(), junto con el método listarHojas() de la clase Nodo,  son quienes dan una posible solución a obtener una LinkedList con los valores de los "nodos hoja".

Por último la clase Test:
Código: [Seleccionar]
package arbol;

import java.util.LinkedList;

public final class Test {

private static Arbol arbol;
private final static int[] valores = {60, 75, 66, 85, 42, 14, 73, 72, 2, 54};

public static void main(String[] args) {

//Creamor arbol con el valor inicial
arbol = new Arbol(valores[0]);
//Insertamos siguientes valores
for (int i = 1; i < valores.length; i++)
arbol.insertarValor(valores[i]);

System.out.println("Altura del arbol(1er nivel es 0): " + arbol.getAltura());
System.out.println("Cantidad de nodos: " + arbol.contarNodos());
System.out.println("Cantidad de hojas: " + arbol.contarHojas());
System.out.print("Los valores de los nodos hoja son : ");
LinkedList<Integer> listaHojas = arbol.getListadoHojas();
for (Integer valor: listaHojas)
System.out.print(valor + " ");

}

}

Se declara un objeto Arbol y un vector con los valores enteros que usaremos para crear nodos a modo de prueba, que son los valores de la imagen publicada anteriormente.

Una vez creado el Arbol, le pedimos los datos que queremos conocer y podemos comprobar que son correctos, si nos fijamos en la imagen con los valores de muestra.

Un saludo.

864
Hola.

El problema se debe a un pequeño fallo. Muy pequeño, pero suficiente para que el programa no funcione correctamente.

El problema está en el primer bucle for, te lo marco en rojo:
Citar
for(int i=0;i<aux.length;i++){
         if(aux[0].charAt(i)=='a'||aux[0].charAt(i)=='e'||aux[0].charAt(i)=='i'||aux[0].charAt(i)=='o'||aux[0].charAt(i)=='u'){
            ux=aux[0].charAt(i);
            System.out.println(ux);
            res[cont]=ux;
            
            cont+=1;
         }
      }

Ahí le estás diciendo el bucle que aumente el contador según la longitud de aux.
Pero claro, aux es un array con un solo elemento, un String. Así que ese bucle solo se repite una vez.
Porque aux.length = 1

Para que funcione, tienes que decirle al bucle que aumente el contador según la longitud del String que hay dentro de aux.
Es decir, según lo que mida aux[0].

Si cambias este pequeño detalle, ya si funcionará. Te lo señalo en verde como ha de quedar.

Citar
for(int i=0;i<aux[0].length();i++){
         if(aux[0].charAt(i)=='a'||aux[0].charAt(i)=='e'||aux[0].charAt(i)=='i'||aux[0].charAt(i)=='o'||aux[0].charAt(i)=='u'){
            ux=aux[0].charAt(i);
            System.out.println(ux);
            res[cont]=ux;
            
            cont+=1;
         }
      }

Con esto ya funciona.

Por otro lado, no es una solución muy elegante para un ejercicio.
Esta bien como prueba inicial, pero hay cosas que se deben mejorar.
Por ejemplo, el arreglo de char lo declaras con una longitud de [2] porque tú ya sabes que solo hay dos vocales.

Habría que pensar una forma de solucionarlo sin saber de antemano cuantas vocales vamos a encontrar.

Además este código está pensado para un arreglo con un solo y único String. También sería interesante hacerlo de manera que sirva para arreglos de cualquier tamaño, ya tenga solo 1 elemento, 5, 25,  o los que sean...

865
Hola.
Basta con que "relajes" la restricción del modificador de acceso del ArrayList en la clase Implementacion.

Ahora mismo está como private, la más restrictiva. A este nivel solo los métodos o clases declarados dentro de la clase Implementación (dentro de una clase, puedes crear otras clases... es lo que se llama "anidar clases" (Nested Classes)) pueden ver el ArrayList.
Por eso antes el método main() podía acceder a él. Pero ahora que lo has sacado a otra clase, ya no puede verlo. Ha quedado fuera de su alcance (scope).

Por norma habitual, y por la filosofía de "encapsulamiento", siempre se recomienda que los atributos sean private y controlar su acceso "al exterior" mediante getters y setters.
Esto es importante sobre todo cuando escribimos clases y programas que vamos a compartir con otros programadores, y no queremos que estos metan la pata accediendo a "a lo loco" a estos atributos, ya que no conocen los entresijos de nuestro código y pueden hacer un uso erróneo de estos atributos.

Pero, si es un código que escribimos para nosotros, y que sabemos lo que nos hacemos y tal... podemos relajar el control de acceso a los atributos si esto nos ayuda a hacer más fácil el código.
De nuevo, la norma dice que debemos ir aumentando el nivel escalonadamente, de más restrictivo a menos, hasta que encontremos el nivel que necesitemos sin "abrir las puertas" del todo.

Hay cuatro niveles de acceso:
Código: [Seleccionar]
private ArrayList<Medicamentos> medicamentos = new ArrayList<>();private ya lo conocemos. El atributo solo es visible dentro de su propia clase.
Este ahora mismo no te sirve. Puedes salvarlo haciendo un getter que devuelva el ArrayList de Medicamentos.
O si no, pasar al siguiente nivel:

Código: [Seleccionar]
ArrayList<Medicamentos> medicamentos = new ArrayList<>();El siguiente nivel, es no poner ningún modificador de acceso. Así de simple.
A este nivel se le llama default y hace que el atributo sea visible a todas las clases que pertenezcan al mismo paquete (package)
Con este nivel ya te serviría para tu proposito. Tu nueva clase Main, al estar en el mismo paquete que Implementacion, podría acceder al ArrayList sin problemas.

Código: [Seleccionar]
protected ArrayList<Medicamentos> medicamentos = new ArrayList<>();El siguiente escalón es protected. Aquí le abrimos la puerta de acceso a clases de otros paquetes, pero solo si son subclases (es decir, que heredan) de Implementacion.

Esto significa que una clase de otro package declarada como:
Código: [Seleccionar]
class nuevaClase extends ImplementacionSí podría acceder al ArrayList, porque es una subclase. De lo contrario, no podría.

Código: [Seleccionar]
public ArrayList<Medicamentos> medicamentos = new ArrayList<>();Este es último nivel. Con public  abrimos la puerta para que cualquier clase, de cualquier paquete, pueda acceder al ArrayList y hacer con él lo quiera.

Esto significa que cualquier programador al que le pases tu clase Implementacion,podrá instanciar un objeto de esta clase y acceder libremente al ArrayList de Medicamentos, tal vez sin saber a ciencia cierta si es un ArrayList, o sin saber que tipo de datos puede albergar, o sin saber cuál es su propósito dentro del programa ni que importancia tiene.
Y si esto fuese un programa profesional, del mundo real, este ArrayList sería muy importante porque básicamente es una base de datos donde se estaría guardando todo el stock de productos de una empresa farmaceutica.
Así que si este programador es un poco osado o torpe, y piensa que en un momento dado se le puede poner valor null a ese atributo llamado medicamentos que no sabe muy bien lo que es (muy torpe hay que ser, pero los hay...) pues podría hacer perder una información valiosísima para la empresa.

Por esto debemos ser muy cuidadosos a la hora de declarar como public un atributo, porque lo estamos dejando "indefenso" ante otros programadores que no conocen a fondo nuestra clase.

En cambio, poniéndolo como private y usando getters y setters para establecer unas normas de seguridad de como debe usarse este atributo, evitamos errores y hacemos que nuestra clase sea sólida y fiable.
Por ejemplo (en plan humor):
Código: [Seleccionar]
if (nuevoArrayRecibido == null)
    mostrarMensajeAlerta("Pero cómo se te ocurre pasarme un null, cerebro de melón..");
else
{
    medicamentos = nuevoArrayRecibido;
    mostrarMensajeInformativo("Nuevo Array aceptado. Datos farmaceutica actualizados");
}

Bueno, y tras estas explicaciones (puedes ver más en un capitulo del curso de Aprender A Programar, volvamos a tu programa.

En Implementacion, basta con que elimines el modificador de acceso private al ArrayList de Medicamentos y no pongas nada. Así estaría en default, suficiente para que la clase Main tenga acceso a este array.

Luego en la clase Main, en realidad no necesitas declarar ningún atributo, ni tampoco usar ningún constructor.
Lo único importante es que lo primero que haga el programa sea instanciar la clase Implementacion que es por así decirlo, el "director de la orquesta" y el resto de clases dependen de ella.
Y así es como lo tienes, por tanto, basta con que elimines los atributos y el constructor, porque no los necesitas.
Ahora Main ya puede ver el ArrayList de Medicamentos y puede encargarse de pasárselo al resto de clases.

Pongo en comentario, lo que puedes quitar (atributos y constructor).
Clase Main
Código: [Seleccionar]
package farmaceutica;

import java.io.*;
import java.util.ArrayList;
import javax.swing.JOptionPane;

public class Main
{
//private File archivo = new File("archiyect.txt");
//private ArrayList<Medicamentos> medicamentos = new ArrayList<>();
/*
public Main(ArrayList<Medicamentos> medicamentos)
{
this.medicamentos = medicamentos;
}*/

public static void main(String args[])throws FileNotFoundException, IOException
{   
//Inicializamos implementacion, quien tiene el ArrayList de Medicamentos
Implementacion implementacion = new Implementacion();
//Inicializamos el objeto que contiene las funciones del programa
AltasListado al = new AltasListado(implementacion.medicamentos);//Recibe el ArrayList de Medicamentos.
Modificacion modifica = new Modificacion(implementacion.medicamentos);
Consultas consultas = new Consultas(implementacion.medicamentos);
Bajas bajas = new Bajas(implementacion.medicamentos);

String opcions;
int opcion;
do{
opcions = JOptionPane.showInputDialog ("Menu\n 1.Altas productos\n 2.Listado de productos\n 3.Consulta de productos\n 4.Bajas\n 5. Modificacion 6.SALIR\n");
//opcions = JOptionPane.showInputDialog ("Menu\n 1.Altas productos\n 2.Consulta productos\n 3.Baja porductos\n 4.Modificacion de un producto\n 5.Listado de productos\n 6. Salir\n ");
opcion=Integer.parseInt (opcions);
switch(opcion)
{
case 1:
al.altas();
break;
case 2:
al.listado();
break;
case 3:
String opcionl;
int opc;
do{
opcionl=JOptionPane.showInputDialog ("Menu\n 1.Busqueda por clave\n 2.Busqueda por nombre\n 3.SALIR");
opc=Integer.parseInt(opcionl);
switch(opc){
case 1:
consultas.consultasc();
break;
case 2:
consultas.consultasn();
break;
}
}while(opc!=3);
break;
case 4:
bajas.mebajas();
break;
case 5:
modifica.modificar();
break;
case 6:
JOptionPane.showMessageDialog(null, "FIN del programa");
break;
default:
JOptionPane.showMessageDialog(null, "Opcion invalida");

}while(opcion!=6);
}
}

Creo que con esto ya debería funcionar. Ya nos contarás.
Un saludo.

866
Pues acabo de probar tu código para hacer listado, y me funciona perfectamente.
Ahí salen las tres lineas que tengo en mi archivo de texto:



No se que puede fallarte. Comprueba que en todas las clases estás usando la misma ruta para el archivo.

También puedes comprimir todas tus clases en un zip y adjuntarlas aquí en el foro en tu próximo mensaje.
Para adjuntar, bajo el campo de texto donde escribes tu mensaje, verás una opcion llamada "Opcionas Adicionales" donde puedes adjuntar un archivo.

Así puedo probar tus clases tal cuál tú las tienes. A ver si hay alguna sutil diferencia que hayamos pasado por alto.

867
Pues ya no se decir que puede estar fallando.
A mi me funciona todo: altas, bajas, modificaciones, consulta..

En este mensaje te adjunto un .zip  (lo verás al final del mensaje) con mis clases, descárgalo, crea un nuevo package con él y comprueba su funcionamiento.

Por el error que pusiste antes:

Código: [Seleccionar]
java.lang.NullPointerException
at java.io.Writer.write(Writer.java:157)
at CrearFile2.setModificar(CrearFile2.java:237)
at MenuV2.setMenuV2(MenuV2.java:50)
at MenuBueno.main(MenuBueno.java:12)

...parece que falla justo en la linea en la que empieza a escribir los cambios en el archivo:

Citar
if (archivo.delete())
            {
               BufferedWriter bw = new BufferedWriter(new FileWriter(archivo, true));
               for (String line: lineas)
               {
                  bw.write(line);
                  bw.newLine();
               }
               bw.close();

Pero no se por qué, el código parece exactamente igual al mío...

868
Hola.

Veo que has creado una nueva clase específica, llamada Modificar,  para el método .setModificar().

Si quieres hacerlo así, has de hacer algunos cambios. Quizás ya los has hecho, pero por si a caso te los indico.

En la clase MenuV2, tendrás que instanciar un objeto de esta clase, tal y como haciamos con la clase CrearFile2

Citar
public final class MenuV2 {
   
   private CrearFile2 cf2 = new CrearFile2();
   private Modificar mod = new Modificar();

   public MenuV2()
   {}

Y despues, en el switch del menú, llamamos el metodo setModificar(), de esta nueva clase, no la de la antigua:

Citar
   case 2:
            cf2.setEliminar(); break; 
         case 3:
            cf2.setConsulta();break;
         case 4:
            cf2.setModificar();
            mod.setModificar();
            break;
         case 5:
            JOptionPane.showMessageDialog(null,"Salio del sistema"); break;


Vale, ahora, respecto a la nueva clase Modificar

Revisa, un par de cosas en la parte donde estaríamos modificando un Proveedor.
1. Comprueba que estás escribiendo el nombre de la clase Proveedor.
Es con una o y dos e.
No con dos oo y una e -- > Proovedor
A no ser que tu hayas declarado esta clase escrita de esta manera, en cuyo caso no debería ser problema para que el programa funcione.

2. Comprueba el atributo telefono del Proveedor si lo tienes declarado como String o como int.
Yo lo tengo como int, por lo tanto, al metodo setTelefono() tengo que pasarselo parseado, ya que del archivo de texto este dato lo obtenemos como tipo String.
ASí que hay que hacer una conversion de tipo de dato en este caso.

Te marco en rojo las líneas donde debes revisar esto:

Citar
else if (linea.endsWith("Proveedor"))//La linea pertenece a la clase Proveedores
      {
         String[] datosProveedores = linea.split("\\|");

         Proveedores pr = new Proveedores();
         pr.setNombre(datosProveedores[0]);
         pr.setDireccion(datosProveedores[1]);
         pr.setCiudad(datosProveedores[2]);
         pr.setEmail(datosProveedores[3]);
         pr.setTelefono(Integer.parseInt(datosProveedores[4]));

Tras todo esto, el programa debería funcionar. A mi me está funcionando.
Lo único que faltaría es añadirle también a esta nueva clase, el metodo de apoyo mostrarDatos(), el que usabamos para coger la "linea fea" con los datos separados por pipes para construir un String y mostrar los datos de forma más elegante.

Te dejo aquí la clase Modificar, tal y como yo la tengo. Ya incluye el metodo mostrarDatos()
Código: [Seleccionar]
import java.io.*;
import javax.swing.JOptionPane;
import java.util.*;

public class Modificar {

File archivo= new File("C:\\Prueba\\EquipoV.txt");
LeerMostrar5 lm5 = new LeerMostrar5();

public Modificar()
{}


public void setModificar()
{
if (archivo.exists())
{
String clave = JOptionPane.showInputDialog("Dame clave a modificar");
try {
ArrayList<String> lineas = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader(archivo));
String linea = br.readLine();
while (linea != null)
{
if (linea.startsWith(clave))
{
int confirmar = JOptionPane.showConfirmDialog(null, mostrarDatos(linea)
+ "\n¿Seguro que quiere modificar?", "Confirmar Modificacion", JOptionPane.YES_NO_OPTION);
if (confirmar == JOptionPane.YES_OPTION)
{
lineas.add(getLineaModificada(linea));
}
else//No quiere modificar
lineas.add(linea);
}
else//Linea no coincide con clave
lineas.add(linea);

linea = br.readLine();
}
br.close();
//Guarda los cambios en el archivo.
if (archivo.delete())
{
BufferedWriter bw = new BufferedWriter(new FileWriter(archivo, true));
for (String line: lineas)
{
bw.write(line);
bw.newLine();
}
bw.close();
JOptionPane.showMessageDialog(null, "Los cambios se han guardado");
}
else//Este en caso de no poder modificar
{
JOptionPane.showMessageDialog(null, "No se ha podido modificar el archivo: " + archivo.getAbsolutePath());
}

}catch(Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, e.getLocalizedMessage());
}
}
else//No existe archivo
JOptionPane.showMessageDialog(null, "No existe fichero: " + archivo.getAbsolutePath());
}

private String getLineaModificada(String linea)
{
String lineaModificada = null;//Esta linea devuelve las modificaciones

if (linea.endsWith("Jugador"))//La linea pertenece a la clase Jugadores
{
String[] datosJugador = linea.split("\\|");
//Construimos un Jugador con los datos obtenidos
Jugadores jugador = new Jugadores();
jugador.setMatricula(Integer.parseInt(datosJugador[0]));
jugador.setNombre(datosJugador[1]);
jugador.setAp(datosJugador[2]);
jugador.setAm(datosJugador[3]);
jugador.setNumeroCa(Integer.parseInt(datosJugador[4]));
jugador.setPosicion(datosJugador[5]);
jugador.setEstatus(datosJugador[6]);
jugador.setSexo(datosJugador[7]);

//Preguntamos por matricula
int respuesta = JOptionPane.showConfirmDialog(null, "Matricula Actual:\n" + jugador.getMatricula() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)//SÍ quiere modificar
jugador.setMatricula(lm5.getMatricula2());

//Preguntamos por nombre
respuesta = JOptionPane.showConfirmDialog(null, "Nombre Actual:\n" + jugador.getNombre() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setNombre(lm5.getNombreJ());

//Apellido Paterno
respuesta = JOptionPane.showConfirmDialog(null, "Apellido Paterno Actual:\n" + jugador.getAp() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setAp(lm5.getApe());

//Apellido Materno
respuesta = JOptionPane.showConfirmDialog(null, "Apellido Materno Actual:\n" + jugador.getAm() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setAm(lm5.getAma());

//Numero Camiseta
respuesta = JOptionPane.showConfirmDialog(null, "Numero Camiseta Actual:\n" + jugador.getNumeroCa() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setNumeroCa(lm5.getNumC());

//Posicion
respuesta = JOptionPane.showConfirmDialog(null, "Posicion Actual:\n" + jugador.getPosicion() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setPosicion(lm5.getPosic());

//Status
respuesta = JOptionPane.showConfirmDialog(null, "Estado Actual:\n" + jugador.getEstatus() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setEstatus(lm5.getEstatus1());

//Sexo
respuesta = JOptionPane.showConfirmDialog(null, "Sexo Actual:\n" + jugador.getSexo() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setSexo(lm5.getSex1());


lineaModificada = jugador.toString();
}
else if (linea.endsWith("Personal"))//La linea pertenece a la clase Personal
{
String[] datosPersonal = linea.split("\\|");

Personal p = new Personal();
p.setClave(Integer.parseInt(datosPersonal[0]));
p.setNombre(datosPersonal[1]);
p.setAp(datosPersonal[2]);
p.setAm(datosPersonal[3]);
p.setPuesto(datosPersonal[4]);
p.setEspecialidad(datosPersonal[5]);
p.setTiempoE(Integer.parseInt(datosPersonal[6]));
p.setSexo(datosPersonal[7]);


int respuesta = JOptionPane.showConfirmDialog(null, "Clave Actual:\n" + p.getClave() + "\n¿Modificar?",
"Modificar Personal", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)//SÍ quiere modificar
p.setClave(lm5.getClave());

//Preguntamos por nombre
respuesta = JOptionPane.showConfirmDialog(null, "Nombre Actual:\n" + p.getNombre() + "\n¿Modificar?",
"Modificar Personal", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
p.setNombre(lm5.getNombrep());

//Apellido Paterno
respuesta = JOptionPane.showConfirmDialog(null, "Apellido Paterno Actual:\n" + p.getAp() + "\n¿Modificar?",
"Modificar Personal", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
p.setAp(lm5.getAp2());

//Apellido Materno
respuesta = JOptionPane.showConfirmDialog(null, "Apellido Materno Actual:\n" + p.getAm() + "\n¿Modificar?",
"Modificar Personal", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
p.setAm(lm5.getAm2());

//Puesto
respuesta = JOptionPane.showConfirmDialog(null, "Puesto Actual:\n" + p.getPuesto() + "\n¿Modificar?",
"Modificar Personal", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
p.setPuesto(lm5.getPuesto1());

//Especialidad
respuesta = JOptionPane.showConfirmDialog(null, "Especialidad Actual:\n" + p.getEspecialidad() + "\n¿Modificar?",
"Modificar Personal", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
p.setEspecialidad(lm5.getEsp());

//Tiempo en la empresa
respuesta = JOptionPane.showConfirmDialog(null, "Estado Actual:\n" + p.getTiempoE() + "\n¿Modificar?",
"Modificar Personal", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
p.setTiempoE(lm5.getTiempoe());

//Sexo
respuesta = JOptionPane.showConfirmDialog(null, "Sexo Actual:\n" + p.getSexo() + "\n¿Modificar?",
"Modificar Personal", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
p.setSexo(lm5.getSex2());

lineaModificada = p.toString();
}
else if (linea.endsWith("Proveedor"))//La linea pertenece a la clase Proveedores
{
String[] datosProveedores = linea.split("\\|");

Proveedores pr = new Proveedores();
pr.setNombre(datosProveedores[0]);
pr.setDireccion(datosProveedores[1]);
pr.setCiudad(datosProveedores[2]);
pr.setEmail(datosProveedores[3]);
pr.setTelefono(Integer.parseInt(datosProveedores[4]));

//Preguntamos por Nombre
int respuesta = JOptionPane.showConfirmDialog(null, "Nombre Actual:\n" + pr.getNombre() + "\n¿Modificar?",
"Modificar Personal", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)//SÍ quiere modificar
pr.setNombre(lm5.getNombrePr());

//Direccion
respuesta = JOptionPane.showConfirmDialog(null, "Direccion Actual:\n" + pr.getDireccion() + "\n¿Modificar?",
"Modificar Proveedores", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
pr.setDireccion(lm5.getDirecpr());

//Ciudad
respuesta = JOptionPane.showConfirmDialog(null, "Ciudad Actual:\n" + pr.getCiudad() + "\n¿Modificar?",
"Modificar Proveedores", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
pr.setCiudad(lm5.getCiudad1());

//Email
respuesta = JOptionPane.showConfirmDialog(null, "Email Actual:\n" + pr.getEmail() + "\n¿Modificar?",
"Modificar Proveedores", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
pr.setEmail(lm5.getEmail());

//Telefono
respuesta = JOptionPane.showConfirmDialog(null, "Telefono Actual:\n" + pr.getTelefono() + "\n¿Modificar?",
"Modificar Proveedores", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
pr.setTelefono(lm5.getTelefono());

lineaModificada = pr.toString();
}

return lineaModificada;//Finalizado el metodo, esta linea contendrá los datos de un Jugador, o un Proveedor o un Personal
}

private String mostrarDatos(String lineaFea)
{
String datosAMostrar;
String[] datos = lineaFea.split("\\|");

if (lineaFea.endsWith("Jugador"))
{
datosAMostrar = "        JUGADOR\n\nMatricula: " + datos[0] + "\nNombre: " + datos[1] + "\nApe. Paterno: " + datos[2]
+ "\nApe. Materno: " + datos[3] + "\nNº Camiseta: " + datos[4] + "\nPosicion: " + datos[5]
+ "\nSexo: " + datos[6];
}
else if (lineaFea.endsWith("Personal"))
{
datosAMostrar = "        PERSONAL\n\nClave: " + datos[0] + "\nNombre: " + datos[1] + "\nApe. Paterno: " + datos[2]
+ "\nApe. Materno: " + datos[3] + "\nPuesto: " + datos[4] + "\nEspecialidad: " + datos[5]
+ "\nTiempo en Empresa: " + datos[6] + "\nSexo: " + datos[7];
}
else if (lineaFea.endsWith("Proveedor"))
{
datosAMostrar = "        PROVEEDOR\n\nNombre: " + datos[0] + "\nDireccion: " + datos[1] + "\nCiudad: " + datos[2]
+ "\nE-Mail: " + datos[3] + "\nTelefono: " + datos[4];
}
else//En el MUY improbable caso de que no pudieramos identificar la clase de la linea...
return lineaFea;//...devolvemos la "linea fea" tal cual. Esta situación no debería ocurrir nunca, pero por si a caso...

return datosAMostrar;
}
}

869
Hola compi.

Hay unos detalles que fallan.

El más importante, que supongo que es por lo que te salen vacio el archivo, es que en Implementacion estás usando la ruta de archivo que yo uso en mi ejercicio.
Código: [Seleccionar]
private File archivo = new File("c:\\prueba\\archiyect.txt");
En las otras clases, estás usando tu ruta habitual:
Código: [Seleccionar]
private File archivo = new File("archiyect.txt");
Por eso no ves los cambios.
Corrigelo para que todos tengan la misma ruta de archivo.
Incluso si quisieras, igual que a Metodo y Modificacion les estamos pasando a su constructor el ArrayList que deben usar, también se les podría pasar el objeto File que deben usar.
Así solo tendrías que declarar una vez la ruta en Implementacion y el resto lo recibirían de esta.


Otra cosa que faltaría es que en Modificacion, también se han de escribir los cambios en el archivo de texto.
Se procedería igual que en Bajas, borramos el archivo actual, y volvemos a crearlo con los nuevos datos.
Te pongo aquí como lo he hecho yo:
Código: [Seleccionar]
package farmaceutica;

import javax.swing.JOptionPane;
import java.io.*;
import java.util.ArrayList;

public class Modificacion
{
private File archivo = new File("c:\\prueba\\archiyect.txt");
private ArrayList<Medicamentos> medicamentos = new ArrayList<>();

public Modificacion(ArrayList<Medicamentos> medicamentos)
{
this.medicamentos = medicamentos;
}
private String mensajeMedicamento(Medicamentos m)
{
return "Clave: " + m.getClave()
+ "\nNombre: " + m.getNombre()
+ "\nPrecio: " + m.getPrecio()
+ "\nExistencias: " + m.getExistencia()
+ "\nNombre Generico: " + m.getNombregenerico()
+ "\nCaducidad: " + m.getCaducidad()
+ "\nForma Farmaceutica: " + m.getFormafarmaceutica()
+ "\nConcentracion: " + m.getConcentracion();
}


public void modificar()throws FileNotFoundException,IOException
{
if (medicamentos.isEmpty())
JOptionPane.showMessageDialog(null, "No hay Medicamentos registrados");
else
{
String clave = JOptionPane.showInputDialog("Introduzca la clave del Medicamento para modificar:");
boolean encontrado = false;//Para controlar si lo hemos encontrado
for (int i = 0; i < medicamentos.size(); i++)
{
if (medicamentos.get(i).getClave().equalsIgnoreCase(clave))
{
encontrado = true;
String mensaje = mensajeMedicamento(medicamentos.get(i)) + "\n\n¿Desea modificar este medicamento?";
int confirmar = JOptionPane.showConfirmDialog(null, mensaje, "Confirmar Modificacion", JOptionPane.YES_NO_OPTION);
if (confirmar == JOptionPane.YES_OPTION)//SI quiere modificar
{
medicamentos.remove(i);
String claved = JOptionPane.showInputDialog("cual es la nueva clave del producto");
String nombre = JOptionPane.showInputDialog("cual es el nuevo nombre del producto");
int precio = Integer.parseInt(JOptionPane.showInputDialog("cual es el nuevo precio del producto"));
int existencia = Integer.parseInt(JOptionPane.showInputDialog("Cuántos productos hay en existencia"));

Medicamentos nuevoMed = new Medicamentos(claved,nombre, precio, existencia);
medicamentos.add(nuevoMed);

/*
* También podría hacer sin necesida de borrar --> .remove()
* y luego añadir uno nuevo --> .add()
*
* Se podría modificar directamente los atributos del
* objeto almacenado en el ArrayLis:
*
* medicamentos.get(i).setClave(claved);
* medicamentos.get(i).setNombre(nombre);
* etc...
*
*/

//Puesto que ha habido una modificacion, esta ha de guardarse en el archivo texto.
//Como hacíamos en las bajas, lo más fácil es eliminar el archivo y volver a crearlo
//con los nuevos datos.

try{
if (archivo.delete())
{
BufferedWriter escribir = new BufferedWriter(new FileWriter(archivo, true));
for (Medicamentos m:medicamentos)
{
escribir.write(m.toString());
escribir.newLine();
}
escribir.close();
JOptionPane.showMessageDialog(null, "Medicamento Modificado.\nLos cambios se han guardado", "Modificacion de Medicamento",
JOptionPane.INFORMATION_MESSAGE);
}
else//Por algun motivo, no se pudo borrar archivo
{
JOptionPane.showMessageDialog(null, "Error de acceso a archivo.\nLos cambios no han sido guardados", "Modificacion de Medicamento",
JOptionPane.WARNING_MESSAGE);
}
}catch(IOException e){
JOptionPane.showMessageDialog(null, "No se pudo escribir datos en archivo: " + archivo.getAbsolutePath(),
"Error de Escritura", JOptionPane.WARNING_MESSAGE);
}

}

}
}//Fin bucle FOR

if (!encontrado)//Tras recorrer todos los Medicamentos, no se ha encontrado lo que se buscaba
JOptionPane.showMessageDialog(null, "NO se encontro Medicamento con la clave: " + clave, "Baja de Medicamentos",
JOptionPane.INFORMATION_MESSAGE);
}
}
}


También he puesto un comentario explicando que tenemos dos formas de modificar un medicamento.
Una es como tu lo has hecho, lo borramos del ArrayList, pedimos datos y volvemos a crear uno nuevo.

La otra forma sería pedir datos y usarlos para cambiar los atributos directamente en el objeto Medicamento guardado en el ArrayList, usando sus correspondientes setters...

En ambos casos, habría que guardar luego en fichero texto.

Y creo que ya está. Esas dos cositas era lo que fallaba, sobre todo lo la ruta del archivo, ya que estabamos leyendo uno, pero luego guardando en otro.
Por eso siempre te salía vacío.

870
Ahora no puedo probar lo que has hecho.

Pero intuyo que el problema está en que ahora hay dos ArrayList de Medicamentos en memoria, el que crea Metodos y el que está creando ahora tu nueva clase Modificacion.

Estos ArrayList no están sincronizados, así que a lo largo del programa tendrán datos distintos.

Cuando haces una modificación, estás cambiando el ArrayList de la clase Modificacion.
Pero si luego haces una consulta, estás consultando el ArrayList de la clase Metodos. Por eso no ves las modificaciones que haces.

Si quieres que varias clases modifiquen un mismo objeto, lo mejor es que ese objeto lo declares e incialices en un sitio donde luego puedas pasárselo por referencia (luego comentamos que significa esto) a estas clases y así todas están trabajando con el mismo objeto.

Creo que lo más cómodo es declararlo en Implementacion.
En esta clase ahora mismo, solo tenemos el metodo main().

Pero podemos añadirle atributos y un constructor si lo necesitamos, y eso es lo que vamos a hacer.
Código: [Seleccionar]
package farmaceutica;

import java.io.*;
import java.util.ArrayList;

import javax.swing.JOptionPane;
public class Implementacion
{

private File archivo = new File("c:\\prueba\\archiyect.txt");
private ArrayList<Medicamentos> medicamentos = new ArrayList<>();

public Implementacion()
{
if (archivo.exists())
{
try {
BufferedReader leer = new BufferedReader(new FileReader(archivo));
String linea = leer.readLine();
while(linea != null)
{
String[] atributos = linea.split("--");
//Los 4 atributos obligatorios
String clave = atributos[0];
String nombre = atributos[1];
int precio = Integer.parseInt(atributos[2]);
int existencia = Integer.parseInt(atributos[3]);

//Los 4 atributos opcionales
String nombreGenerico;
if (atributos[4].equals("null"))//Este atributo tenía valor null cuando se guardo en el archivo
nombreGenerico = null;
else
nombreGenerico = atributos[4];

int caducidad = Integer.parseInt(atributos[5]);

String formaFarmaceutica;
if (atributos[6].equals("null"))
formaFarmaceutica = null;
else
formaFarmaceutica = atributos[6];

int concentracion = Integer.parseInt(atributos[7]);

medicamentos.add(new Medicamentos(clave, nombre, precio, existencia, nombreGenerico,
caducidad, formaFarmaceutica, concentracion));
//Medicamento añadido, leemos una nueva linea y si contiene datos, se repetirá este proceso
linea = leer.readLine();
}
leer.close();
//Lectura concluida.
//Podemos informar por pantalla cuantos Medicamentos hemos recuperado del archivo
JOptionPane.showMessageDialog(null, "Cantidad de Medicamentos recuperados: " + medicamentos.size(),
"Datos Leidos", JOptionPane.INFORMATION_MESSAGE);
} catch (Exception ex)
{
JOptionPane.showMessageDialog(null, "No se pudo leer datos del archivo: " + archivo.getAbsolutePath(),
"Error de Lectura", JOptionPane.WARNING_MESSAGE);
}
}
}

public static void main(String args[])throws FileNotFoundException, IOException
{   
//Inicializamos implementacion, quien tiene el ArrayList de Medicamentos
Implementacion implementacion = new Implementacion();
//Inicializamos el objeto que contiene las funciones del programa
Metodos metodos = new Metodos(implementacion.medicamentos);//Recibe el ArrayList de Medicamentos.

String opcions;
int opcion;
do{
opcions = JOptionPane.showInputDialog ("Menu\n 1.Altas productos\n 2.Listado de productos\n 3.Consulta de productos\n 4.Bajas\n 5.SALIR\n");
//opcions = JOptionPane.showInputDialog ("Menu\n 1.Altas productos\n 2.Consulta productos\n 3.Baja porductos\n 4.Modificacion de un producto\n 5.Listado de productos\n 6. Salir\n ");
opcion=Integer.parseInt (opcions);
switch(opcion)
{
case 1:
metodos.altas();
break;
case 2:
metodos.listado();
break;
case 3:
String opcionl;
int opc;
do{
opcionl=JOptionPane.showInputDialog ("Menu\n 1.Busqueda por clave\n 2.Busqueda por nombre\n 3.SALIR");
opc=Integer.parseInt(opcionl);
switch(opc){
case 1:
metodos.consultasc();
break;
case 2:
metodos.consultasn();
break;
}
}while(opc!=3);
break;
case 4:
metodos.bajas();
break;
case 5:
JOptionPane.showMessageDialog(null, "FIN del programa");
break;
default:
JOptionPane.showMessageDialog(null, "Opcion invalida");

}while(opcion!=5);
}   
}


Añadimos dos atributos, el objeto File y el ArrayList.

Añadimos un constructor, que hace exactamente lo mismo que hacía el constructor de Metodos. Leerá el fichero de texto, si es que existe, recogerá los datos que contiene y añadirá los Medicamentos que encuentre al ArrayList.

Luego, en el metodo main(), lo primero que hacemos es instanciar a la clase Implementacion. Así su constructor creará el ArrayList.

Luego instanciamos la clase Metodos, solo que esta vez le vamos a pasar como argumento el ArrayList del objeto Implementación.
Así la clase Metodos trabajará con ESTE ArrayList, en lugar de trabajar con uno propio.
Fíjate que le estamos pasando el ArrayList sin necesidad de usar ningún getter o setter.
Estos es porque el método main() pertenece a la clase Implementacion, y por tanto puede ver y acceder directamente a sus atributos, sin tener que usar un metodo public void getArray() ni nada de esto


Luego, tendrías que instanciar tu clase Modificacion y al igual que con Metodos, pasarle el ArrayList de Implementacion.

Así ambas clases trabajaran con el MISMO ArrayList, y las modificaciones que haga uno, las verá el otro.

Ahora, hay que modificar la clase Metodos, ya que ahora mismo no está escrita para recibir un ArrayList externo.

Los cambios que hay que hacer son muy simples, tan solo hay que modificar su constructor.
Antes se encargaba de leer el archivo e inicializar el ArrayList. Esto ahora ya lo hace Implementacion, así que el constructor de Metodos lo único que tiene que hacer ahora es recibir el ArrayList y recogerlo para su atributo.

Código: [Seleccionar]
public class Metodos {

private File archivo = new File("c:\\prueba\\archiyect.txt");
private ArrayList<Medicamentos> medicamentos = new ArrayList<>();

public Metodos(ArrayList<Medicamentos> medicamentos)
{
this.medicamentos = medicamentos;
}

Y para tu clase Modificacion, habría que hacer exactamente lo mismo.

Y creo que con esto, debería funcionarte. Pruébalo y nos lo comentas.


Sobre lo que decía antes de para POR REFERENCIA.
Fíjate que las clases Metodos y Modificacion, aunque cada una declara su propio ArrayList como atributo, en realidad van a trabajar con un UNICO ArrayList, que es el que reciben desde la clase Implementacion

Esto es posible porque este objeto lo reciben POR REFERENCIA.
En programacion, cuando pasamos una variable u objeto a un método o a una clase, hay (principalmente) dos formas de hacerlo: POR REFERENCIA o POR VALOR

Pasar una variable u objeto (son lo mismo en realidad) por VALOR significa que lo que le estamos pasando a la clase/metodo, es una copia de esa variable.
Los cambios que hagamos a esa copia, NO tendrán ningún efecto en la variable original.

Pasar una variable por REFERENCIA significa que NO estamos pasando una copia, si no que lo que estamos pasando es la direccion de memoria donde se encuentra la variable original. Un "acceso directo" por así decirlo.
En este caso, los cambios que hagamos a esta variable, SI tienen efecto en la variable original, porque en realidad solo hay una.
No estariamos trabajando con una copia, sino con la original.

En Java, para bien o para mal... los objetos "complejos" SIEMPRE se pasan por REFERENCIA. No podemos escoger.
Por este motivo, las clases Metodos y Modificacion van a poder trabajar con el mismo ArrayList al mismo tiempo. Porque NO han recibido una copia, han recibido la direccion de memoria donde se encuentra este UNICO ArrayList

En cambio, cuando se trata de variables primitivas (int, char, double, byte...), en Java siempre se pasan por VALOR.
Esto significa que sí se recibe una COPIA del ORIGINAL. Así que si le hacemos un cambio a esta COPIA, tenemos que tener en cuenta que el ORIGINAL no va a cambiar.
Por tanto si queremos trabajar con los cambios que les hemos hecho a la COPIA, tenemos que retornarlo y recogerlos, porque el ORIGINAL no sabe nada de los cambios que hayamos hecho.


En otros lenguajes como C/C++, si podemos escoger de qué modo transmitimos las variables y objetos.
Esto nos da más poder, pero también más responsabilidad (ya lo decia el tio de Spiderman: "Un gran poder conlleva una gran responsabilidad" ).

Más responsabilidad porque si nos despistamos podemos incluso dejar datos en memoria perdidos sin ninguna referencia para encontrarlos, o tener referencias que apuntan a datos equivocados o invalidos.

Java no nos da tanto poder, pero a cambio se encarga de que no haya lios con las referencias y de limpiar datos que hayan podido quedar sin puntero que indique donde están, y en general, nos hace más fácil la vida a los que estamos aprendiendo programacion.

871
Hola.
Entiendo a que te refieres a que ahora mismo, cuando mostramos el dato consultado, lo que mostramos es una linea "fea" con todos los datos separados por los pipes.
Esto se puede mejorar fácilmente, y bastaría con escribir un nuevo método que se encargue de recibir la "línea fea", separar los datos y construir un String más elegante con los datos, el nombre del dato, saltos de linea,...

La "línea fea" la estamos mostrando desde este JOptionPane situado en el metodo setConsulta() de la clase CrearFile2

Código: [Seleccionar]
if (lineaArchivo.startsWith(datoAbuscar))
    JOptionPane.showMessageDialog(null,"Dato Buscado:\n" + lineaArchivo);
Ahí es donde le estamos pasando la "linea fea", tal cual está en el archivo. En vez de eso, lo que le vamos a pasar es el String que nuestro nuevo método va a construir a partir de esa línea.
El método ha de distinguir si la linea pertenece a un Jugador, Proveedor o Personal, pues el texto que va a construir será diferente para cada uno de ellos.
Así que, tal y como hicimos en el metodo getLineaModificada(), preguntaremos cual es la última palabra de la linea para distinguir a que clase pertenece y escribiremos un texto diferente para cada caso.

Este podría ser el método, que estaría incluido en la clase CrearFile2:
Código: [Seleccionar]
private String mostrarDatos(String lineaFea)
{
String datosAMostrar;
String[] datos = lineaFea.split("\\|");

if (lineaFea.endsWith("Jugador"))
{
datosAMostrar = "        JUGADOR\n\nMatricula: " + datos[0] + "\nNombre: " + datos[1] + "\nApe. Paterno: " + datos[2]
+ "\nApe. Materno: " + datos[3] + "\nNº Camiseta: " + datos[4] + "\nPosicion: " + datos[5]
+ "\nSexo: " + datos[6];
}
else if (lineaFea.endsWith("Personal"))
{
datosAMostrar = "        PERSONAL\n\nClave: " + datos[0] + "\nNombre: " + datos[1] + "\nApe. Paterno: " + datos[2]
+ "\nApe. Materno: " + datos[3] + "\nPuesto: " + datos[4] + "\nEspecialidad: " + datos[5]
+ "\nTiempo en Empresa: " + datos[6] + "\nSexo: " + datos[7];
}
else if (lineaFea.endsWith("Proveedor"))
{
datosAMostrar = "        PROVEEDOR\n\nNombre: " + datos[0] + "\nDireccion: " + datos[1] + "\nCiudad: " + datos[2]
+ "\nE-Mail: " + datos[3] + "\nTelefono: " + datos[4];
}
else//En el MUY improbable caso de que no pudieramos identificar la clase de la linea...
return lineaFea;//...devolvemos la "linea fea" tal cual. Esta situación no debería ocurrir nunca, pero por si a caso...

return datosAMostrar;
}

Apoyándonos en este método, ahora al JOptionPane del metodo setConsulta() lo lanzamos así:
Código: [Seleccionar]
if (lineaArchivo.startsWith(datoAbuscar))
JOptionPane.showMessageDialog(null,mostrarDatos(lineaArchivo));

No solo ahí, habría que hacer lo mismo en el método setEliminar():

Código: [Seleccionar]
int confirmar = JOptionPane.showConfirmDialog(null, mostrarDatos(linea)
+ "\n\n¿Seguro que quiere borrar?", "Confirmar Eliminacion", JOptionPane.YES_NO_OPTION);

Y en setModificar():

Código: [Seleccionar]
int confirmar = JOptionPane.showConfirmDialog(null, mostrarDatos(linea)
+ "\n\n¿Seguro que quiere modificar?", "Confirmar Modificacion", JOptionPane.YES_NO_OPTION);

Y con esto ya queda algo más elegante cuando mostramos los datos.
Comprueba como funciona y ya luego tu decides si quieres construir el mensaje a mostrar de otra forma distinta.

Lo importante es comprender que lo que hacemos es un metodo que coge la linea de texto, la trocea para identificar los datos, construye un mensaje de presentación y lo devuelve en un String que podemos mostrar desde un JOptionPane o donde sea que podamos necesitarlo.

Un saludo.

872
Metodos
Código: [Seleccionar]
import javax.swing.JOptionPane;
import java.io.*;
import java.util.ArrayList;

public class Metodos {

private File archivo = new File("c:\\prueba\\archiyect.txt");
private ArrayList<Medicamentos> medicamentos = new ArrayList<>();

public Metodos()
{
/*
* El constructor de Metodos lo que hará es comprobar si ya existe un
* archivo con datos de Medicamentos ya creado.
* Si existe, recuperará estos datos, creará objetos Medicamentos y los
* pasará al ArrayList desde donde podremos trabajar con ellos.
* Si no existe, no hará nada, tendremos un ArrayList vacio listo para
* que podamos hacer las primeras altas.
*/
if (archivo.exists())
{
try {
BufferedReader leer = new BufferedReader(new FileReader(archivo));
String linea = leer.readLine();
while(linea != null)
{
/*
* Separamos los atributos del Medicamento de la linea que hemos leido
* En la linea los atributos estan separados por un doble guion "--"
* La linea contendrá los 8 atributos correspondientes a un Medicamento.
* Sin embargo, los 4 últimos es posible que no tengan datos validos, si no que
* puede que contengan valores null y 0, ya que los únicos atributos que son
* de obligatoria cumplimentación son los primeros 4.
*/

String[] atributos = linea.split("--");
//Los 4 atributos obligatorios
String clave = atributos[0];
String nombre = atributos[1];
int precio = Integer.parseInt(atributos[2]);
int existencia = Integer.parseInt(atributos[3]);

/*
* Ahora recogemos los 4 atributos opcionales.
* Los de tipo String, si no fueron cumplimentados,
* tendrían valor null  y en el archivo de texto se
* habrá escrito la palabra "null". Sin embargo,
* al leer del archivo estamos recibiendo un String
* con el texto "null". No podemos pasar este texto
* directamente al atributo, sino que en este caso
* debemos pasar el valor null, que no es lo mismo
* que un string con el texto "null". Son cosas distintas.
*/
String nombreGenerico;
if (atributos[4].equals("null"))//Este atributo tenía valor null cuando se guardo en el archivo
nombreGenerico = null;
else
nombreGenerico = atributos[4];

int caducidad = Integer.parseInt(atributos[5]);

String formaFarmaceutica;
if (atributos[6].equals("null"))
formaFarmaceutica = null;
else
formaFarmaceutica = atributos[6];

int concentracion = Integer.parseInt(atributos[7]);

/*
* Ya tenemos los 8 atributos.
* Podemos añadir al ArrayList un nuevo Medicamento.
*/

medicamentos.add(new Medicamentos(clave, nombre, precio, existencia, nombreGenerico,
caducidad, formaFarmaceutica, concentracion));
//Medicamento añadido, leemos una nueva linea y si contiene datos, se repetirá este proceso
linea = leer.readLine();
}
leer.close();
//Lectura concluida.
//Podemos informar por pantalla cuantos Medicamentos hemos recuperado del archivo
JOptionPane.showMessageDialog(null, "Cantidad de Medicamentos recuperados: " + medicamentos.size(),
"Datos Leidos", JOptionPane.INFORMATION_MESSAGE);
} catch (Exception ex)
{
JOptionPane.showMessageDialog(null, "No se pudo leer datos del archivo: " + archivo.getAbsolutePath(),
"Error de Lectura", JOptionPane.WARNING_MESSAGE);
}
}
}

public void altas() throws FileNotFoundException,IOException
{
/*
* Los Medicamentos tienen 8 atributos, pero para su creacion solo
* son obligatorios propocionar 4. En este ejemplo solo pediremos
* los 4 atributos obligatorios.
*/

String clave = JOptionPane.showInputDialog("Dame la clave del producto");
String nombre = JOptionPane.showInputDialog("Escribe el nombre del producto");
int precio = Integer.parseInt(JOptionPane.showInputDialog("Escribe el precio del producto"));
int existencia = Integer.parseInt(JOptionPane.showInputDialog("Cuántos productos hay en existencia"));

/*
* Tenemos los 4 atributos.
* Crearemos un Medicamento y lo añadiremos al ArrayList.
* Luego, lo añadiremos al archivo de texto en disco.
*/
Medicamentos nuevoMed = new Medicamentos(clave, nombre, precio, existencia);
medicamentos.add(nuevoMed);

try{
BufferedWriter escribir = new BufferedWriter(new FileWriter(archivo, true));
escribir.write(nuevoMed.toString());
escribir.newLine();
escribir.close();
}catch(IOException e){
JOptionPane.showMessageDialog(null, "No se pudo escribir datos en archivo: " + archivo.getAbsolutePath(),
"Error de Escritura", JOptionPane.WARNING_MESSAGE);
}
}

/**
* Este metodo contruye un String con todos los datos de un
* Medicamento para ser mostrado en pantalla.
* Es útil porque puede ser utilizado para las funciones
* de listado, búsqueda por clave, busqueda por nombre..
* @param m Objeto Medicamentos que queremos mostrar.
* @return Cadena String con todos los datos
*/
private String mensajeMedicamento(Medicamentos m)
{
return "Clave: " + m.getClave()
+ "\nNombre: " + m.getNombre()
+ "\nPrecio: " + m.getPrecio()
+ "\nExistencias: " + m.getExistencia()
+ "\nNombre Generico: " + m.getNombregenerico()
+ "\nCaducidad: " + m.getCaducidad()
+ "\nForma Farmaceutica: " + m.getFormafarmaceutica()
+ "\nConcentracion: " + m.getConcentracion();
}

public void listado()
{
/*
* Recorremos el ArrayList y por cada Medicamento existente
* construimos un mensaje con los datos y lo mostramos en un
* Dialogo de Confirmacion.
* El usuario tiene la oportunidad de finalizar el listado pulsando
* el boton NO de este dialogo.
* Antes de nada, por supuesto, hemos de comprobar si existen medicamentos
* ya registrados
*/
if (medicamentos.isEmpty())
JOptionPane.showMessageDialog(null, "No hay Medicamentos registrados");
else
{
for (int i = 0; i < medicamentos.size(); i++)
{
/*
* Para mostrar el medicamento usamos el String que nos devuelve el metodo
* mensajeMedicamento() y además le añadimos otra linea indicando al usuario
* que puede detener el listado pulsando el boton NO de la ventana de dialogo.
* Esta ventana, en su título superior, además mostrará el número de posicion
* que ocupa este Medicamento en el ArrayList y el total que hay.
* Un mensaje tipo ---> Medicamento nº 4/30
* Así el usuario tendrá una idea de cuantos Medicamentos quedan por listar.
*/
String mensaje = mensajeMedicamento(medicamentos.get(i)) + "\n\n¿Desea seguir visualizando el listado?";

int seguir = JOptionPane.showConfirmDialog(null, mensaje, "Medicamento nº " + (i+1) + "/" + medicamentos.size(), JOptionPane.YES_NO_OPTION);

if (seguir == JOptionPane.NO_OPTION)//Usuario NO quiere seguir con el listado, "rompemos" el bucle
break;
}
}
}
//CONSULTA POR CLAVE
public void consultasc()
{
if (medicamentos.isEmpty())
JOptionPane.showMessageDialog(null, "No hay Medicamentos registrados");
else
{
String clave = JOptionPane.showInputDialog("Introduzca clave a buscar:");

/*
* Recorremos el ArrayList mediante un bucle FOR EACH para buscar el Medicamento con
* la clave que nos han indicado.
* Si lo encontramos, mostramos sus datos y detenemos el bucle de búsqueda.
* Si no lo encontramos, habría que informar al usuario de que no existe dicha clave.
* Para controlar si hemos encontrado o no el Medicamento, podemos usar una variable
* booleana. Esta variable comenzará con valor false.
* Si lo encontramos, la pondremos a true.
* Al terminar el bucle de busqueda, si esta variable conserva el valor false inicial,
* sabremos que el Medicamento no fue encontrado e informaremos al usuario.
*/
boolean encontrado = false;
for (Medicamentos m:medicamentos)
{
if (m.getClave().equalsIgnoreCase(clave))
{
encontrado = true;//¡¡Lo hemos encontrado!!
JOptionPane.showMessageDialog(null, mensajeMedicamento(m), "Mostrando medicamento", JOptionPane.INFORMATION_MESSAGE);
}
}
//Bucle de busqueda terminado, hemos de comprobar si fue encontrado el medicamento o no
if (!encontrado)
JOptionPane.showMessageDialog(null, "No se encontro medicamento con clave: " + clave, "Mostrando medicamento", JOptionPane.INFORMATION_MESSAGE);
}

}

//CONSULTA POR NOMBRE
public void consultasn()
{
//Igual que consultas por clave, pero ahora por nombre
}


public void bajas()throws FileNotFoundException,IOException
{
/*
* El metodo para hacer bajas es muy parecido al metodo de consulta por clave.
* Solo que esta vez al encontrar el medicamento, este ha de ser eliminado del
* ArrayList y también del fichero de texto donde guardamos los datos.
* Borrar del ArrayList se hace con una sencilla instruccion.
* Borrar la linea de datos del archivo de texto, es un poco más laborioso.
* Para facilitar la tarea, lo ideal es eliminar el archivo por completo
* y volver a crearlo de nuevo con todos los Medicamentos contenidos en el
* ArrayList, donde ya no estará el Medicamento que hemos dado de baja.
*/
if (medicamentos.isEmpty())
JOptionPane.showMessageDialog(null, "No hay Medicamentos registrados");
else
{
String clave = JOptionPane.showInputDialog("Introduzca clave de Medicamento a eliminar:");
boolean encontrado = false;//Para controlar si lo hemos encontrado
boolean borrado = false;//Para controla si el usuario ha decidido eliminarlo
for (int i = 0; i < medicamentos.size(); i++)
{
if (medicamentos.get(i).getClave().equalsIgnoreCase(clave))
{
encontrado = true;
String mensaje = mensajeMedicamento(medicamentos.get(i)) + "\n\n¿Desea dar de baja?";
int confirmar = JOptionPane.showConfirmDialog(null, mensaje, "Confirmar Baja", JOptionPane.YES_NO_OPTION);
if (confirmar == JOptionPane.YES_OPTION)//SI quiere dar de baja
{
//Eliminamos del ArrayList
medicamentos.remove(i);
borrado = true;
}
}
}
/*
* Bucle de busqueda terminado ahora comprobamos si el Medicamento fue encontrado o no.
* Si no fue encontrado, informamos al usuario con un mensaje
* Si fue encontrado y eliminado guardaremos los datos actualizados en el archivo de texto.
* Para crear este archivo habrá que recorrer de nuevo el ArrayList y añadir una linea de texto
* por cada Medicamento que contenga.
*/
if (encontrado && borrado)
{
try {
//Intentamos borrar archivo actual
if (archivo.delete())
{
//Archivo borrado, creamos uno nuevo actualizado
BufferedWriter escribir = new BufferedWriter(new FileWriter(archivo, true));
for (Medicamentos m:medicamentos)
{
escribir.write(m.toString());
escribir.newLine();
}
escribir.close();
JOptionPane.showMessageDialog(null, "Medicamento eliminado.\nLos cambios se han guardado", "Baja de Medicamento",
JOptionPane.INFORMATION_MESSAGE);
}
else//Por algun motivo, no se pudo borrar archivo
{
JOptionPane.showMessageDialog(null, "Error de acceso a archivo.\nLos cambios no han sido guardados", "Baja de Medicamento",
JOptionPane.WARNING_MESSAGE);
}
} catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Error de acceso a archivo\nTipo de error: " + ex.getLocalizedMessage());
}
}
else if(!encontrado)//No fue encontrado
{
JOptionPane.showMessageDialog(null, "NO se encontro Medicamento con la clave: " + clave, "Baja de Medicamentos",
JOptionPane.INFORMATION_MESSAGE);
}

}
}
}

Es la clase más grande y tiene muchas lineas de código, aunque la verdad muchas son lineas de comentarios donde explico lo que se va haciendo a cada paso para que se entienda mejor.

Comienza con 2 atributos: el ArrayList y el objeto File identificando al archivo con el que vamos a trabajar.
La ventaja de declararlos como atributos de clase es que así están visibles para todos los metodos y no hay problemas de "alcance"(scope).

Luego el constructor, que se encarga de ver si ya existe un archivo con datos y si lo hay, leerá cada linea de este para construir Medicamentos y pasarlos al ArrayList.
Para leer lineas estamos usando la clase BufferedReader. Es parecida a la FileReader, de hecho, para construir un BufferedReader tenemos que pasarle un FileReader.
La ventaja es que BufferedReader lee lineas de texto completas, FileReader solo lee caracter a caracter.
En los comentarios hago algunas explicaciones más detalladas, que no haré aquí para no extenderme demasiado. Si tienes dudas de por qué hago tal cosa o la otra, pregúntalas y ya profundizamos más.

Luego vienen los metodos:
  • altas()
  • listado()
  • consultasc()
  • consultasn()
  • bajas()

Todos tienen comentarios explicando paso a paso. Así que ahora explico solo un poco por encima para no extenderme. De nuevo, si tienes dudas concretas, pregunta y las tratamos luego:

-altas()
Es muy facil. Pedimos los 4 atributos mínimos obligatorios (pedir 8 son muchos y hace que testear el ejercicio sea mas tedioso).
Construimos un Medicamento, lo añadimos al ArrayList y añadimos una nueva linea de texto al archivo.
Para escribir, usamos la clase BufferedWriter ya que, al igual que su hermana BufferedReader, nos permite trabajar con lineas completas y no solo caracter a caracter.

-listado()
Muy facil también. Recorremos el ArrayList y por cada Medicamento encontrado mostramos sus atributos en una ventana de diálogo.
Cada vez que se muestra la ventana, el usuario puede escoger entre seguir adelante con el listado o detenerlo. De este modo no se le obliga a ver todo el listado completo (imagina que tenemos 50 Medicamentos, o 100...)

-consultasc()
Pedimos la clave y recorremos el ArrayList preguntando si algún Medicamento coincide con la clave que nos han dado.
Si lo encontramos, lo mostramos en pantalla.
Si no lo encontamos, informamos de que no existe medicamento con esa clave

-consultasn()
Este no lo he escrito, te lo dejo para que lo hagas tú.
En realidad es lo mismo que el anterior, solo que esta vez buscaremos por nombre.

-bajas()
Buscamos Medicamento por clave.
Si lo encontramos pedimos confirmacion para borrarlo.
Si el usuario confirma la baja, lo borramos del ArrayList y además tenemos que actualizar el archivo de texto.
Borrar lineas de un archivo de texto creo que puede ser un poco lioso, así que lo fácil  y rápido es eliminar por completo el archivo existente y volver a crearlo de nuevo con los datos del ArrayList, donde ya no se encuentra el Medicamento que hemos dado de baja.

Hay otro método, declarado como private (ya que es para uso interno de esta clase) llamado mensajeMedicamento()
Este es un método de apoyo.
Fíjate que en los metodos listado(), consultac()  y consultan() vamos a tener que mostrar una ventana con todos los datos, los 8 atributos, del Medicamento. Esto implica escribir varias linea para construir un String bastante grande.
Pues en lugar de repetir este proceso en varios sitios, lo que hacemos es crear un metodo que se encargue de esta tarea. Recibe un objeto Medicamento y devuelve un String, con texto,datos y saltos de linea..., listo para mostrar como mensaje al usuario.

Y bueno, el programa ya está funcionando perfectamente.

Solo quedaría escribir el metodo de consultas por nombre.
Y supongo que además habría que crear un nuevo metodo que permitiese modificar un Medicamento ya creado.
Este método sería posiblemente el más laborioso de realizar, aunque no es tampoco demasiado difícil y de hecho, sería muy similar al metodo de bajas().
La única diferencia es que en lugar de eliminar un objeto, ofrecemos la posibilidad de modificarlo

A ver si consigues hacerlo tú.

Y de nuevo, no dudes en preguntar lo que sea. No hay nada especialmente dificil, pero las cosas cuando se ven por primera vez, lo parecen.
Así que no te quedes con dudas.
Lo importante no es hacer el ejercicio, sino aprender haciéndolo.

873
Hola de nuevo. Ya he revisado todo el programa.
Te comento los cambios que pienso (pienso yo, no tiene por qué ser la única o la mejor forma de hacer un programa) podríamos hacer para que funcionase bien y además quede todo más simplificado, fácil de entender y de mantener.

Tenemos dos clases más: la clase Metodos y la clase Implementacion

Implementacion es la que se encarga de lanzar el programa y mostrar al usuario un menu de opciones.
Y creo que debería limitarse precisamente a eso y a nada más. Recoger la opcion elegida por el usuario y pedirle a Metodos que actúe según esa opcion.

Metodos será quien se encargue de leer y escribir datos en el archivo de texto, quien tenga un array en memoria con los datos de los Medicamentos con los que estamos trabajando, quien active los procesos de dar de alta, de baja, consulta, listado...
Va a ser quien realice todo el "trabajo duro", toda la labor interna del programa.

Implementacion en cambio no hará gran cosa, solo mostrar un menú.
Código: [Seleccionar]
import java.io.*;
import javax.swing.JOptionPane;
public class Implementacion
{

public static void main(String args[])throws FileNotFoundException, IOException
{     
//Inicializamos el objeto que contiene y gestiona todos los datos y funciones del programa
Metodos metodos = new Metodos();

String opcions;
int opcion;
do{
opcions = JOptionPane.showInputDialog ("Menu\n 1.Altas productos\n 2.Listado de productos\n 3.Consulta de productos\n 4.Bajas\n 5.SALIR\n");
//opcions = JOptionPane.showInputDialog ("Menu\n 1.Altas productos\n 2.Consulta productos\n 3.Baja porductos\n 4.Modificacion de un producto\n 5.Listado de productos\n 6. Salir\n ");
opcion=Integer.parseInt (opcions);
switch(opcion)
{
case 1:
metodos.altas();
break;
case 2:
metodos.listado();
break;
case 3:
String opcionl;
int opc;
do{
opcionl=JOptionPane.showInputDialog ("Menu\n 1.Busqueda por clave\n 2.Busqueda por nombre\n 3.SALIR");
opc=Integer.parseInt(opcionl);
switch(opc){
case 1:
metodos.consultasc();
break;
case 2:
metodos.consultasn();
break;
}
}while(opc!=3);
break;
case 4:
metodos.bajas();
break;
case 5:
JOptionPane.showMessageDialog(null, "FIN del programa");
break;
default:
JOptionPane.showMessageDialog(null, "Opcion invalida");

}while(opcion!=5);
}   
}

En realidad apenas he modificado la clase que tu ya tenias escrita. Tan solo eliminar un array que había declarado, una variable y poco más.
Fíjate que la primera linea es inicializar a Metodos que ya hemos dicho que será quien haga el trabajo de verdad.
Ahora además las llamadas a los metodos .listado(), consulta(), baja(),... se han simplificado. Ya no hay que pasarles parámetros entre parentesis, ya que todos los datos de trabajo ya los posee la clase Metodos y los gestiona ella. No necesita informacion externa.

Ahora vamos con la clase Metodos, que obviamente es la más interesante.
Antes es importante aclarar como vamos a trabajar con los datos.
El programa gestiona Medicamentos y estos se guardan en un archivo de texto para poder recuperarlos cada vez que se reinicie el programa.

A este archivo solo debemos acceder para recuperar los datos al iniciar el programa y guardar cambios como altas o bajas, no para hacer consultas o listados.
Para estos procesos tenemos que tener un array en memoria con todos los objetos Medicamentos, lo que nos permite trabajar con más rapidez y seguridad.

Para este tipo de programas, un array primitivo se nos queda muy limitado. Especialmente porque hay que indicarles un tamaño fijo.
Tu declaraste uno de tamaño 20, que bueno, para un ejercicio de práctica puede valer. Pero obviamente es una limitación importante.

Para evitar estas limitaciones podemos usar una estructura de datos más dinámica y avanzada. En Java hay varias para elegir, todas similares pero con ciertos matices.
Pero para no complicarnos la vida, es muy habitual usar el tipo ArrayList.
En esencia es muy similar a un array primitivo, pero tiene la ventaja de que no hay que indicar un tamaño fijo. Se le pueden añadir o eliminar elementos y su tamaño se irá adaptando a estos cambios.
Así que está sera la estructura que usaremos para tener los Medicamentos en memoria.

Para que los distintos metodos que va a tener la clase Metodos puedan acceder sin problemas tanto al ArrayList como al archivo de texto y hacer su trabajo, estos dos elementos los vamos a declarar como atributos de esta clase.
Tendremos un atributo File con la ruta del archivo ya predefinida y un ArrayList inicializado para poder albergar objetos Medicamentos

Además Metodos va a tener un constructor, pero en este caso va a hacer una tarea algo distinta a la habitual de recibir valores para pasar a los atributos.
Este constructor lo que va a hacer es comprobar si hay ya creado un archivo de texto.
Y si lo hay, recogerá los datos que contenga, construirá objetos Medicamentos y los añadirá al ArrayList.
De este modo, nuestro programa lo primero que hará al iniciarse será recuperar los datos guardados (si los hubiere) y los tendremos listos para trabajar con ellos.

Algo de lo que hay que hablar ahora, es de como vamos a guardar los datos en el archivo de texto.
Lo ideal es que cada linea del archivo contenga los datos (los 8 atributos) de un medicamento. Así sabremos que cada linea corresponde a un medicamento.
Los datos deberían ir separados por algún simbolo para que luego, cuando el programa lea la linea y quiera construir un objeto Medicamento con esos datos, sepa como separar esos datos y a que atributo pertenece a cada uno.
Yo he elegido separarlos por un doble guion -->  "--" pero vamos, podría ser cualquier otro simbolo.
De este modo, tendríamos un archivo de texto como este:

Citar
001--Frenadol--15--300--null--0--null--0
002--Focusin--35--250--null--0--null--0
003--Betadine--10--475--null--0--null--0

Cada linea es un medicamento, y cada atributo está diferenciado de los demás por el doble guion.

Para crear estas lineas, lo más comodo es que a la clase Medicamentos le añadamos un nuevo método.
Es el método toString(), que nos permite sobreescribirlo para que decidamos como queremos construir un String que sirva para mostrar los datos de dicho objeto.
Es aquí donde podemos meter los atributos separados por el doble guion y tener ya construida la linea que escribiremos en el archivo de texto.

Así que ha Medicamentos, le vamos a añadir este método:
Código: [Seleccionar]
@Override
public String toString()
{
return super.getClave() + "--" + super.getNombre() + "--" + super.getPrecio() + "--" + super.getExistencia()
+ "--" + nombregenerico + "--" + caducidad + "--" + formafarmaceutica + "--" + concentracion;
}

Con esto ya podremos escribir de forma sencilla lineas de texto que contengan toda la info de cada Medicamento.

Vamos a ver ya la clase Metodos, la pongo en el siguiente post

874
Voy a echarle un vistazo a todo en cuanto tenga tiempo, que ya se me terminaron las vacaciones, he vuelto al trabajo y ya no tengo tanto tiempo para dedicarle a esto. :-\

Pero para empezar, veo un par de cosas que no me cuadran:

La clase Productos, has definido su constructor indicando que va a recibir 7 parámetros, uno por cada atributo.
Sin embargo, el código del constructor solo recoge los primeros 4 atributos, los otros 3 (nombregenerico, caducidad y forma farmecutica) los ignora:
Código: [Seleccionar]
public Productos(String clave, String nombre, int precio, int existencia, String nombregnerico, int caducidad, String formafarmaceutica)
   {
   this.clave = clave;
   this.nombre = nombre;
   this.precio = precio;
   this.existencia = existencia;
   }

Ya que para construir un Producto pedimos 7 parametros, habría que recogerlos.
O bien reducir los parametros necesarios para la construcción a solo 4, si valoramos que los otros 3 no son importantes y pueden ser establecidos a posteriori usando los setters.

Es importante tomar una decisión sobre esto, porque esta decisión influye a la hora de crear objetos de la clase Medicamentos.
Esta clase hereda de Productos, esto significa que el constructor de Medicamentos, ha de pedir, como mínimo, los mismos parámetros que pide el constructor de Productos, ya que Medicamentos en su constructor, ha de pasarle esos parametros a su "superclase" Productos mediante el método super().

Esto significa que ahora mismo tu constructor de Medicamentos es erróneo y no funciona. No lo has notado porque en la Implementacion no estas construyendo Medicamentos, solo estás construyendo Productos. No se si es así como tienes que hacerlo (en cuyo caso la clase Medicamentos no sirve para nada) o te estás equivocando y lo que tienes que dar de alta, baja, etc.. son Medicamentos y no Productos

En cualquier caso, repito que ahora mismo tu constructor de Medicamentos es incorrecto:
Código: [Seleccionar]
public Medicamentos()
   {
      nombregenerico = null;
      caducidad = 0;
      formafarmaceutica = null;
      concentracion = 0;
   }
Para que se compilable y ejecutable, ha de incluir la llamada al super() (a la clase padre de la que hereda) y pasarle los parametros que este requiere para ser construido.
Por lo tanto, el constructor de Medicamentos ha de pedir también estos parametros.

Código: [Seleccionar]
public Medicamentos(String clave, String nombre, int precio, int existencia, String nombregenerico, int caducidad, String formafarmaceutica)
   {
  super(clave, nombre, precio, existencia, nombregenerico, caducidad, formafarmaceutica);
      nombregenerico = null;
      caducidad = 0;
      formafarmaceutica = null;
      concentracion = 0;
   }

Este constructor sí es compilable y ejecutable. Java lo dará por bueno y el programa funcionará.
Sin embargo, no es correcto. Hay errores de diseño en las clases, hay atributos repetidos.
Lo atributos: nombregenerico, caducidad y forma farmecutica están declarados en ambas clases, que son precisamente los atributos que el constructor de Productos estaba ignorando.
Supongo que se debe a que esos atributos deberían ser declarados solo para Medicamentos.
Así que vamos a redefinir las dos clases haciendo una distribución más lógica de sus atributos.

La clase Productos debería quedar solo con estos 4 atributos (y sus correspondientes getters/setters), que es de suponer son los únicos atributos comunes a todos los Productos, ya sean:
Productos->Medicamentos,
..o Productos->Vacunas(esta es otra clase que podría ser también heredera),
.. o lo que sea...

Código: [Seleccionar]
public class Productos
{
   private String clave;
   private String nombre;
   private int precio;
   private int existencia;

   
   public Productos(String clave, String nombre, int precio, int existencia)
   {
   this.clave = clave;
   this.nombre = nombre;
   this.precio = precio;
   this.existencia = existencia;
   }
   
   public void setClave(String clave)
   {
      this.clave = clave;
   }
   public String getClave()
   {
      return clave;
   }
   public void setNombre(String nombre)
   {
      this.nombre = nombre;
   }
   public String getNombre()
   {
      return nombre;
   }
   public void setPrecio(int precio)
   {
      this.precio = precio;
   }
   public int getPrecio()
   {
      return precio;
   }
   public void setExistencia(int existencia)
   {
      this.existencia = existencia;
   }
   public int getExistencia()
   {
      return existencia;
   }
   
}

Y entonces la clase Medicamentos, aporta 4 atributos más:
nombregenerico, caducidad, formafarmaceutica y concentracion

Por lo tanto, su constructor puede pedir 8 parámetros, 4 para pasarlos a su superclase Productos y los otros 4 para sus propios atributos.
Pero no es obligatorio pedir 8, la única cifra obligatoria es pedir los 4 necesarios para los atributos de Productos

Fíjate que incluso, podemos crear dos constructores y luego en la Implementacion podemos usar el que nos de la gana.
Un constructor solo pedirá los 4 necesarios para cumplir con la herencia de Productos, el resto de atributos se tendrían que establecer mediante los setters
El otro constructor si pedirá los 8 atributos completos, de forma que el objeto Medicamento quedaría completamente construido de una sola vez.

Aquí tienes la clase Medicamentos con los dos constructores.
Fíjate que en ambos constructores, la instrucción super() siempre ha de recibir esos 4 parámetros básicos necesarios para construir un Producto
Esto siempre es obligatorio cuando una clase hereda de otra clase.

Código: [Seleccionar]
public final class Medicamentos extends Productos
{
private String nombregenerico; //acido
private int caducidad;
private String formafarmaceutica;//tabletas, pastillas, jarabe
private int concentracion; //500 mg

public Medicamentos(String clave, String nombre, int precio, int existencia)
{
super(clave, nombre, precio, existencia);
nombregenerico = null;
caducidad = 0;
formafarmaceutica = null;
concentracion = 0;
}

public Medicamentos(String clave, String nombre, int precio, int existencia, String nombregenerico, int caducidad, String formafarmaceutica, int concentracion)
{
super(clave, nombre, precio, existencia);
this.nombregenerico = nombregenerico;
this.caducidad = caducidad;
this.formafarmaceutica = formafarmaceutica;
this.concentracion = concentracion;
}

public String getNombregenerico() {
return nombregenerico;
}

public void setNombregenerico(String nombregenerico) {
this.nombregenerico = nombregenerico;
}

public int getCaducidad() {
return caducidad;
}

public void setCaducidad(int caducidad) {
this.caducidad = caducidad;
}

public String getFormafarmaceutica() {
return formafarmaceutica;
}

public void setFormafarmaceutica(String formafarmaceutica) {
this.formafarmaceutica = formafarmaceutica;
}

public int getConcentracion() {
return concentracion;
}

public void setConcentracion(int concentracion) {
this.concentracion = concentracion;
}

}

Vale, aquí ya tenemos las dos clases bien definidas y cumpliendo con las herencias.
Revisa el enunciado de tu ejercicio. Si indica que los atributos han de ir repartidos de otra forma entre estas clases, dilo y lo cambiamos. Lo que desde luego no puede decir es que un mismo atributo está definida en ambas clases. Eso es redundante e innecesario.

Y revisa también si en la Implementacion lo que debemos dar de alta, baja, etc.. son Productos o Medicamentos. Lo lógico sería que trabajásemos con Medicamentos.

El resto del ejercicio lo revisaré entre este Sábado y Domingo. Ahora mismo no puedo dedicarle más tiempo.
Un saludo.

875
Hola.

Cuando postees código aquí en el foro, es mejor que lo envuelvas entre las etiquetas [ code ] para que quede mejor visualizado.
Basta con que pulses el boton  --> que verás arriba cuando escribes texto en el foro.
Te aparecerán dos etiquetas y dentro de ellas pegas el código para que quede así:
Código: [Seleccionar]
public class Productos
{
   private String clave;
   private String nombre;
   private int precio;
   private int existencia;
   private String nombregenerico;//acido
   private int caducidad;
   private String formafarmaceutica;//tabletas, pastillas, jarabe

   
   public Productos(String clave, String nombre, int precio, int existencia, String nombregnerico, int caducidad, String formafarmaceutica)
   {
   this.clave = clave;
   this.nombre = nombre;
   this.precio = precio;
   this.existencia = existencia;
   }
   
   public void setClave(String clave)
   {
      this.clave = clave;
   }
   public String getClave()
   {
      return clave;
   }
   public void setNombre(String nombre)
   {
      this.nombre = nombre;
   }
   public String getNombre()
   {
      return nombre;
   }
   public void setPrecio(int precio)
   {
      this.precio = precio;
   }
   public int getPrecio()
   {
      return precio;
   }
   public void setExistencia(int existencia)
   {
      this.existencia = existencia;
   }
   public int getExistencia()
   {
      return existencia;
   }
   public void setNombregenerico(String nombregenerico)
   {
      this.nombregenerico = nombregenerico;
   }
   public String getNombregenerico()
   {
      return nombregenerico;
   }
   public void setCaducidad(int caducidad)
   {
      this.caducidad = caducidad;
   }
   public int getCaducidad()
   {
      return caducidad;
   }
   public void setFormafarmaceutica(String formafarmaceutica)
   {
      this.formafarmaceutica = formafarmaceutica;
   }
   public String getFormafarmaceutica()
   {
      return formafarmaceutica;
   }
   
}


Por otra parte, has publicado un par de clases, pero no el programa principal donde supongo habrá algun menu para hacer las altas, bajas, etc...

No podemos ayudarte si no tenemos todas las clases.

Puedes publicarlas aquí o bien puedes comprimirlas en un archivo .zip y adjuntarlas en tu mensaje aqui en el foro.
PAra adjuntar, debajo del cuadro blanco donde escribimos el texto, verás un linea que pone Opciones Adicionales....
Pinchale y tendrás opcion de adjuntar archivos

876
Como dijimos, el proceso es muy similar al de eliminar. Solo que ahora hay que crear un nuevo objeto, por lo tanto hay que pedir datos al usuario y tal.

Entonces vamos a hacer un método que va a ser prácticamente idéntico al de setEliminar() y lo vamos a llamar setModificar().
Este método, ahora mismo ya tiene muchos if, muchos else, que si while()..., que si try ....
Resulta un poco lioso a los ojos, y ahora encima tenemos que meter más código. Así que para sea más legible, lo que vamos a hacer es crear un segundo método de apoyo, que se encargará de pedir al usuario datos, construir un objeto nuevo y devolver los datos en un String para meterlo en el ArrayList.
Así todo el proceso está separado en dos métodos y es más agradable a la vista. Tener un único método gigantesto con muchas lineas, muchas bifurcaciones... produce fatiga visual y mental, y creeme que esto dificulta resolver problemas de programación.

Bueno, mira. Este sería el método setModificar()
Fíjate que es prácticamente idéntico al de setEliminar(), solo varían los mensajes que mostramos al usuario y lo más importante, la línea que está señalada en color rojo:
Citar
public void setModificar()
   {
      if (archivo.exists())
      {
         String clave = JOptionPane.showInputDialog("Dame clave a modificar");
         try {
            ArrayList<String> lineas = new ArrayList<>();
            BufferedReader br = new BufferedReader(new FileReader(archivo));
            String linea = br.readLine();
            while (linea != null)
            {
               if (linea.startsWith(clave))
               {
                  int confirmar = JOptionPane.showConfirmDialog(null, "Se ha encontrado:\n"
                        + linea + "\n¿Seguro que quiere modificar?", "Confirmar Modificacion", JOptionPane.YES_NO_OPTION);
                  if (confirmar == JOptionPane.YES_OPTION)
                  {
                     lineas.add(getLineaModificada(linea));
                  }
                  else//No quiere modificar
                     lineas.add(linea);
               }
               else//Linea no coincide con clave
                  lineas.add(linea);
               
               linea = br.readLine();
            }
            br.close();
            //Guardamos los cambios en el archivo.
            if (archivo.delete())
            {
               BufferedWriter bw = new BufferedWriter(new FileWriter(archivo, true));
               for (String line: lineas)
               {
                  bw.write(line);
                  bw.newLine();
               }
               bw.close();
               JOptionPane.showMessageDialog(null, "Los cambios se han guardado");
            }
            else//Por algun motivo, no se ha podido borrar el archivo
            {
               JOptionPane.showMessageDialog(null, "No se ha podido modificar el archivo: " + archivo.getAbsolutePath());
            }

         }catch(Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, e.getLocalizedMessage());
         }
      }
      else//No existe archivo
         JOptionPane.showMessageDialog(null, "No existe fichero: " + archivo.getAbsolutePath());
   }

Marcado en rojo vemos que lo que añadiremos al ArrayList, será un String que nos devolverá el metodo de apoyo getLineaModificada()
Este método le pasamos la linea con los datos actuales y se encargará de preguntar al usuario que datos quiere modificar.
Recuerda que llegados a este punto, nos encontrabamos con el problema de que a través de la linea que hemos leido del fichero, NO podemos saber si se trata de un Jugador, o un Proveedor o alguien de Personal.

Se nos ocurrían dos soluciones:
1.- Hacer que las lineas de texto terminen indicando a que clase pertenecen.
Para esto habría que hacer una pequeña modificacion en los métodos .toString() de las tres clases que heredan de Persona.
Así tendríamos lineas como estas:
Citar
4567|Juan|Lopez|Canovas|8|Alero|Activo|Masculino|Jugador
Mikasa|C/Marcos|Madrid|mikasa@pelotas.net|678906543|Proveedor
Así comprobando la última palabra, podríamos deducir a que clase pertenece cada linea.

2.- Preguntar directamente al usuario qué tipo de clase está modificando. Y según su respuesta, procedemos de un modo u otro.


Personalmente, prefiero la primera opción. Creo que lo correcto es que el programa sepa identificar por sí solo a cual clase pertenece cada linea y no tener que preguntarle al usuario.
Así que primero voy a modificar los métodos toString() para que incluyan este nuevo dato identificativo:
Clase Jugadores:
Código: [Seleccionar]
@Override
public String toString()
{
return matricula + "|" + super.getNombre() + "|" + super.getAp()  + "|"
+ super.getAm() + "|" + numeroca  + "|" + posicion  + "|" + estatus +
"|" + super.getSexo()  + "|Jugador" ;
}

Clase Personal:
Código: [Seleccionar]
@Override
public String toString()
{
return clave + "|" + super.getNombre() + "|" + super.getAp() + "|"
+ super.getAm() + "|" +  puesto + "|" + especialidad + "|" + tiempoe
+ "|" + super.getSexo() + "|Personal";
}

Clase Proveedores:
Código: [Seleccionar]
@Override
public String toString()
{
return super.getNombre() + "|" + direccion + "|" + ciudad  + "|"
+ email + "|" + telefono + "|Proveedor";
}

Ahora ya solo hay que ponerse con el método getLineaModificada()

Este método es sencillo, pero tiene muchas líneas porque hay que incluir todas las preguntas necesarias para modificar un Jugador, un Proveedor o un Personal.

Básicamente lo que hace es identificar a que clase pertenece la linea que recibe.
Según a la clase que pertenezca, recupera los datos de la linea por separado para construir un objeto de esta clase.
Luego muestra estos datos uno por uno al usuario, y este decide si quiere modificarlo o no.
Una vez modificado, lo devuelve en un String y el metodo setModificar() se encargará de guardarlo en el fichero de texto.

Para separar los datos de la linea y poder construir el objeto, he usado el metodo split() de la clase String. Si no lo conoces o tienes dudas, pregunta y lo explicamos un poco.

De momento te pongo el método con el codigo necesario para modificar una linea perteneciente a la clase Jugadores.
Incluye comentarios para que se entienda bien cuál es el proceso seguido.

Faltaría el código para modificar lineas de las clases Proveedores y Personal.
Eso te lo dejo para que lo hagas tú.
Básicamente es repetir los mismos pasos seguidos para modificar Jugadores, solo cambian las preguntas porque cada clase tiene distintos datos/atributos.

Por último, solo aclarar que este método va incluido dentro de la clase CrearFile2
Lo he declarado como private porque se supone que este método no debería ser invocado desde otras clases. Es un método de apoyo que solo ha de ser invocado por el método setModificar(), quien sí es public porque será invocado desde otras clases (concretamente desde la clase MenuV2)

Código: [Seleccionar]
private String getLineaModificada(String linea)
{
String lineaModificada = null;//Esta será la linea que vamos a devolver con las modificaciones

if (linea.endsWith("Jugador"))//La linea pertenece a la clase Jugadores
{
/*
* Antes de modificar, creamos un objeto de la clase Jugadores
* recuperando los datos de la linea que hemos leido.
* Puesto que los datos de la linea están separados por el simbolo "|"
* esto nos viene de maravilla para obtener los datos por separado en
* un arreglo simple usando el metodo split() de la clase String.
*
* El simbolo "|", tambien llamado pipe o barra vertical es un simbolo especial,
* lo que se llama un "meta caracter".
* Para poder usarlo como "expresion regular" en el metodo split(), es necesario
* "escaparlo" con doble backslash para que lo reconozca
*/
String[] datosJugador = linea.split("\\|");
//Construimos un Jugador con los datos obtenidos
Jugadores jugador = new Jugadores();
jugador.setMatricula(Integer.parseInt(datosJugador[0]));
jugador.setNombre(datosJugador[1]);
jugador.setAp(datosJugador[2]);
jugador.setAm(datosJugador[3]);
jugador.setNumeroCa(Integer.parseInt(datosJugador[4]));
jugador.setPosicion(datosJugador[5]);
jugador.setEstatus(datosJugador[6]);
jugador.setSexo(datosJugador[7]);
/*
* Ya tenemos un Jugador con los datos ACTUALES.
* Ahora hay que preguntar al usuario que datos quiere modificar.
* Podemos mostrarle los datos actuales uno a uno y que elija si quiere modificar o no.
* Cuando quiera modificar alguno, usamos la clase LeerMostrar5 para pedir el dato adecuado.
*/
//Preguntamos por matricula
int respuesta = JOptionPane.showConfirmDialog(null, "Matricula Actual:\n" + jugador.getMatricula() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)//SÍ quiere modificar
jugador.setMatricula(lm5.getMatricula2());

//Preguntamos por nombre
respuesta = JOptionPane.showConfirmDialog(null, "Nombre Actual:\n" + jugador.getNombre() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setNombre(lm5.getNombreJ());

//Apellido Paterno
respuesta = JOptionPane.showConfirmDialog(null, "Apellido Paterno Actual:\n" + jugador.getAp() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setAp(lm5.getApe());

//Apellido Materno
respuesta = JOptionPane.showConfirmDialog(null, "Apellido Materno Actual:\n" + jugador.getAm() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setAm(lm5.getAma());

//Numero Camiseta
respuesta = JOptionPane.showConfirmDialog(null, "Numero Camiseta Actual:\n" + jugador.getNumeroCa() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setNumeroCa(lm5.getNumC());

//Posicion
respuesta = JOptionPane.showConfirmDialog(null, "Posicion Actual:\n" + jugador.getPosicion() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setPosicion(lm5.getPosic());

//Status
respuesta = JOptionPane.showConfirmDialog(null, "Estado Actual:\n" + jugador.getEstatus() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setEstatus(lm5.getEstatus1());

//Sexo
respuesta = JOptionPane.showConfirmDialog(null, "Sexo Actual:\n" + jugador.getSexo() + "\n¿Modificar?",
"Modificar Jugador", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION)
jugador.setSexo(lm5.getSex1());

/*
* Ya tenemos al Jugador con las modificaciones que haya elegido el usuario.
* Lo convertimos en una linea String y el método lo retornará para que sea incluido
* en el ArrayList del método setModificar() quien se encargará de guardarlo en el fichero
*/
lineaModificada = jugador.toString();
}
else if (linea.endsWith("Personal"))//La linea pertenece a la clase Personal
{
//Contruir objeto Personal, preguntar al usuario modificaciones y convertirlo a String
}
else if (linea.endsWith("Proveedor"))//La linea pertenece a la clase Proveedores
{
//Contruir objeto Proveedores, preguntar al usuario modificaciones y convertirlo a String
}

return lineaModificada;//Finalizado el metodo, esta linea contendrá los datos de un Jugador, o un Proveedor o un Personal
}

877
Tengo un pregunta para poder hacer modificación puedo utilizar osea basarme en el código de eliminación?

Sí.
Porque si no me equivoco, no puedes modificar una linea de texto, o al menos yo no se hacerlo.
Me refiero a una modificación "real".

Yo lo haría igual a como hemos hecho en el método de eliminación.
Leer todas las lineas y pasarlas al ArrayList.
Antes de pasarla, si la linea coincide con la clave que el usuario ha proporcionado, preguntamos si quiere modificar esa linea.

Si dice que NO quiere modificarla, la añadimos al ArrayList y seguimos buscando lineas.

Si dice que SI quiere modificarla, entonces no añadimos esa línea. Quizás lo más fácil sería pedir de nuevo todos los datos, crear un objeto nuevo y lo que metemos en el ArrayList es lo que nos devuelva el metodo toString() de este nuevo objeto que acabamos de crear.

Pero esto presenta un problema importante. Nosotros, solo con leer el archivo, no podemos saber si la linea que estamos leyendo pertenece a un Jugador, un Personal o un Proveedor
Una vez guardados los datos en el archivo de texto, no hay nada que distinga uno de otros.

Así que a la hora de modificar una linea, no sabremos que tipo de nuevo objeto tendremos que crear.

Se me ocurren dos soluciones posibles:
1) Cuando pidamos datos al usuario para hacer la modificación, lo primero que le preguntamos es si quiere crear un Jugador, un Personal o un Proveedor.
Y según lo que indique decidimos que objeto crear, y que datos pedir..

2) Modificar el método toString() para que al final de la linea añada el tipo de clase al que pertenece.
Así, en el archivo de texto cada linea terminará con la palabra Jugadores, o Personal, o Proveedor.
Y así, con el metodo endsWith(), luego en el programa podemos determinar a que clase pertenece cada linea.
Algo así...
Código: [Seleccionar]
if (linea.endsWith("Personal"))
{
    //La linea pertenece a la clase Personal
}
else if (linea.endsWith("Jugadores"))
{
    //La linea pertenece a la clase Jugadores
}
else
{
    //La linea pertenece a Proveedores
}


Como ves, modificar una linea se parece un poco a eliminar..... pero en realidad supone nuevos retos..  :o

878
Aprender a programar desde cero / Re:Centrar texto en HTML
« en: 06 de Junio 2018, 20:51 »
Hola.

A mi me salen centrados, ¿con que navegador lo visualizas?

He probado con Opera, Chrome y MS Edge. Y con todos se ve bien. Lo unico que MS Edge no aplicar el color de fondo al body, pero los simbolos salen centrados.

Incluso con el viejo Internet Explorer sale centrado, aunque parece que no sabe ponerlos en formato de grilla.

No se porque no te sale bien a ti. La propiedad text-align: center debería funcionar en cualquier navegador.

879
Ok. Creo que ya lo tengo.

La clase Persona no la he cambiado

Las clases Jugadores, Personal y Proveedores, el único cambio que he hecho ha sido añadirles a cada uno su propio metodo .toString(), ya que como explique antes, es muy útil y ayuda  mucho a reducir código.

Jugadores:
Código: [Seleccionar]
@Override
public String toString()
{
return matricula + "|" + super.getNombre() + "|" + super.getAp()  + "|"
+ super.getAm() + "|" + numeroca  + "|" + posicion  + "|" + estatus +
"|" + super.getSexo()  + "|";
}

Personal:
Código: [Seleccionar]
@Override
public String toString()
{
return clave + "|" + super.getNombre() + "|" + super.getAp() + "|"
+ super.getAm() + "|" +  puesto + "|" + especialidad + "|" + tiempoe
+ "|" + super.getSexo() + "|";
}

Proveedores:
Código: [Seleccionar]
@Override
public String toString()
{
return super.getNombre() + "|" + direccion + "|" + ciudad  + "|"
+ email + "|" + telefono + "|";
}

Fíjate que para obtener los atributos de la clase padre Persona, hay que usar la palabra super seguido del métod get() que necesitamos.

Sobre la clase LeerMostrar5
No he hecho cambios importantes. Tan solo eliminar lineas de código innecesarias, como por ejemplo los try catch cuando estamos pidiendo datos de tipo String.
También he quitado las declaraciones de atributos donde estaban puestos unos objetos de Personal, Jugadores y Proveedores.
Tampoco son necesarios para esta clase.

LeerMostrar5:
Código: [Seleccionar]
import javax.swing.JOptionPane;

public final class LeerMostrar5 {

public LeerMostrar5()
{}

public int getMatricula2()
{
int matricula = 0;
boolean bandera = false;
do
{
try
{
matricula = (Integer.parseInt(JOptionPane.showInputDialog("Matricula del jugador:")));
bandera=true;
}
catch(NumberFormatException e)
{JOptionPane.showMessageDialog(null,"El dato ingresado no es correcto");}
}while(bandera!=true);

JOptionPane.showMessageDialog(null,"Matricula\n"+matricula);
return matricula;
}

public String getNombreJ()
{
String nombre = JOptionPane.showInputDialog("Nombre:\r\n");
JOptionPane.showMessageDialog(null,"Nombre\n"+nombre);
return nombre;
}

public String getApe()
{
String apeP = JOptionPane.showInputDialog("Apellido paterno:");
JOptionPane.showMessageDialog(null,"Apellido Paterno\n"+apeP);
return apeP;
}

public String getAma()
{
String apeM = JOptionPane.showInputDialog("Apellido materno:");
JOptionPane.showMessageDialog(null,"Apellido Materno\n"+apeM);
return apeM;
}

public int getNumC()
{
boolean bandera=false;
int numCam=0;
do
{
try
{
numCam = (Integer.parseInt(JOptionPane.showInputDialog("Numero de camisa:\r\n"+"")));
bandera=true;
}
catch(Exception e)
{JOptionPane.showMessageDialog(null,"El dato ingresado no es correcto");}
}while(bandera!=true);
JOptionPane.showMessageDialog(null,"Numero de Camisa\n"+numCam);
return numCam;
}

public String getPosic()
{
String posicion = JOptionPane.showInputDialog("Posicion:\r\n");
JOptionPane.showMessageDialog(null,"Posicion\n"+posicion);
return posicion;
}

public String getEstatus1()
{
String status = JOptionPane.showInputDialog("Estatus:");
JOptionPane.showMessageDialog(null,"Estatus\n"+status);
return status;
}

public Object getSex1()
{
Object sexo = JOptionPane.showInputDialog(null,"Seleccione sexo","Sexo",
JOptionPane.QUESTION_MESSAGE,null, new Object[]
{ "Masculino", "Femenino"},"Masculino");

JOptionPane.showMessageDialog(null,"Sexo\n"+sexo);
return sexo;
}


/*Ingresar datos de personal*/

public int getClave()
{
boolean bandera = false;
int clave = 0;
do
{
try
{
clave = (Integer.parseInt(JOptionPane.showInputDialog("Clave:\t")));
bandera=true;
}
catch(NumberFormatException e)
{JOptionPane.showMessageDialog(null,"El dato ingresado no es correcto");}
}while(bandera!=true);
return clave;
}

public String getNombrep()
{
String nombre = JOptionPane.showInputDialog("Nombre:\t");
JOptionPane.showMessageDialog(null,"Nombre\n"+nombre);
return nombre;
}

public String getAp2()
{
String apeP = JOptionPane.showInputDialog("Apellido Paterno:\t");
JOptionPane.showMessageDialog(null,"Apellido Paterno\n"+apeP);
return apeP;
}

public String getAm2()
{
String apeM = JOptionPane.showInputDialog("Apellido materno:");
JOptionPane.showMessageDialog(null,"Apellido Materno\n"+apeM);
return apeM;
}

public String getPuesto1()
{
String puesto = JOptionPane.showInputDialog("Puesto:");
JOptionPane.showMessageDialog(null,"Puesto\n"+puesto);
return puesto;
}

public String getEsp()
{
String espe = JOptionPane.showInputDialog("Especialidad:");
JOptionPane.showMessageDialog(null,"Especialidad\n"+espe);
return espe;
}

public int getTiempoe()
{
boolean  bandera = false;
int tiempo = 0;
do
{
try
{
tiempo = (Integer.parseInt(JOptionPane.showInputDialog("Tiempo en la empresa:\t")));
bandera=true;
}
catch(NumberFormatException nft)
{JOptionPane.showMessageDialog(null,"Error ingreso un dato no valido");}
}while(bandera!=true);
JOptionPane.showMessageDialog(null, "Tiempo en la empresa\n" + tiempo);
return tiempo;
}

public Object getSex2()
{
Object sexo = (JOptionPane.showInputDialog(null,"Seleccione sexo","Sexo",
JOptionPane.QUESTION_MESSAGE,null, new Object[]
{ "Masculino", "Femenino"},"Masculino"));
JOptionPane.showMessageDialog(null, "Sexo\n" + sexo);
return sexo;
}

/* Ingresar Proveedores*/
public String getNombrePr()
{
String provee = JOptionPane.showInputDialog("Proveedor:\t");
JOptionPane.showMessageDialog(null, "Proveedor\n" + provee);
return provee;
}

public String getDirecpr()
{
String direc = JOptionPane.showInputDialog("Direccion:\t");
JOptionPane.showMessageDialog(null, "Direccion\n" + direc);
return direc;
}

public String getCiudad1()
{
String ciudad = JOptionPane.showInputDialog("Ciudad:\t");
JOptionPane.showMessageDialog(null, "Ciudad\n" + ciudad);
return ciudad;
}

public String getEmail()
{
String mail = JOptionPane.showInputDialog("E-Mail:\t");
JOptionPane.showMessageDialog(null, "E-Mail\n" + mail);
return mail;
}

public int getTelefono()
{
boolean  bandera = false;
int telef = 0;
do
{
try
{
telef = (Integer.parseInt(JOptionPane.showInputDialog("telefono:\t")));
bandera=true;
}
catch(NumberFormatException nft)
{JOptionPane.showMessageDialog(null,"Error ingreso un dato no valido");}
}while(bandera!=true);
JOptionPane.showMessageDialog(null, "Telefono\n" + telef);
return telef;
}

}

Se podría haber reducido más el código, ya que por ejemplo hay métodos que son iguales.
Los métodos para pedir nombres o los de pedir apellidos.. son iguales tanto si es para una Jugador como si es para Personal.
Así que con solo un método para pedir Nombre nos hubiera servido para todas las clases.
De hecho, esta clase no tiene porque saber nada acerca de Jugadores, Proveedores,...

Su única función es mostrar ventanas con los mensajes adecuados para pedir los datos correspondientes.

La clase MenuBueno no he cambiado nada. Lo único que considero que es un poco innecesaria su existencia. El metodo main() podría estar incluido en la clase MenuV2 y lanzarse el programa desde ahí. Pero bueno, no importa demasiado.

Sobre la clase MenuV2, tampoco ha cambiado demasiado.
He quitado de nuevo varios atributos innecesarios y objetos innecesarios.
Esta clase no necesita ningún BufferedReader, ni objetos Jugadores, ni tampoco objetos MenuV2 (es decir, ella misma estaba declarada como un atributo más)

MenuV2:
Código: [Seleccionar]
import java.io.IOException;

import javax.swing.JOptionPane;

public final class MenuV2 {

private CrearFile2 cf2 = new CrearFile2();

public MenuV2()
{}

public void setMenuV2() throws IOException
{
int opcion = 0;
do
{
opcion=Integer.parseInt(JOptionPane.showInputDialog(null,"1.Registrar\n"+"2.Eliminar registro\n"+"3.Consultar\n"+"4.Salir"));
switch (opcion)
{
case 1:
int opc=0;
do
{
opc=Integer.parseInt(JOptionPane.showInputDialog(null,"1.Agregar jugadores\n"+"2.Agregar Personal\n"+"3.Agregar Proveedores\n"+"4.Salir"));
switch(opc){
case 1:
cf2.setCrearJugadores(); break;
case 2:
cf2.setCrearPersonal(); break;
case 3:
cf2.setCrearProveedores(); break;
case 4:
JOptionPane.showMessageDialog(null,"Volviendo al menu principal");break;
default:
JOptionPane.showMessageDialog(null,"Opcion invalida");
}
}while(opc!=4);
break;
case 2:
cf2.setEliminar(); break; 
case 3:
cf2.setConsulta();break;         
case 4:
JOptionPane.showMessageDialog(null,"Salio del sistema"); break;

default:
JOptionPane.showMessageDialog(null,"Opcion invalida");

}
}while(opcion!=4);
}

}

Esta clase solo necesita tener como atributo a la clase CrearFile2, ya que todo lo que tiene que hacer es mostrar menus de opciones, y segun lo que escoja el usuario, pedirle a CrearFile2 que haga una cosa o la otra.


Y ahora llegamos a la clase CrearFile2, que es la más importante de todas.
Aquí es donde más cambios he hecho, aunque a nivel funcional ya estaba casi completa.
De nuevo he eliminado atributos y objetos que no eran necesarios.
He simplificado los métodos para crear Jugadores, Personal y Proveedores al valernos del metodo toString()
Además en estos metodos ya no pregunto si el archivo existe o no existe. En realidad nos da igual si existe o no. Si te fijas, tu preguntabas pero hacías exactamente lo mismo tanto si existía como si no..
Para estos metodos no necesitamos saber si existe o no. El objeto BufferedWriter se encarga por si solo.
Si el archivo existe agregará nuevas lineas, si no existe, creará un archivo nuevo.

Los metodos setConsulta() y setMostrarB() son dos versiones distintas para hacer una misma cosa.
He modificado el setConsulta() para hacerlo funcionar con un objeto BufferedReader y es el que estoy usando para hacer consultas.

El setMostrarB() no lo estoy usando pero lo he dejado como version alternativa ya que es lo mismo pero con un Scanner en lugar de un BufferedReader.

Por último, el metodo setEliminar(), que es el más dificil y el que te traía de cabeza supongo.
Lo he simplificado utilizando un ArrayList para leer las lineas del archivo antes de eliminar lo que pida el usuario.
Tu lo intentabas hacer con un arreglo normal, pero esta estructura es demasiado primitiva y hay que complicar mucho el código para que funcione bien.
En este método he puesto bastante comentarios explicando cada paso y creo que se entiende bastante bien. Miratelo y pregunta cualquier duda que tengas.
No se si te pondrán alguna pega por estar usando un ArrayList, si hubiera que utilizar un arreglo simple, dímelo y podemos hacer una versión alternativa.

CrearFile2:
Código: [Seleccionar]
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.JOptionPane;

public final class CrearFile2 {

/*
* Como atributos de clase solo necesitamos el objeto File para escribir al archivo
* y un objeto LeerMostrar5 para pedir datos usando sus métodos.
*/
File archivo= new File("C:\\Prueba\\EquipoV.txt");
LeerMostrar5 lm5 = new LeerMostrar5();

public void setCrearJugadores()
{
try
{
//Preparamos archivo para escribir
BufferedWriter bw = new BufferedWriter(new FileWriter(archivo, true));
//Creamos un jugador nuevo.
Jugadores jugador = new Jugadores();
//Pedimos datos usando métodos de la clase LeerMostrar5
jugador.setMatricula(lm5.getMatricula2());
jugador.setNombre(lm5.getNombreJ());
jugador.setAp(lm5.getApe());
jugador.setAm(lm5.getAma());
jugador.setNumeroCa(lm5.getNumC());
jugador.setPosicion(lm5.getPosic());
jugador.setEstatus(lm5.getEstatus1());
jugador.setSexo(lm5.getSex1());
/*
* Ya tenemos un Jugador creado.
* Ahora guardamos todos sus datos en el archivo.
* Usamos el metodo .toString() para tener todos los datos
* preparados en una sola linea.
*/
bw.write(jugador.toString());
bw.newLine();
bw.close();
}
catch(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(null,ex.getLocalizedMessage());
}

}   

public void setCrearPersonal(){

try {
BufferedWriter bw = new BufferedWriter(new FileWriter(archivo, true));
Personal personal = new Personal();
personal.setClave(lm5.getClave());
personal.setNombre(lm5.getNombrep());
personal.setAp(lm5.getAp2());
personal.setAm(lm5.getAm2());
personal.setPuesto(lm5.getPuesto1());
personal.setEspecialidad(lm5.getEsp());
personal.setTiempoE(lm5.getTiempoe());
personal.setSexo(lm5.getSex2());
bw.write(personal.toString());
bw.newLine();
bw.close();
}
catch(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(null,ex.getLocalizedMessage());
}
}

public void  setCrearProveedores() throws IOException
{
try
{
BufferedWriter bw = new BufferedWriter(new FileWriter(archivo, true));
Proveedores proveedor = new Proveedores();
proveedor.setNombre(lm5.getNombrep());
proveedor.setDireccion(lm5.getDirecpr());
proveedor.setCiudad(lm5.getCiudad1());
proveedor.setEmail(lm5.getEmail());
proveedor.setTelefono(lm5.getTelefono());
bw.write(proveedor.toString());
bw.newLine();
bw.close();
}
catch(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(null,ex.getLocalizedMessage());
}
}

public void setConsulta()
{
if (archivo.exists())
{
String datoAbuscar = JOptionPane.showInputDialog("Dato a buscar:");

try {

BufferedReader br = new BufferedReader(new FileReader(archivo));

String lineaArchivo = br.readLine();//Leemos primera linea

while (lineaArchivo != null) {//Si no es null, es que hemos podido leer linea

if (lineaArchivo.startsWith(datoAbuscar))
JOptionPane.showMessageDialog(null,"Dato Buscado:\n" + lineaArchivo);

lineaArchivo = br.readLine();//Leemos otra linea, si no quedasen, tendriamos null y el bucle terminará
}
br.close();
} catch(Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, e.getLocalizedMessage());
}
}
else
JOptionPane.showMessageDialog(null, "No se puede consultar\nNo existe fichero: " + archivo.getAbsolutePath());
}

public void setMostrarB() throws IOException
{
try {

Scanner lector = new Scanner(archivo);
String datoAbuscar =  JOptionPane.showInputDialog("Dato a buscar:");
while (lector.hasNextLine()) {
String datoBuscado = lector.nextLine();

if (datoBuscado.startsWith(datoAbuscar)) {
JOptionPane.showMessageDialog(null,"Dato buscado\n" + datoBuscado);
}


}
}catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "No se ha encontrado el fichero " + archivo.getAbsolutePath());
e.printStackTrace();//Muestra por consola la "traza" del error
}
}

public void setEliminar() {

if (archivo.exists())
{
String clave = JOptionPane.showInputDialog("Dame clave a eliminar");
/*
* Leeremos todas las lineas existentes en el archivo para tenerlas en memoria.
* Como no sabemos cuantas lineas puede haber, es más comodo guardarlas en un ArrayList
* ya que no hay que indicarle un tamaño específico, y permite añadir/eliminar datos.
* Un arreglo normal no nos da esta flexibilidad y nos complica demasiado el codigo.
*
*  Cada vez que leemos una nueva linea, podemos comprobar si coinciden con la clave
*  que queremos eliminar. Si coincide, preguntamos al usuario si es esta la clave que quiere
*  eliminar.
*  Si DENIEGA eliminar la clave, la añadimos al ArrayList y seguimos leyendo lineas.
*  Si CONFIRMA que es la clave a eliminar, NO la añadiremos al ArrayList, aunque seguiremos
*  leyendo y preguntando en caso de encontrar más coincidencias.
*/
try {
ArrayList<String> lineas = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader(archivo));
String linea = br.readLine();
while (linea != null)
{
if (linea.startsWith(clave))//Coincidencia, preguntamos si quiere eliminar
{
int confirmar = JOptionPane.showConfirmDialog(null, "Se ha encontrado:\n"
+ linea + "\n¿SEguro que quiere borrar?", "Confirmar Eliminacion", JOptionPane.YES_NO_OPTION);
if (confirmar == JOptionPane.YES_OPTION)//SI quiere borrar. Por tanto, no la añadimos al ArrayList
{
JOptionPane.showMessageDialog(null, "El dato será eliminado");
}
else//No quiere borrar. Por tanto, SI lo añadimos al ArrayList
{
lineas.add(linea);
}
}
else//No ha habido coincidencia. Añadimos linea al ArrayList sin preguntar nada.
{
lineas.add(linea);
}
linea = br.readLine();//Leemos nueva linea y repetimos bucle
}
br.close();
/*
* Bucle de lectura finalizado.
* Ahora mismo en el ArrayList tenemos las lineas que
* el usuario NO ha querido borrar. Solo queda volver a
* escribirlas en el fichero sustituyendo todos los datos que contiene ahora.
*
* Por tanto, primero intentaremos borrar el archivo actual para crear uno nuevo
*/

if (archivo.delete())
{
BufferedWriter bw = new BufferedWriter(new FileWriter(archivo, true));
//Ahora recorremos el ArrayList y vamos grabando cada una de las lineas que contiene
for (String line: lineas)
{
bw.write(line);
bw.newLine();
}
//Listo. Ya se ha han guardado los cambios.
bw.close();
JOptionPane.showMessageDialog(null, "Los cambios se han guardado");
}
else//Por algun motivo, no se ha podido borrar el archivo
{
JOptionPane.showMessageDialog(null, "No se ha podido modificar el archivo: " + archivo.getAbsolutePath());
}

}
catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, e.getLocalizedMessage());
}

}

}
}


Y esto es todo. Yo lo he probado y funciona.
Creo que dijiste que una opcion era mostrar TODO el contenido del archivo de texto al usuario.
Es lo único que faltaría por añadir.

Cualquier duda, ya sabes, pregunta por aquí

880
Vale.
Voy a echarle un vistazo a ver para ponerme en situación y a ver si puedo ponerlo en marcha y ver que está fallando. Entre hoy y mañana intentaré decirte algo.

De momento, solo comentar unas cositas.

1.
En la clase Persona hay un pequeño error aquí:
Código: [Seleccionar]
public void setAm (String Am)
   {
      this.am=am;
   }

La variable del parentesis tiene la "A" mayuscula y eso hace que en el código no se esté recogiendo su valor, ya que su nombre es distinto de la variable en minuscula "am"
Hay que corregirlo así:
Código: [Seleccionar]
public void setAm (String am)
   {
      this.am=am;
   }

2.
En la clase LeerMostrar5, al pedir datos como la matricula del jugador, puesto que la matricula es un valor int pero lo recibimos como String, hacemos un parseo para cambiar el tipo de dato.
Este parseo lo hacemos dentro de un try{}catch(){} porque puede haber errores al pasar de String a int y hay que controlarlos.
OK, esto es totalmente correcto.

Pero luego, al pedir datos como Nombre o Apellido, también lo estamos poniendo dentro de un try catch
Esto es innecesario, ya que no estamos haciendo ninguna conversión de datos y no va a ocurrir ninguna excepcion que debamos controlar.
No pasa nada malo por ponerlo dentro del try catch, pero no sirve para nada, así que se pueden quitar esos try catch y reducir lineas de código.
O se pueden dejar si lo prefieres, no afectan para nada.

3.
En la clase MenuV2 aparecen objetos de una clase llamada CrearFile.
¿Puedes publicar también esa clase? Así lo tendré todo igual a como tú lo estás haciendo.

4.
Por último, una duda sobre el enunciado.
Tendremos datos de Jugadores, Personal y Proveedores.
Y se han de guardar en archivos de texto.
¿Se guardan juntos? ¿O cada uno se guardará en un archivo distinto?

Páginas: 1 ... 39 40 41 42 43 [44] 45 46 47 48 49 50

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".