Activitats

Compta paraules

L’objectiu d’aquesta activitat és aprendre a treballar amb cadenes de text llegides d’un fitxer orientat a caràcter.

Feu un programa anomenat ComptaParaulesFitxer que llegeixi un fitxer orientat a caràcter on hi ha tot de frases escrites en línies diferents. Per indicar el final del fitxer, hi ha una frase o només posa “fi”. Aquest programa ha de mostrar per pantalla el nombre de paraules que té cada frase, sense comptar la de “fi”. Les contraccions (l’, d’, etc.) compten com a part de la paraula associada.

Per exemple, a partir d’aquest fitxer:

Hi havia una vegada...
Perquè ho ha fet avui?
No està malament
Si tu ho dius hi aniré
Doncs d'acord
fi

La sortida per pantalla podria ser:

La línia 1 té 4 paraules.
La línia 2 té 5 paraules.
La línia 3 té 3 paraules.
La línia 4 té 6 paraules.
La línia 5 té 2 paraules.

  1. package unitat6.apartat2.activitats;
  2.  
  3. import java.util.Scanner;
  4. import java.io.File;
  5.  
  6. public class ComptaParaulesFitxer {
  7.  
  8. public static void main (String[] args) {
  9. ComptaParaulesFitxer programa = new ComptaParaulesFitxer();
  10. programa.inici();
  11. }
  12.  
  13. public void inici() {
  14. try {
  15. File f = new File("Document.txt");
  16. Scanner lector = new Scanner(f);
  17. boolean llegir = true;
  18. int numLinia = 1;
  19.  
  20. while (llegir) {
  21. String text = lector.nextLine();
  22. if ("fi".equals(text)) {
  23. llegir = false;
  24. } else {
  25. //Es pot usar "split" per comptar les paraules
  26. String[] paraules = text.split(" ");
  27. int numPar = paraules.length;
  28. System.out.println("La línia " + numLinia + " té " + numPar + " paraules.");
  29. numLinia++;
  30. }
  31. }
  32. lector.close();
  33. } catch (Exception e) {
  34. System.out.println("Error llegint fitxer: " + e);
  35. }
  36.  
  37. }
  38. }

La màquina d'escriure

L’objectiu d’aquesta activitat és veure com emmagatzemar dades llegides des del teclat en fitxers orientats a caràcter.

Feu un programa que funcioni com una màquina d’escriure. En iniciar la seva execució, ha de preguntar a l’usuari que escrigui, usant el teclat el nom d’un fitxer. Si aquest fitxer ja existeix, s’ha de demanar que posi un altre nom. Un cop s’ha escrit un nom correcte, el programa ha d’anar llegint tot el text que escrigui l’usuari i, cada cop que acaba d’introduir una línia, en prémer la tecla de retorn, desar-lo al fitxer. El programa acaba quan l’usuari escriu una línia de text en la qual només hi ha un punt (”.”). Aquest punt no s’escriu dins el fitxer resultant.

  1. package unitat6.apartat2.activitats;
  2.  
  3. import java.util.Scanner;
  4. import java.io.File;
  5. import java.io.PrintStream;
  6.  
  7. public class MaquinaEscriure {
  8.  
  9. public static void main (String[] args) {
  10. MaquinaEscriure programa = new MaquinaEscriure();
  11. programa.inici();
  12. }
  13.  
  14. public void inici() {
  15. try {
  16. File fitxerSortida = preguntarFitxer();
  17. PrintStream escriptor = new PrintStream(fitxerSortida);
  18. Scanner lector = new Scanner(System.in);
  19.  
  20. boolean llegir = true;
  21. while (llegir) {
  22. String text = lector.nextLine();
  23. if (".".equals(text)) {
  24. llegir = false;
  25. } else {
  26. escriptor.println(text);
  27. }
  28. }
  29.  
  30. escriptor.close();
  31. } catch (Exception e) {
  32. System.out.println("Error escrivint fitxer: " + e);
  33. }
  34. }
  35.  
  36. /** Pregunta a l'usuari el nom del fitxer.
  37.   *
  38.   * @return Ruta al fitxer a escriure
  39.   */
  40. public File preguntarFitxer() {
  41. Scanner lector = new Scanner(System.in);
  42. boolean preguntar = true;
  43. File f = null;
  44. while (preguntar) {
  45. System.out.print("Escriu el nom del fitxer on escriure: ");
  46. String nomFitxer = lector.nextLine();
  47. f = new File(nomFitxer);
  48. if (f.exists()) {
  49. System.out.println("El fitxer ja existeix.");
  50. } else {
  51. preguntar = false;
  52. }
  53. }
  54. return f;
  55. }
  56. }

