PushbackReader en NetBeans

Hola a todos,

Sigo aprendiendo este hermoso lenguaje con ayuda de algunos libros y en especial con el de Fco. Ceballos, bueno pues tengo un problema al correr la siguiente linea: nombreFichero = Leer.dato(); en Netbeans, meto un nombre mediante el teclado y pues NetBeans no hace nada, ya lo probe con Eclipse y bien que funciona, el problema es que me siento mas comodo con NetBeans que con Eclipse, ¿saben si puedo solucionar este problema?.

Saludos y de antemano gracias.

Este es el fragmento de la clase que debe de leer la cadena

 

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

JVM's

Seguramente es por una diferencia entre versiones de JVM. Necesitas revisar la version de JVM que usa Eclipse y la que usa NetBeans.

Supongo que esto es un ejercicio, porque en Java 6 ya puedes usar simplemente System.console().readLine() que hasta acepta un prompt.

Imagen de samz550a

esos mes haces pensars

¿ya cuantas formas hay de leer de consola?

Habia visto algo por ahí de Scanner... ahora el codigo inicial de este hilo y también lo de System.console().readLine() es nuevo para mi... ... además he utilizado siempre otra manera que vendrá de antes de java 1.4 con algo de BufferedInputStream o algo similar... ya no recuerdo.

¿cual seria la mejor manera para leer de consola? ¿por qué tantas formas tan distintas? hay alguna mas practica que todas?

Imagen de ezamudio

Console

La clase Console es nueva en Java 6, me ha parecido la mejor; puedes hacer cosas como:

 

La primera linea presenta el prompt y en esa misma linea lee lo que el usuario escriba hasta dar ENTER y devuelve esa cadena.
La segunda linea presenta el prompt y en esa misma linea lee lo que el usuario escriba hasta dar ENTER, pero sin mostrar lo tecleado en pantalla, y devuelve los caracteres tecleados.
La tercera linea presenta el prompt, que como puedes ver, es de forma similar a String.format().

Antes se podia usar BufferInputStream o LineNumberReader, pero es mas engorroso:

 

y para leer passwords no habia manera de capturar datos sin que se vieran en la pantalla (estamos hablando de programas de linea de comando obviamente).

Eso si, hay que ver si System.console() no devuelve null, lo cual significa que el programa no esta corriendo de forma interactiva (puede ser un cronjob o le redirigieron el STDIN). Siempre vas a tener un System.in que puede venir de un archivo por ejemplo, si usas pipes o el "<" en la linea de comando, y siempre vas a tener un System.out, que puede ser la pantalla o un archivo si rediriges la salida (o puede ser un pipe). Pero no siempre vas a tener una consola.

Imagen de benek

Ahora con Scanner

Extracto que viene de acá:

La clase Scanner divide los datos ingresados de dos maneras, por líneas y por tokens, cuando haces nextLine() obtienes toda la línea, pero cuando obtienes next(), nextByte(), nextInt(), etc... obtienes el token siguiente (aunque esté en la misma línea) según un delimitador que puedes configurar. Este comportamiento es útil cuando le dices a Scanner que lea a partir un archivo, pero de alguna manera se anula cuando lees directo de System.in, por eso el comportamiento extraño, ahora explico.

Cuando lees con nextInt() (en tu caso, aunque es el mismo para los demás excepto nextLine()) la instancia de Scanner te devuelve lo ingresado, pero el enter que le tiene que dar el usuario lo guarda en el input, es por eso que cuando viene después el nextLine() lee lo que quedó del input (el salto de línea) y da otro más por el mismo comportamiento de nextLine(), entonces es como si el usuario hubiera dado un enter sin haber escrito nada.

Mira lo que dice la documentación de Scanner:

String nextLine()
Advances this scanner past the current line and returns the input that was skipped.

Lo solucionas usando next() en lugar de nextLine() después de usar cualquier next que devuelva un primitivo, en tu caso nextInt().

 

Salida:

Ingrese su nombre:
Benek
Ahora ingrese su direccion:
Sta Teresa
Ingrese Telefono:
55555
Ingrese su edad:
25
Ingrese su sexo:
Masculino
Hola Benek Vives en la direccion Sta Teresa Tu telefono es: 55555 Tienes 25 Años de edad y tu sexo es: Masculino

Process finished with exit code 0

Saludos!

Javier Ramírez Jr.

Imagen de francisco.santiagoj

Como puedo ver que JVM uso en Eclipse?

