Win a copy of Learning Regular Expressions this week in the General Computing forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Liutauras Vilda
  • Campbell Ritchie
  • Tim Cooke
  • Bear Bibeault
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Knute Snortum
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Ganesh Patekar
  • Stephan van Hulst
  • Pete Letkeman
  • Carey Brown
Bartenders:
  • Tim Holloway
  • Ron McLeod
  • Vijitha Kumara

FYI: wrapper class for Scanner(System.in)  RSS feed

 
Saloon Keeper
Posts: 4801
52
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is a bad programming practice of creating a new Scanner object with System.in in every place you need to get some keyboard input. The correct way is to only ever create one new Scanner(System.in) object and pass it around or make it static.

Here is a utility class for doing this, wrapping the common Scanner methods with a private static Scanner object:

Including this class in your project then allows you to make calls like this:
 
Rancher
Posts: 2842
96
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nice Wrapper!

To all those unfortunates who did close System.in and who use an IDE: just rerun your program and all is fine again.

@Carey: I've seen you using quite some Patterns lately. Time to change your sig a little?    
 
Sheriff
Posts: 5136
138
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perhaps this wasn't your concern, but this doesn't address the nextLine() after nextInt() problem.
 
Marshal
Posts: 60199
188
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are still risking an input mismatch exception. A long time ago, Rob Spoor taught me how you can avoid that exception altogether, with a loop:-That code won't throw an input mismatch exception.
You also would want a private constructor because that utility class shou‍ld never be instantiated. You can enhance those methods to return only values in a specified range. Other mehods can be written similarly. For nextBoolean(), you will get true from any input matching “true”, but case‑insensitive, but if you write anything else, 1234567890 or Carey (I think) it will interpret that as meaning false.
 
Carey Brown
Saloon Keeper
Posts: 4801
52
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Knute Snortum wrote:Perhaps this wasn't your concern, but this doesn't address the nextLine() after nextInt() problem.


I thought about that. My approach was to keep the logic as close as possible to a programs direct use of Scanner, which would include the warts.
 
Carey Brown
Saloon Keeper
Posts: 4801
52
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:You are still risking an input mismatch exception. A long time ago, Rob Spoor taught me how you can avoid that exception altogether, with a loop:-That code won't throw an input mismatch exception.
You also would want a private constructor because that utility class shou‍ld never be instantiated. You can enhance those methods to return only values in a specified range. Other mehods can be written similarly. For nextBoolean(), you will get true from any input matching “true”, but case‑insensitive, but if you write anything else, 1234567890 or Carey (I think) it will interpret that as meaning false.


Absolutely I need a private constructor. Good catch.

Good suggestion for a more robust method. I'll have to think about it a bit. My original thinking was to keep it as close to direct use of a Scanner object as possible. But this might make a lot of programs behave better.
 
Knute Snortum
Sheriff
Posts: 5136
138
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:You also would want a private constructor because that utility class shou‍ld never be instantiated.


What about a multiuser system?  Wouldn't having only one Scanner mean that users could clobber each other's buffers?
 
Knute Snortum
Sheriff
Posts: 5136
138
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Anyone interested in how I dealt with this problem can look at:

https://github.com/ksnortum/Inputer
 
Marshal
Posts: 6015
415
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Knute Snortum wrote:Perhaps this wasn't your concern, but this doesn't address the nextLine() after nextInt() problem.


And that part could be handled using this method, nope? I think almost always this works, either you had nextInt() before or you didn't.
 
Carey Brown
Saloon Keeper
Posts: 4801
52
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Updated with private constructor.
 
Campbell Ritchie
Marshal
Posts: 60199
188
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Knute Snortum wrote:. . . What about a multiuser system? . . .

You would have one Scanner object per JVM, not one Scanner object per computer, but I don't know more about multiuser systems.
As I said, my version isn't thread‑safe, but it could be made thread‑safe.

It was Rob Spoor who taught me about that loop. I preferred to maintain the default delimiter, and would use a second Scanner object if it is ever necessary to use a different delimiter. Yes, nextInt() + nextLine() would work, but there is a subtle difference:-
  • 1: Passing "Sheriff: Campbell Ritchie" to next() followed by nextLine() returns "Sheriff:" and "Campbell Ritchie"
  • 2: Passing "Sheriff: Campbell Ritchie" to next() + nextLine() returns "Sheriff:Campbell Ritchie"
  • 3: Passing "Sheriff: Campbell Ritchie" to nextLine() returns "Sheriff: Campbell Ritchie"
  • I like Knute's validation which shows the input to the user and allows them to say whether it is correct . I have validation for ranges of numbers but never thought to use validation for names like that.
     
    Sheriff
    Posts: 12357
    201
    Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Are multiple users and concurrency around standard input really a concern when it comes to this kind of thing? I can't think of any reason it would be. What am I missing?
     
    Campbell Ritchie
    Marshal
    Posts: 60199
    188
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I can imagine scenarios where threading would be a problem, e.g. if you are reading similar input from multiple threads. I can't see that multiple users would be an issue unless they are trying to use the same terminal/command line.
     
    Knute Snortum
    Sheriff
    Posts: 5136
    138
    Chrome Eclipse IDE Java Postgres Database VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Junilu Lacar wrote:Are multiple users and concurrency around standard input really a concern when it comes to this kind of thing? I can't think of any reason it would be. What am I missing?


    Probably nothing.  I keep forgetting that each user will have their own JVM.  I might change my Inputer class based on this.
     
    Consider Paul's rocket mass heater.
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!