Histogrames

L’objectiu d’aquesta activitat és veure com desar en un fitxer orientat a caràcter el resultat de fer operacions complexes sobre unes dades llegides des d’un altre fitxer.

Genereu un programa que, en iniciar-se, pregunti el nom d’un fitxer a l’usuari. El programa ha de comprovar que existeix. Aquest fitxer ha de contenir una seqüència de valors reals, entre 0 i 10, que representen un seguit de notes d’estudiants d’una aula. Per indicar el final de la seqüència, s’usa el valor -1 com a marca de fi. Podeu generar-lo prèviament vosaltres mateixos amb un editor de text.

El programa ha de llegir el contingut del fitxer i generar-ne un de nou anomenat “Histograma-nom del fitxer llegit”. Per exemple, si el fitxer amb les notes es diu, “NotesReals.txt”, el fitxer resultat s’anomenarà “Histograma-NotesReals.txt”. El contingut d’aquest fitxer ha de ser un histograma de les notes, comptant que:

  • Excel·lent = nota entre 10 i 9
  • Notable = nota entre 9 i 6.5
  • Aprovat = nota entre 6.5 i 5
  • Suspès = nota inferior a 5

Per exemple, si el fitxer “NotesReals.txt” conté:

10 8,5 4,5 3,75 6 7,5 8 9 2,5 9 5 6,5 -1

El fitxer resultant “Histograma-NotesReals.txt” contindria el següent:

