Skip to content

Commit 58c9c75

Browse files
committed
Añade referencias a .getResourceAsStream()
1 parent 120fe0b commit 58c9c75

File tree

5 files changed

+114
-34
lines changed

5 files changed

+114
-34
lines changed

source/01.archivos/01.gestion.rst

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,59 @@ podemos hacer construcciones como esta:
253253
[#]_ y crear código condicional que implemente la solución dependiendo
254254
cuál sea.
255255

256+
.. _file-arc-pro:
257+
258+
Archivos del proyecto
259+
---------------------
260+
Es común que, cuando desarrollamos una aplicación, tengamos que hacer referencia
261+
a archivos que hemos incluido dentro de ella. Un error de principiante es hacer
262+
lo siguiente:
263+
264+
.. code-block:: java
265+
266+
// No haga esto jamás.
267+
Path path = Path.of(System.getProperty("user.dir"), "imagen.jpg");
268+
269+
Durante el desarrollo, si colocamos el archivo de imagen en el directorio de
270+
proyecto, la aplicación posiblemente encontrará el archivo, porque el |IDE|
271+
suele fijar el *directorio de proyecto* (que es lo que significa realmente
272+
``user.dir``) como *directorio de trabajo*. Sin embargo, al empaquetarla en
273+
un archivo |JAR|, no lo hará porque el archivo se encontrará dentro del paquete
274+
y el directorio de trabajo será el directorio desde el que el usuario ejecuta la
275+
aplicación.
276+
277+
La forma correcta de acceder a archivos para su lectura incluidos en la
278+
aplicación es:
279+
280+
.. code-block:: java
281+
282+
// Obsérvese la ruta absoluta.
283+
InputStream st = getClass().getResourceAsStream("/imagen.jpg");
284+
285+
que abre el archivo como un |InputStream| para su lectura y entiende que el
286+
archivo está en la raíz del *classpath*. Ya veremos más adelante :ref:`cómo
287+
utilizar estos flujos <iotext-r>`.
288+
289+
.. note:: Hemos supuesto que la línea está dentro de un método de instancia. Si
290+
fuera estático, tendríamos que utilizar directamente la clase:
291+
292+
.. code-block:: java
293+
294+
InputStream st = Main.class.getResourceAsStream("/imagen.jpg");
295+
296+
Cuando la ruta es relativa, en vez de absoluta, se entiende que es referida
297+
al directorio del *classpath* donde se encuentra la clase que se utiliza para
298+
invocar el método.
299+
300+
.. caution:: En los proyectos de *Java* suele existir un directorio
301+
:file:`resources` para almacenar archivos con datos. El contenido de este
302+
directorio acaba en la aplicación en la raíz del *classpath*. Por tanto, el
303+
archivo de imagen que hemos puesto de ejemplo, podríamos hacerlo incluido en
304+
este subdirectorio del proyecto. Ahora bien, con :ref:`Maven` la copia a
305+
*classpath* no es automática y hay que declararla en :file:`pom.xml`. Vea un
306+
ejemplo de :ref:`cómo añadir archivos con propiedades <add-resources>` en uno
307+
de los apéndices.
308+
256309
.. _file.files:
257310

258311
Gestión
@@ -397,3 +450,7 @@ contenido, pero los dejamos para el siguiente epígrafe.
397450
.. |API| replace:: :abbr:`API (Application Programming Interface)`
398451
.. |MIME| replace:: :abbr:`MIME (Multipurpose Internet Mail Extensions)`
399452
.. |URI| replace:: :abbr:`URI (Uniform Resource Identifier)`
453+
.. |IDE| replace:: :abbr:`IDE (Integrated Development Environment)`
454+
.. |JAR| replace:: :abbr:`JAR (Java ARchive)`
455+
.. |InputStream| replace:: :java-io:`InputStream <InputStream>`
456+

source/01.archivos/02.manipulacion.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ y que también coincide con el tipo de ``System.in``:
8080
8181
InputStream st = System.in;
8282
83+
Un caso particular son los archivos que se incluyen dentro de la aplicación,
84+
que pueden leerse con:
85+
86+
.. code-block:: java
87+
88+
String rutaRelativa = "/ruta/relativa/a/resources/archivo.txt"
89+
InputStream st = getClass().getResourceAsStream(rutaRelativa);
90+
91+
.. caution:: Se está suponiendo que el código está dentro de un método de
92+
instancia y, por tanto, se dispone del objeto ``this``. Si el método es
93+
estático, entonces debe utilizarse directamente la clase:
94+
95+
.. code-block:: java
96+
97+
// El método está, por ejemplo, en la clase 'Main'.
98+
InputStream st = Main.class.getResourceAsStream(rutaRelativa);
99+
100+
..
101+
83102
En consecuencia, a partir de este punto podemos tratar estas tres entradas
84103
diferentes de un mismo modo (p.e. usando la clase :java-util:`Scanner
85104
<Scanner>`). Si el archivo lo vamos a manejar por líneas lo más adecuado es

source/03.xml/01.jaxp.rst

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@ Comencemos por conocer cómo abrir un documento |XML| y acceder a sus nodos:
1414

1515
.. code-block:: java
1616
17-
Path ruta = Path.of(System.getProperty("user.home"), "claustro.xml");
1817
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1918
// La siguiente línea puede provocar un ParseConfigurationException
2019
DocumentBuilder builder = factory.newDocumentBuilder();
2120
22-
try (InputStream st = Files.newInputStream(ruta)) {
21+
try (InputStream st = getClass().getResourceAsStream("/claustro.xml")) {
2322
// La línea posterior también puede generar una excepción.
2423
Document xml = builder.parse(st);
2524
// Accedemos a la información del documento a través de su DOM.
@@ -39,14 +38,11 @@ Comencemos por conocer cómo abrir un documento |XML| y acceder a sus nodos:
3938
<jaxp-dtd>`.
4039

4140
Una vez tenemos disponible el objeto `Document` ya podremos acceder a los nodos
42-
del documento. En principio, los nodos se modelan mediante la clase `Node
43-
<https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Node.html>`_ sobre la que
44-
construyen subsclases que modelan los distintos tipos de nodos (`Element
45-
<https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Element.html>`_, `Text
46-
<https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Text.html>`_, `Attr
47-
<https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Attr.html>`_, etc.). Cada
48-
uno de estos tipos de nodos está asociado a un número entero al que se da
49-
nombre mediante un atributo estático de `Node`_. Por ejemplo:
41+
del documento. En principio, los nodos se modelan mediante la clase |Node| sobre
42+
la que construyen subsclases que modelan los distintos tipos de nodos
43+
(|Element|, |Text|, |Attr|, etc.). Cada uno de estos tipos de nodos está
44+
asociado a un número entero al que se da nombre mediante un atributo estático de
45+
|Node|. Por ejemplo:
5046

5147
.. code-block:: java
5248
@@ -73,7 +69,7 @@ hacer diversas pesquisas:
7369

7470
``getNodeValue()``
7571
devuelve el valor del nodo. Dependiendo del tipo de nodo, así será su valor
76-
(al comienzo de la explicación sobre Node_ hay una tabla que indica qué valor
72+
(al comienzo de la explicación sobre |Node| hay una tabla que indica qué valor
7773
devuelve cada tipo).
7874

7975
``getTextContent()``
@@ -89,8 +85,8 @@ hacer diversas pesquisas:
8985

9086
.. code-block:: java
9187
92-
// apelativo es una variable que contiene el elemento apelativo comentado
93-
apelativo.getTextContent() == apelativo.firstChild().getNodeValue();
88+
// apelativo es una variable que contiene el elemento apelativo antedicho
89+
apelativo.getTextContent().equals(apelativo.firstChild().getNodeValue());
9490
9591
``getFirstChild()`` o ``getLastChild()``
9692
Devuelve el primero o el último **nodo** hijo de aquel. Se ha remarcado nodo,
@@ -101,13 +97,11 @@ hacer diversas pesquisas:
10197
devuelve el nodo padre o el hermano previo o el hermano siguiente.
10298

10399
``getChildNodes()``
104-
devuelve un objeto `NodeList
105-
<https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/NodeList.html>`_ con
106-
los nodos hijos. A pesar de su naturaleza no implementa la interfaz
107-
:java-lang:`Iterable <Iterable>` y sólo presenta un método (``getLength()``)
108-
que devuelve la cantidad de hijos y un método ``item(int index)`` que
109-
devuelve el i-ésimo nodo de la lista. Por tanto, si se quiere quiere recorrer
110-
la colección, habrá que usar un `for` clásico:
100+
devuelve un objeto |NodeList| con los nodos hijos. A pesar de su naturaleza
101+
no implementa la interfaz :java-lang:`Iterable <Iterable>` y sólo presenta un
102+
método (``getLength()``) que devuelve la cantidad de hijos y un método
103+
``item(int index)`` que devuelve el i-ésimo nodo de la lista. Por tanto, si
104+
se quiere quiere recorrer la colección, habrá que usar un `for` clásico:
111105

112106
.. code-block:: java
113107
@@ -124,7 +118,7 @@ hacer diversas pesquisas:
124118
}
125119
126120
.. tip:: Pese a que, a priori, sólo podemos utilizar el `for` tradicional
127-
para recorrer NodeList_, podemos buscarnos las vueltas para convertirlo
121+
para recorrer |NodeList|, podemos buscarnos las vueltas para convertirlo
128122
en un flujo y poder usar con él técnicas de :ref:`Java funcional <funcional>`:
129123

130124
.. code-block:: Java
@@ -133,12 +127,11 @@ hacer diversas pesquisas:
133127
Stream<Node> streamNode = IntStream.range(0, hijos.getLength()).mapToObj(hijos::item);
134128
135129
``getAttributes()``
136-
devuelve los atributos del elemento en forma de `NamedNodeMap
137-
<https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/NamedNodeMap.html>`_
138-
que como NodeList_ tampoco implemente la interfaz :java-lang:`Iterable
139-
<Iterable>`. Además de ``item(int index)`` y ``getLength()``, dispone también
140-
de ``getNamedItem(String name)`` que permite obtener el nodo atributo a
141-
partir de su nombre:
130+
devuelve los atributos del elemento en forma de |NamedNodeMap| que como
131+
|NodeList| tampoco implemente la interfaz :java-lang:`Iterable <Iterable>`.
132+
Además de ``item(int index)`` y ``getLength()``, dispone también de
133+
``getNamedItem(String name)`` que permite obtener el nodo atributo a partir
134+
de su nombre:
142135

143136
.. code-block:: java
144137
@@ -151,12 +144,12 @@ hacer diversas pesquisas:
151144
}
152145
153146
Por otra parte, los tipos de nodos tiene también sus métodos específicos. Por
154-
ejemplo, Element_:
147+
ejemplo, |Element|:
155148

156149
``getElementsByTagName(String name)``
157150
devuelve los elementos descendientes cuyo nombre de etiqueta es el
158151
suministrado en el argumento. El método también existe para los nodo
159-
`Document <https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Document.html>`_:
152+
|Document|:
160153

161154
.. code-block:: java
162155
@@ -172,7 +165,7 @@ ejemplo, Element_:
172165
Element p17 = xml.getElementById("p17"); // null, porque no estamos usando el DTD
173166
174167
``getAttributeNode(String name)`` o ``getAttribute(String name)``
175-
devuelve el atributo (Attr_) o el valor del atributo cuyo nombre se
168+
devuelve el atributo (|Attr|) o el valor del atributo cuyo nombre se
176169
proporciona en el argumento.
177170

178171
.. _jaxp-dtd:
@@ -303,7 +296,7 @@ crearlo *ex novo*:
303296
304297
Escritura a archivo
305298
-------------------
306-
Partamos de que ya tenemos un Document_ construido como queremos que quede
299+
Partamos de que ya tenemos un |Document| construido como queremos que quede
307300
(véase el apartado anterior) y queremos ahora generar el |XML| correspondiente:
308301

309302
.. code-block:: java
@@ -385,11 +378,19 @@ si nuestra intención es usarla una sola vez:
385378

386379
.. [#] En realidad el método tiene sentido para otros nodos que no sean
387380
elementos. Véase la tabla que resume sus significados en la explicación del
388-
método que ofrece la documentación original de Node_.
381+
método que ofrece la documentación original de |Node|.
389382
390383
.. |JAXP| replace:: :abbr:`JAXP (Java API for XML Processing)`
391384
.. |XML| replace:: :abbr:`XML (eXtensible Markup Language)`
392385
.. |DOM| replace:: :abbr:`DOM (Document Object Model)`
393386
.. |DTD| replace:: :abbr:`DTD (Document Type Definition)`
394387
.. |JDK| replace:: :abbr:`JDK (Java Development Kit)`
395388
.. |URL| replace:: :abbr:`URL (Uniform Resource Locator)`
389+
390+
.. |Node| replace:: :java-jaxp:`Node`
391+
.. |Element| replace:: :java-jaxp:`Element`
392+
.. |Attr| replace:: :java-jaxp:`Attr`
393+
.. |Text| replace:: :java-jaxp:`Text`
394+
.. |NodeList| replace:: :java-jaxp:`NodeList`
395+
.. |NamedNodeMap| replace:: :java-jaxp:`NamedNodeMap`
396+
.. |Document| replace:: :java-jaxp:`Document`

source/98.apendices/15.cli.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,11 @@ a. Crear un archivo dentro de :file:`src/main/resources` que copie los valores
434434
app.version=${project.version}
435435
app.description=${project.description}
436436
437+
.. _add-resources:
437438

438-
#. Añadir en :file:`pom.xml` un sección que habilite la sustitución de las
439-
variables incluidas en el archivo anterior por sus valores:
439+
#. Añadir en :file:`pom.xml` un sección que añada el archivo al proyecto y
440+
habilite la sustitución de las variables incluidas en el archivo anterior
441+
por sus valores:
440442

441443
.. code-block:: xml
442444

source/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
'java-io': ('https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/io/%s.html', 'java.io.%s'),
4949
'java-nio': ('https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/nio/file/%s.html', 'java.nio.file.%s'),
5050
'java-lang': ('https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/%s.html', '%s'),
51+
'java-jaxp': ('https://docs.oracle.com/en/java/javase/23/docs/api/java.xml/org/w3c/dom/%s.html', '%s'),
5152
'java-function': ('https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/function/%s.html', 'java.util.function.%s'),
5253
'java-stream': ('https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/stream/%s.html', 'java.util.stream.%s'),
5354
'java-sql': ('https://docs.oracle.com/en/java/javase/23/docs/api/java.sql/java/sql/%s.html', 'java.sql.%s'),

0 commit comments

Comments
 (0)