ezamudio, como puedo ver que JVM uso en eclipse, se que en NetBeans uso jdk1.6.0_18, pero en eclipse no se si toma la que tiene mi sistema o en su carpeta Zip viene la JVM incluida. de eclipse tengo la version Eclipse Java EE IDE for Web Developers. Build id: 20100218-1602 que baje hace un par de dias.

Saludos

Imagen de ezamudio

Eclipse JVM

Segun yo, Eclipse usa la JVM de tu sistema, no trae una incluida. En las preferencias de Eclipse hay una sección de JVM's disponibles que le puedes poner a tus proyectos; revisa primero la del proyecto (porque cada proyecto puede usar una JVM distinta), en las propiedades del proyecto, y si dice que está usando la general (de hecho creo que dice que NO está usando una propia del proyecto), entonces revisa las preferencias de Eclipse a ver qué JVM estás usando (puedes tener varias y seleccionar una por default).

Imagen de benek

RE: Como puedo ver que JVM uso en Eclipse?

Si no mal recuerdo es en:

Window > Preferences > Java > Installed JREs.

Saludos.

Imagen de francisco.santiagoj

Ya verifique en Eclipse y

Ya verifique en Eclipse y estaba usando la JVM de la carpeta C:\Archivos de programa\Java\jre6 ¿?, agrege C:\Archivos de programa\Java\jdk1.6.0_18 que es la misma de NetBeans y deje esta ultima seleccionada en el area de Installed JREs, cerre eclipse lo volvi a correr y mi ejercicio sigue fucnionando. Lei que NetBeans tiene problemas para leer el caracter -1 con los algunas subclases de Reader, pareciera que no diferencia cuando damos Enter. Mientras tanto seguire usando Eclipse para este ejercicio.

Saludos

Imagen de ezamudio

Suena grave

Suena a que es un bug muy serio en NetBeans entonces, aunque no sé qué tenga que ver el -1, puesto que estás leyendo de System.in y el método read() devuelve -1 cuando ya no hay nada que leer porque el stream está cerrado (pasa mucho en sockets por ejemplo).

Otra posibilidad es que ENTER en Eclipse sí trae \r mientras que en NetBeans solamente es \n; a fin de cuentas tu programa no es muy portable porque en Mac o Linux el ENTER solamente es un \n, mientras que en Windows es \r\n. Modifica tu condición de salida para que sea con \r o \n en vez de solamente \r a ver si con eso funciona en NetBeans.

Imagen de francisco.santiagoj

Listo!

Cambie \r por \n y funciono, seguramente NeteBans hace esto para la portabilidad que comenta ezamudio.

Gracias.

Imagen de samz550a

Leyendo desde consola con BufferedReader e InputStreamReader

Hola Javamexicanos, me quedé con la inquietud sobre lo que hablabamos sobre las diversas formas de leer desde consola; yo siempre he usado el siguiente método que de casualidad encuentro en una pagina... les dejo el enlace:::

<--- En la sección 3. Lecturas de cadenas desde el teclado con la clase java.io.BufferedReader

Al leer en el anterior enlace me sugue la duda sobre lo de "Envoltura de objetos de flujo"... ¿eso es lo mismo que la aplicación del patron Inyección de dependencias?
Porque podria interpretar que se le inyecta un objeto de la interfaz Reader en el constructor de BufferedReader y gracias a este objeto inyectado se invoca luego métodos como lo es readLine()

Por cierto, a BufferedReader se le inyecta también (siguiendo mi linea de pesamiento) objetos FileReader para leer desde archivos

¿estoy en lo cierto? ¿allí con lo de "envoltura" se está haciendo es una Inyección de dependencias?

Un gran saludo.

Imagen de ezamudio

Envoltura != inyección

eso de "envoltura de objetos de flujo" me imagino que fue la traducción de "stream object wrappers".

Sabes que hay subclases de InputStream y OutputStream (o de Reader y Writer) que envuelven otro stream (o Reader/Writer), como por ejemplo PrintStream, GzipOutputStream, CipherOutputStream, BufferedReader, LineNumberReader, etc. A eso se refiere la página que refieres, que no está muy actualizada porque ahora es más sencillo hacer System.console().readLine(), si es que vas a leer realmente de la consola (que el usuario teclee valores). La ventaja de System.in es que es el STDIN (standard input), que puede ser la consola (por default) o un archivo, o el resultado de otro proceso (pipes), etc.

Imagen de samz550a

El concepto de "envolver"

¿Como se interpreta el concepto de envolver en Java?