Histograma del fitxer NotesReals.txt
------------
Suspès    :***
Aprovat   :**
Notable   :****
Excel·lent:***

  1. package unitat6.apartat2.activitats;
  2.  
  3. import java.util.Scanner;
  4. import java.io.File;
  5. import java.io.PrintStream;
  6.  
  7. public class Histogrames {
  8.  
  9. //Constant que tradueix <blau>índexs d'histograma</blau><nota blau>és correcta l'esmena? --- //[[cortegai@uoc.edu|Clara Ortega Illera]] 11/08/2011 17:43//</nota> a text
  10. private static final String[] textHistograma =
  11. {"Suspès ", "Aprovat ", "Notable ", "Excel·lent"};
  12.  
  13. public static void main (String[] args) {
  14. Histogrames programa = new Histogrames();
  15. programa.inici();
  16. }
  17.  
  18. public void inici() {
  19. File fitxerEntrada = preguntarFitxer();
  20. int[] histograma = crearHistograma(fitxerEntrada);
  21.  
  22. String nomSortida = "Histograma-" + fitxerEntrada.getName();
  23. File fitxerSortida = new File (nomSortida);
  24. String titol = "Histograma del fitxer " + fitxerEntrada.getName();
  25. escriureHistograma(titol, histograma, fitxerSortida);
  26.  
  27. System.out.println("Histograma escrit al fitxer " + fitxerSortida);
  28. }
  29.  
  30. /** Pregunta a l'usuari el nom del fitxer.
  31.   *
  32.   * @return Ruta al fitxer a escriure
  33.   */
  34. public File preguntarFitxer() {
  35. Scanner lector = new Scanner(System.in);
  36. boolean preguntar = true;
  37. File f = null;
  38. while (preguntar) {
  39. System.out.print("Escriu el nom del fitxer amb les dades: ");
  40. String nomFitxer = lector.nextLine();
  41. f = new File(nomFitxer);
  42. if (f.isFile()) {
  43. preguntar = false;
  44. } else {
  45. System.out.println("Aquest fitxer no existeix.");
  46. }
  47. }
  48. return f;
  49. }
  50.  
  51. /** A partir d'un fitxer orientat a caràcter que conté reals, genera
  52.   * l'histograma. El valor -1 indica el final de les dades.
  53.   *
  54.   * @param f Fitxer d'on llegir les dades
  55.   * @return L'array de l'histograma.
  56.   */
  57. public int[] crearHistograma(File f) {
  58. try {
  59. Scanner lector = new Scanner(f);
  60. int[] histograma = new int[4];
  61. boolean llegir = true;
  62.  
  63. while (llegir) {
  64. double valor = lector.nextDouble();
  65. if (valor == -1) {
  66. llegir = false;
  67. } else {
  68. int index = indexHistograma(valor);
  69. if (index != -1) {
  70. histograma[index]++;
  71. }
  72. }
  73. }
  74.  
  75. lector.close();
  76. return histograma;
  77. } catch (Exception e) {
  78. return null;
  79. }
  80. }
  81.  
  82. /** Escriu un array que representa un histograma a un fitxer.
  83.   *
  84.   * @param titol Títol a la primera línia de l'histograma.
  85.   * @param histograma array amb l'histograma (4 posicions)
  86.   * @param f Fitxer destinació
  87.   */
  88. public void escriureHistograma(String titol, int[] histograma, File f) {
  89. try {
  90. PrintStream escriptor = new PrintStream(f);
  91. escriptor.println(titol);
  92. escriptor.println("------------");
  93. for(int i = 0; i < histograma.length; i++) {
  94. escriptor.print(textHistograma[i] + ":");
  95. for (int j = 0; j < histograma[i]; j++) {
  96. escriptor.print("*");
  97. }
  98. escriptor.println();
  99. }
  100.  
  101. escriptor.close();
  102. } catch (Exception e) {
  103. System.out.println("Error escrivint resultat: " + f);
  104. }
  105. }
  106.  
  107. /** A partir del valor d'una nota, diu a quin índex de l'histograma correspon.
  108.   *
  109.   * @param valor Valor de nota a comprovar.
  110.   * @return Índex de l'histograma (0-3), o -1 si el valor no està entre 0 i 10.
  111.   */
  112. public int indexHistograma(double valor) {
  113. if ((valor >= 9)&&(valor <= 10)) {
  114. return 3;
  115. } else if ((valor >= 6.5)&&(valor < 9)) {
  116. return 2;
  117. } else if ((valor >= 5)&&(valor < 6.5)) {
  118. return 1;
  119. } else if ((valor >= 0)&&(valor < 5)) {
  120. return 0;
  121. }
  122. return -1;
  123. }
  124. }

Cadenes de bytes

L’objectiu d’aquesta activitat és aprendre a tractar fitxers orientats a byte que contenen diferents tipus de dades.

1. Genereu un programa que, a partir d’una frase, la desi en un fitxer orientat a byte. Ara bé, si us fixeu en els continguts de la unitat, veureu que entre la llista de mètodes bàsics per escriure tipus de dades a un fitxer d’aquestes característiques no hi ha cap mètode que escrigui cadenes de text directament. Per tant, el que es farà és emmagatzemar cada paraula individualment com si fos una seqüència de bytes. Per cada paraula, cal escriure primer la seva mida en bytes, i llavors immediatament els bytes de què es composa. Per transformar una cadena de text a un array de bytes podeu usar el mètode getBytes() de la classe String.

Per exemple, si es vol tractar la frase “Hi havia una vegada una cadena de text”, el fitxer contindria consecutivament els valors següents, tots ells en format binari (aquí s’escriuen com a text perquè us sigui possible entendre-ho).

2 Hi 5 havia 3 una 6 vegada 3 una 6 cadena 2 de 4 text

2. Un cop fet, genereu un programa que sigui capaç de llegir el fitxer resultant i mostri per pantalla només les paraules amb un text que ocupi més de 3 bytes. Per exemple, a partir de la frase anterior, el programa mostraria:

havia
vegada
cadena
text

Per inicialitzar una cadena de text partint d’un array de bytes (en lloc d’un literal entre cometes dobles, com heu fet sempre fins ara) es pot usar un constructor especial d‘String, d’acord a la sentència següent:

String text = new String(arrayBytes);

  1. package unitat6.apartat2.activitats;
  2.  
  3. import java.io.RandomAccessFile;
  4. import java.io.File;
  5.  
  6. public class TractarCadenesBinari {
  7.  
  8. public static void main (String[] args) {
  9. TractarCadenesBinari programa = new TractarCadenesBinari();
  10. programa.inici();
  11. }
  12.  
  13. public void inici() {
  14. File fitxer = new File("CadenesText.bin");
  15.  
  16. String text = "Hi havia una vegada una cadena de text";
  17. String[] paraules = text.split(" ");
  18.  
  19. generarFitxer(fitxer, paraules);
  20. tractarFitxer(fitxer);
  21. }
  22.  
  23. /** Genera un fitxer orientat a byte d'acord al format especificat. Si el
  24.   * fitxer ja existia, se sobreescriu totalment.
  25.   *
  26.   * @param f Ruta del fitxer a generar
  27.   * @param paraules Paraules que cal escriure
  28.   */
  29. public void generarFitxer(File f, String[] paraules) {
  30. try {
  31. if (f.isFile()) {
  32. f.delete();
  33. }
  34. RandomAccessFile raf = new RandomAccessFile(f, "rw");
  35.  
  36. for (int i = 0; i < paraules.length; i++) {
  37. byte[] bytes = paraules[i].getBytes();
  38. raf.writeInt(bytes.length);
  39. raf.writeBytes(paraules[i]);
  40. }
  41.  
  42. raf.close();
  43. } catch (Exception e) {
  44. System.out.println("Error generant fitxer: " + e);
  45. }
  46. }
  47.  
  48. /** Tracta el fitxer, de manera que es mostren per pantalla només les
  49.   * paraules que ocupen més de tres bytes.
  50.   *
  51.   * @param f Ruta al fitxer que cal tractar
  52.   */
  53. public void tractarFitxer(File f) {
  54. try {
  55.  
  56. while (raf.getFilePointer() < raf.length()) {
  57. int numBytes = raf.readInt();
  58. if (numBytes > 3) {
  59. //Si ocupa més de tres bytes, es llegeix i es mostra
  60. byte[] bytes = new byte[numBytes];
  61. for (int i = 0; i < numBytes; i++) {
  62. bytes[i] = raf.readByte();
  63. }
  64. String paraula = new String(bytes);
  65. System.out.println(paraula);
  66. } else {
  67. //Si n'ocupa menys, se salta
  68. raf.skipBytes(numBytes);
  69. }
  70. }
  71.  
  72. raf.close();
  73. } catch (Exception e) {
  74. System.out.println("Error tractant fitxer: " + e);
  75. }
  76. }
  77.  
  78.  
  79. }

Copiar fitxers

L’objectiu d’aquesta activitat és aprendre a treballar amb dos fitxers orientats a byte alhora, l’un per llegir dades i l’altre per escriure’n.

Feu un programa anomenat CopiarFitxerBinari que realitzi una còpia d’un fitxer orientat a byte. El programa primer ha de demanar a l’usuari que introdueixi pel teclat els noms dels fitxers origen i destinació. Un cop fet, ha d’assegurar-se que l’origen existeix i que el destí no (no es vol sobreescriure’l). Finalment, ha de crear un fitxer amb el nom de la destinació que contingui exactament les mateixes dades que el fitxer origen, siguin quines siguin aquestes dades o el seu tipus.