Se que hay tipos de envoltura para datos primitivos por ejemplo... para volver los datos primitivos en objetos y poder trabajarlos con el polimorfismo... pero en si ¿que significa envolver?
De los tipos primitivos podria pensar que efectivamente el wrapper guarda el dato para transportarlo y poder meterlo en alguna Colección... y luego se puede sacar y manipular como primitivo normalmente.

Pero lo de "stream object wrappers" me tiene confundido... o mejor dicho, no entiendo bien que significa "envolver" en java ¿que significa realmente?

Sobre los flujos por ejemplo esta frase aparece en el libro de Deitel 5:

"La clase FileOutputStream proporciona métodos para escribir arreglos byte y objetos byte individuales en un archivo. Para este programa escribiremos objetos en un archivo; esta capacidad no la proporciona FileOutputStream. Por esta razón envolvemos un objeto FileOutputStream en un objeto ObjectOutputStream, pasando el nuevo objeto FileOutputStream al constructor de ObjectOutputStream."

Podria interpretar que la clase ObjectOutputStream logra escribir objetos delegandole algun trabajo a FileOutputStream ... sino ¿por qué necesita de FileOutputStream para entregarselo en el constructor?
¿Que hace un objeto envoltura con el objeto que envuelve? ¿se aprovecha de el?

Además

Podria ser que el tipo de la clase del objeto envuelto varie... pero se utilice los métodos declarados en una interfaz que implementen los objetos envueltos para aprovecharlos
entonces si es así si se le estaria sacando provecho a los objetos envueltos de parte de los Wrappers ¿es así?

Creo que puedo dar a entender lo confundido que estoy... o mejor dicho, que no capto bien el concepto. Agradeceria mucho una aclaración.

Saludos.

Imagen de ezamudio

Envoltorios

Hay dos tipos como ya mencionaste. Uno es envolver un tipo primitivo en un objeto, como con las clases Integer, Long, Boolean, etc. que simplemente encapsulan un tipo primitivo.

En cuando a streams, la idea es que tienes streams de bajo nivel (manejan bytes directamente) pero los puedes envolver con otros streams que manejan ya ciertas estructuras de datos. Por ejemplo el DataOutputStream, que envuelve un OutputStream para que puedas escribir tipos primitivos de Java, o un ZipOutputStream para que te comprima los datos que escribes.

Por qué funciona así? Pues porque entonces un ZipOutputStream lo puedes usar para comprimir datos a un archivo, o a un socket, o a una base de datos, etc. Lo mismo con los streams de lectura. Puedes crear un DataInputStream que envuelva un FileInputStream o un InputStream de un socket o de un ResultSet o de donde sea, y leer datos directamente de ahí.

De alguna forma, pues sí, un Stream que envuelve a otro, lo está utilizando para leer o escribir datos directamente de ahí. Y los constructores de estos streams aceptan InputStream o OutputStream para que les pases cualquier otro stream.

Por ejemplo, puedes crear un PrintStream que envuelva un ZipOutputStream que envuelva un ByteArrayOutputStream. Entonces invocas   en el PrintStream y lo que va a hacer es mandar esa cadena, en el encoding definido para la JVM, más un cambio de línea (que puede ser distinto en Mac, Windows, Linux), todo eso lo va a enviar al ZipOutputStream; éste lo que va a hacer con esos datos es comprimirlos y enviarlos al ByteArrayOutputStream, que simplemente los guarda en memoria. Luego puedes revisar el contenido de ese último stream pidiéndole el arreglo de bytes directamente para revisarlo.
Para leerlo, puedes crear un ByteArrayInputStream con el mismo arreglo de bytes, envolverlo en un ZipInputStream y eso a su vez en un InputStreamReader y luego en un LineNumberReader; al invocar   en el LineNumberReader, va a empezar a tomar datos del InputStreamReader hasta encontrar un cambio de línea; el InputStreamReader va a tomar datos del ZipInputStream, que los va a ir leyendo del ByteArrayInputStream y los va a ir descomprimiendo (porque el ZipInputStream espera leer datos comprimidos). Al final vas a obtener la cadena "estamos probando streams" con un cambio de linea.

Luego puedes modificar el código para que al final en vez de ByteArrayOutputStream tengas un FileOutputStream que al final cierres y por otra parte usar un FileInputStream en vez del ByteArrayInputStream; el resto del código no cambia. Lo mismo si decides abrir un Socket para comunicar dos procesos y escribir a través de sus InputStream y OutputStreams; el demás código no cambia.