Un cop heu realitzat el programa i veieu que funciona correctament, reflexioneu sobre la qüestió següent: funcionarà correctament si el fitxer origen és orientat a caràcter? Proveu-ho.

  1. package unitat6.apartat2.activitats;
  2.  
  3. import java.util.Scanner;
  4. import java.io.File;
  5. import java.io.RandomAccessFile;
  6.  
  7. //Proveu-lo sobre un fitxer orientat a caràcter...
  8. public class CopiarFitxerBinari {
  9.  
  10. public static void main (String[] args) {
  11. CopiarFitxerBinari programa = new CopiarFitxerBinari();
  12. programa.inici();
  13. }
  14.  
  15. public void inici() {
  16. //Es llegeix de teclat rutes origen i destinació
  17. Scanner teclat = new Scanner(System.in);
  18. System.out.print("Escriu el nom del fitxer origen: ");
  19. String origen = teclat.nextLine();
  20. File rutaOrigen = new File(origen);
  21.  
  22. if (rutaOrigen.isFile()) {
  23.  
  24. System.out.print("Escriu el nom del fitxer destinació: ");
  25. String desti = teclat.nextLine();
  26. File rutaDesti = new File(desti);
  27.  
  28. if (rutaDesti.isFile()) {
  29. System.out.println("El fitxer destinació ja existeix.");
  30. } else {
  31. ferCopia(rutaOrigen, rutaDesti);
  32. }
  33. } else {
  34. System.out.println("El fitxer origen no existeix.");
  35. }
  36. }
  37.  
  38. /** Copia un fitxer orientat a byte, a partir d'una ruta origen, a una de destinació.
  39.   *
  40.   * @param rutaOrigen Ruta del fitxer origen
  41.   * @param rutaDesti Ruta del fitxer destinació
  42.   */
  43. public void ferCopia(File rutaOrigen, File rutaDesti) {
  44. try {
  45. RandomAccessFile rafOrigen = new RandomAccessFile(rutaOrigen, "r");
  46. RandomAccessFile rafDesti = new RandomAccessFile(rutaDesti, "rw");
  47.  
  48. long numBytes = rutaOrigen.length();
  49. for (int i = 0; i < numBytes; i++) {
  50. byte dada = rafOrigen.readByte();
  51. rafDesti.writeByte(dada);
  52. }
  53. rafDesti.setLength(numBytes);
  54.  
  55. rafOrigen.close();
  56. rafDesti.close();
  57. System.out.println("Copia finalitzada correctament.");
  58. } catch (Exception e) {
  59. System.out.println("Error fent la còpia: " + e);
  60. }
  61. }
  62.  
  63. }

Respecte a la qüestió, sí que funcionarà. Si us pareu a pensar, un fitxer orientat a caràcter és exactament el mateix que un fitxer orientat a byte on totes les dades que conté són de tipus caràcter (char).

Actualització de dades

L’objectiu d’aquesta activitat és veure com treballar amb documents orientats a byte, de manera que s’hi puguin modificar les dades contingudes.

Feu un programa que serveixi com a editor de fitxers orientats a byte que contingui només enters. Aquest s’ha de comportar de la manera següent. En iniciar la seva execució, ha de preguntar a l’usuari quin fitxer vol editar, de manera que aquest pugui escriure el nom usant el teclat. Llavors, ha de mostrar el contingut del fitxer per pantalla, distribuït en files de 10 valors. No cal que formateu la sortida en columnes ben proporcionades. Si el fitxer no existia, se’n crea un de nou i, en aquest cas, no apareix cap valor, ja que el fitxer és buit.

Tot just després dels valors, el programa espera que l’usuari escrigui una comanda, d’entre les següents:

  • a valor: afegir aquest valor al final del fitxer.
  • d posició: esborrar el valor que hi ha en aquesta posició, comptant que el primer valor es considera en la posició 0. Ara hi ha un valor menys al fitxer.
  • x: el programa acaba.

Després d’executar cada comanda, menys la de sortir, es torna a mostrar el contingut del fitxer, de manera que es poden veure els canvis soferts.

Tot seguit es mostra un exemple de com podria ser l’execució del programa.

Escriu el nom del fitxer a editar: FitxerEnters.bin

-------------
Comanda: hfdsgjf
Comanda desconeguda.

-------------
Comanda: a 3

3 
-------------
Comanda: a 50

3 50 
-------------
Comanda: a 40

3 50 40 
-------------
Comanda: a 2

3 50 40 2 
-------------
Comanda: d 1

3 40 2 
-------------
Comanda: x

  1. package unitat6.apartat2.activitats;
  2.  
  3. import java.io.RandomAccessFile;
  4. import java.io.File;
  5. import java.util.Scanner;
  6.  
  7. public class ActualitzacioDades {
  8.  
  9. public static void main (String[] args) {
  10. ActualitzacioDades programa = new ActualitzacioDades();
  11. programa.inici();
  12. }
  13.  
  14. public void inici() {
  15. try {
  16. //Es llegeix de teclat ruta del fitxer
  17. Scanner teclat = new Scanner(System.in);
  18. System.out.print("Escriu el nom del fitxer a editar: ");
  19. String origen = teclat.nextLine();
  20. File fitxer = new File(origen);
  21. RandomAccessFile raf = new RandomAccessFile(fitxer, "rw");
  22.  
  23. boolean executar = true;
  24.  
  25. while(executar) {
  26. mostrarFitxer(raf);
  27. System.out.println("\n-------------");
  28. System.out.print("Comanda: ");
  29. //Llegir comanda
  30. String comanda = teclat.next();
  31. if ("x". equals(comanda)) {
  32. executar = false;
  33. } else {
  34. if ("a".equals(comanda)&&teclat.hasNextInt()) {
  35. int valor = teclat.nextInt();
  36. afegirValor(raf,valor);
  37. } else if ("d".equals(comanda)&&teclat.hasNextInt()) {
  38. int posicio = teclat.nextInt();
  39. eliminarValor(raf,posicio);
  40. } else {
  41. System.out.println("Comanda desconeguda.");
  42. }
  43. }
  44. }
  45.  
  46. raf.close();
  47.  
  48. } catch (Exception e) {
  49. System.out.println("Error accedint al fitxer: " + e);
  50. }
  51. }
  52.  
  53. /** Mostra el contingut del fitxer per pantalla, escrivint 10 valors
  54.   * per fila. Fixeu-vos que un RandomAccessFile es pot passar com a paràmetre.
  55.   *
  56.   * @param raf Fitxer d'acces relatiu a mostrar
  57.   */
  58. public void mostrarFitxer(RandomAccessFile raf) {
  59. try {
  60. long numEnters = raf.length()/4;
  61. //Cal garantir que l'apuntador esta al principi
  62. raf.seek(0);
  63. for (long i = 0; i < numEnters; i++) {
  64. if (i%10 == 0) {
  65. System.out.println();
  66. }
  67. int valor = raf.readInt();
  68. System.out.print(valor + " ");
  69. }
  70. } catch (Exception e) {
  71. System.out.println("Error llegint fitxer: " + e);
  72. }
  73. }
  74.  
  75. /** A partir d'un fitxer d'enters, afegeix un valor al final.
  76.   *
  77.   * @param raf Fitxer a modificar
  78.   * @param valor Valor a afegir
  79.   */
  80. public void afegirValor(RandomAccessFile raf, int valor) {
  81. try {
  82. long fiFitxer = raf.length();
  83. raf.seek(fiFitxer);
  84. raf.writeInt(valor);
  85. } catch (Exception e) {
  86. System.out.println("Error modificant fitxer: " + e);
  87. }
  88. }
  89.  
  90. /** A partir d'un fitxer d'enters, elimina un valor.
  91.   *
  92.   * @param raf Fitxer a modificar
  93.   * @param posicio Posició a esborrar
  94.   */
  95. public void eliminarValor(RandomAccessFile raf, int posicio) {
  96. try {
  97. if ((posicio >= raf.length()/4)||(posicio < 0)) {
  98. System.out.println("Aquesta posició no existeix.");
  99. } else {
  100. long midaFinal = raf.length() - 4;
  101. //Per esborrar un valor, cal desplaçar tots els posteriors a sobre
  102. //de l'anterior valor.
  103. long posMoure = (posicio + 1)*4;
  104. while (posMoure < raf.length()) {
  105. raf.seek(posMoure);
  106. int valor = raf.readInt();
  107. raf.seek(posMoure - 4);
  108. raf.writeInt(valor);
  109. posMoure = posMoure + 4;
  110. }
  111. //Queda el darrer valor repetit. Cal ajustar la nova mida del fitxer
  112. raf.setLength(midaFinal);
  113. }
  114. } catch (Exception e) {
  115. System.out.println("Error modificant fitxer: " + e);
  116. }
  117. }
  118.  
  119. }

Anar a la pàgina anterior:
Tractament bàsic de dades
Anar a la pàgina següent:
Exercicis d'autoavaluació