I'm writing a program that basically acts as an email client as a part of a homework assignment for a class in java. I don't normally resort to the internet to answer my questions, but this is something that goes beyond what the professor is trying to get us to learn/practice, and I need to find a way to fix it.
The Problem: If I run the program, and input the second command (ri), it will prompt me for the number, and then finish by displaying the message, but immediately after, when it goes back into the second iteration of the .run() method the console returns:
Exception in thread "main" java.util.NoSuchElementException: No Line Found
at java.util.scanner.nextLine(Unknown Source)
Here's the code (I'm only including the important stuff...or at least what I think is important).
public class CmdLoop {
private MailClient _client;
Scanner kbd;
private Hashtable<String, ICommand> _commands = new Hashtable<String, ICommand>();
public CmdLoop(MailClient client) {
_client = client;
_commands.put("h", new client.cmd.Help());
_commands.put("ri", new client.cmd.ReadInbox());
kbd = new Scanner(System.in);
}
public void run2() {
System.out.print("\nMail: ");
String command = kbd.nextLine();
ICommand call = _commands.get(command);
if (command.equals("q"))
return;
else if (call == null)
System.out.println(command + " not understood, type h for help");
else if (call.equals(""))
System.out.println(command + " not understood, type h for help");
else call.run(_client);
this.run2();
}
and the ri class:
public class ReadInbox implements ICommand {
#Override
public void run(MailClient client) {
Scanner sc = new Scanner(System.in);
MailBox in = client.getInbox();
if(in.count() < 1)
System.out.println("Inbox empty");
else {
System.out.print("Enter the number of the message you would like to read: ");
int n = Integer.parseInt(sc.nextLine());
if(n > in.count())
System.out.println("Message number " + n + " can't be found");
else
in.getMessage(n - 1).show();
}
sc.close();
}
}
Basically it gets to the end of the ReadInbox.run() call, then it calls this.run2(), returns to the top, outputs "Mail: " and then returns the error. This is what the console looks like in my test:
Mail: ri
Enter the number of the message you would like to read: 1
Date: 2015/04/29 20:24:17
From: Charles Barkley (Charlie) <Charles#gmail.com>
Subj: testerino
this is another test
Mail: Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at client.CmdLoop.run2(CmdLoop.java:28)
at client.CmdLoop.run2(CmdLoop.java:37)
at Main.main(Main.java:29)
If I'm correct, getting it so they both operate off the same scanner would solve my problem, and I feel like I should know how to do that, but I'm drawing a blank. Is there another way as well?
According to the documentation a Scanner will throw that exception "if no line was found". You can prevent that by first calling kbd.hasNextLine() which will tell you if there is something to get. That will wait for a line to be entered as long as the scanner is not closed.
Try this in your run2 method:
String command = null;
if (kbd.hasNextLine())
command = kbd.nextLine();
ICommand call = _commands.get(command);
I found the answer. I got rid of sc.close(); in the ReadInbox class. I have 0 clue why this works, but it does. If anyone has an explanation to offer, much appreciated, otherwise, whatever, at least it works.
Related
So I've built this bot that should respond to it's user with status messages. I want to make these messages rather clean and therefore wanted to start each new property with a new line. Only problem is that when I do this, the bot just prints the first few lines.
So this is the code I've got, I've made sure that the data is actually there.
internal static string DeviceInformation(Device device)
{
StringBuilder sb = new StringBuilder();
sb.Append($"[Name]: {device.Name}\n\n");
sb.Append($"[Location]: {device.LocationName} \n\n");
if (device.ContactLost)
{
sb.Append("[Status]:Offline!\n\n");
sb.Append($"[Time Offline]: {device.ContactLostTime} \n\n");
sb.Append($"[Time Offline]: {device.ContactLostTime} \n\n");
}
else
{
sb.Append("[Status]:online! \n\n");
}
return sb.ToString();
}
internal static string DeviceInformation(Device device, DeviceHistory statistic)
{
StringBuilder sb = new StringBuilder(DeviceInformation(device));
sb.Append($"[Time]: {statistic.CreatedTimeStamp} \n\n");
sb.Append($"[Signal]: {statistic.SignalStrength} \n\n");
sb.Append($"[Battery]: {statistic.BatteryLevel} \n\n");
Debug.WriteLine("TOSTRING " + sb.ToString());
return sb.ToString();
}
The next last line prints out this:
TOSTRING [Name]: Restroom 1
[Location]: Floor 2
[Status]:online!
[Time]: 16/05/2017 22:23:45
[Signal]: -88
[Battery]: 60
Now the bot just prints:
[Name]: Restroom 1
[Location]: Floor 2
[Time]: 16/05/2017 22:23:45
If I remove all the linebreaks \n and put everything on the same row, the bot prints the whole message.
Anyone having any idea what I can do about this?
Interesting behavior. I was able to reproduce it... I'm still looking for the root cause of the issue, however, I found a workaround for you, that is using bullets.
I updated your code in the following way:
internal static string DeviceInformation(Device device)
{
StringBuilder sb = new StringBuilder();
sb.Append($"• [Name]: {device.Name}\n\n");
sb.Append($"• [Location]: {device.LocationName}\n\n");
if (device.ContactLost)
{
sb.Append("[Status]:Offline!\n\n");
sb.Append($"[Time Offline]: {device.ContactLostTime}\n\n");
sb.Append($"[Time Offline]: {device.ContactLostTime}\n\n");
}
else
{
sb.Append("• [Status]:online!\n\n");
}
return sb.ToString();
}
internal static string DeviceInformation(Device device, DeviceHistory statistic)
{
StringBuilder sb = new StringBuilder(DeviceInformation(device));
sb.Append($"• [Time]: {statistic.CreatedTimeStamp}\n\n");
sb.Append($"• [Signal]: {statistic.SignalStrength}\n\n");
sb.Append($"• [Battery]: {statistic.BatteryLevel}\n\n");
Debug.WriteLine("TOSTRING " + sb.ToString());
return sb.ToString();
}
With that, it's working as expected in the emulator:
(In case you're interested, the background for this question is here, but I don't think it's critical for this particular question.)
We're trying to run a series of report exports (a third party method call) one at a time in separate threads, so we can kill off the thread if it takes too long. The ugly, but best-so-far, idea is to use Thread.Abort to kill the thread exporting a given report, then do a ResetAbort to allow the rest of the code to continue.
The proof of concept code looks like this:
public RunningMethod()
{
Report myReport = new Report();
for (int i = 0; i < 10; i++)
{
Thread reportThread = new Thread(() => DoBackgroundJob(myReport, "test" + i.ToString()));
reportThread.Start();
bool finished = reportThread.Join(TimeSpan.FromMilliseconds(100));
if (!finished)
{
reportThread.Abort();
}
}
}
protected void DoBackgroundJob(Report myReport, string reportFilename)
{
try
{
report.ExportToPdf(#"C:\" + reportFilename + ".pdf");
}
catch (ThreadAbortException)
{
}
break;
}
I'm getting a strange result when I run this...the Export line seems to throw an exception that seems like it should be a ThreadAbortException, but apparently is not, since it doesn't get caught by the catch (ThreadAbortException), but is caught by a catch (Exception).
I'd like to know what kind of exception I'm getting, but I can't see it because when I try to view it I only get "Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack."
Is there a way to determine what is happening? What exception is really being thrown here?
Over the last two weeks I have studied 10 different ways to avoid problems with sleep(). The concept of running a block of code on the UI Thread that cannot be interrupted seems the most practical. So I have proceeded to create a FutureTask<Void> object that contains the code not to be interrupted before completed. The code in for loops, pixelArray[r][c].setFill(color) sets the new colors for Circle Objects in a Grid Array that's 32x64. This has always failed to display the colors when just sleep(5000) is invoked between the pixel art files, FileChooser selects and assigns to List<File> selectedFiles. Unfortunately the following code will not compile because runLater in the linePlatform.runLater(diplayFileTask); can't be resolved in the following code:
public class PlayPlaylist{
public static List<File> selectedFiles;
public static void play() throws ExecutionException {
FileChooser fileChooser = new FileChooser();
fileChooser.setInitialDirectory(new File("C:\\ProgramData\\L1 Art Files\\"));
fileChooser.setTitle("Play One or More Pixel Art Files");
List<File> selectedFiles = fileChooser.showOpenMultipleDialog(null);
for (File selectedFile : selectedFiles) {
try {
displayFile(selectedFile.getPath());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
public static void displayFile( String pathName) throws IOException, InterruptedException, ExecutionException {
FutureTask<Void> displayFileTask = new FutureTask<>(new Runnable() {
#Override
public void run() {
path = Paths.get(pathName);
try {
pixelByteArray = Files.readAllBytes(path);
} catch (IOException e) {
e.printStackTrace();
}
int cnt = 0;
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
//int i = r * col + c;
//System.out.println("\nr = " + r + " c = " + c);
String hexRGB = String.format("#%02X%02X%02X",
pixelByteArray[cnt++], //red
pixelByteArray[cnt++], //green
pixelByteArray[cnt++]); //blue
Color color = Color.valueOf(hexRGB);
//System.out.println("\ncolor is " + color);
pixelArray[r][c].setFill(color);
}
}
String fileName = path.getFileName().toString();
window.setTitle(MessageFormat.format("Pixel Array {0} x {1} File: {2}", Integer.toString(row), Integer.toString(col), fileName));
}
}, null); // displayFile
Platform.runLater(displayFileTask);
displayFileTask.get();
sleep(5000);
}
I've followed the example(s) closely in Stack Overflow and fail to see the problem(s).
I have more details on past attempts posted on Stack Overflow at: Wait() & Sleep() Not Working As Thought.
I also have the two UI windows posted on the web at: Virtual Art. I think the pixel art shown in the Pixel Array window clarifies the goal of creating a user-defined slide show.
Can anyone correct my errors? Do you think my sleep(5000) is in the best location?
Answering James_D's questions. This is my best solution to your answer at my first post, Wait() & Sleep() Not Working As Thought. I was actually following your logic and code posted at, java thread immediately update UI.
I save and display pixel art files that are 32x64. You can see an example posted on the Virtual Art website. I thought it would be straight forward to create a slide show under Playlist, click Play. I would use the same class and OpenFile(pathname) method in a for loop to display each file selected and placed in the ArrayList<> but pause by putting Thread.sleep(5000) in the loop.
As you pointed out, this doesn't work, as I best understand, because the Thread.sleep(5000) interrupts the UI Thread causing a "skip" over of just the display code of all the files looped through. But last pixel art file will appear after 5 secs.
I thought your answer in the post referenced above applied: You create a block of code using FutureTask<Void> and Platform.runLater<task> that can't be interrupted until completed. I thought the FutureTask<Void> runs on the UI Thread and would finish displaying the pixel art file before Thread.sleep(5000) could interrupt.
At 68 and retired, I'm new to JavaFX and trying to develop this RGB LED product that can be programmed with a basic pixel editor. Learning JavaFX is a real challenge for me, thanks for your time and patience.
I'm doing this for a class, and I'm really not terribly awesome at this as I'm over a decade out of practice. I'm trying to write a program that displays a menu so the user can choose between methods of determining if it's a palindrome.
It then needs to redisplay the menu once it has completed the test. I'm getting a stack overflow error in the isPalindrome method since I combined the 2 classes into one class, which I thought would fix another problem I was having with the output! Any thoughts or directions I can take?
import java.util.Scanner;
public class PalHelper
{
public String pal;
public void MenuList()
{
System.out.println("How would you like to check your phrase?");
System.out.println("1. Check the first letter like it's the last letter - Leave no phrase unturned!");
System.out.println("2. I Prefer my Palindromes have the gentle treatment");
System.out.println("3. We're done here");
System.out.print("Selection: ");
}
public PalHelper()
{
Scanner decision = new Scanner(System.in);
MenuList();
switch (decision.nextInt())
{
//to access the character by character method of determination
case 1:
System.out.print("Enter Phrase to Test, the Hard Way:");
Scanner keyboard1 = new Scanner(System.in); //declares scanner variable for user entry
String UserInput1 = keyboard1.next();//Phrase variable
Boolean test1 = isPalindrome(UserInput1);
if (test1 == true){
System.out.println(UserInput1+" is a palindrome. That doesn't make you smart.");
}
else {
System.out.println(UserInput1+" is a not palindrome. Why don't you think a little harder and try again.");
}
System.out.println("..\n..\n..\n");
keyboard1.close();
new MenuList();
break;
//to access the string buffer method of determination
case 2:
System.out.print("Thank you for choosing the gentle way, please enter your phrase:");
Scanner keyboard2 = new Scanner(System.in); //declares scanner variable for user entry
String UserInput2 = keyboard2.next();
Boolean test2 = isPalindrome2(UserInput2);
if (test2 == true){
System.out.println(UserInput2+" is a palindrome. Congratulations! You are so wonderful!");
}
else {
System.out.println(UserInput2+" is a not palindrome. It's ok, I'm sure you'll get it next time.");
}
System.out.println("..\n..\n..\n");
keyboard2.close();
new MenuList();
break;
//exit menu
case 3:
System.out.println ( "Too bad – I hid a boot!" );
break;
//response to input other than 1,2,3
default:
System.out.println ( "No sir! Away! A papaya war is on." );
System.out.println("..\n..\n..\n");
new MenuList();
break;
}// close switch
}//close pal helper
public void Palindrome(String UserInput) {
}
public boolean isPalindrome(String UserInput) {
pal = UserInput.toUpperCase();
if (pal.length() <= 1) {//one character, automatically a palindrome
return true;
}
char start = pal.charAt(0);
char end = pal.charAt(pal.length()-1);
if (Character.isLetter(start) &&
Character.isLetter(end)) {//check if first and last characters match
if (start != end) {
return false; //if the beginning & ending characters are not the same it's not a palindrome
}
else {
Palindrome subpal = new Palindrome(pal.substring(1,pal.length()-1));
return subpal.isPalindrome(); //check middle dropping start and end letters
}
}
else if (!Character.isLetter(start)) {
Palindrome subpal = new Palindrome(pal.substring(1));
return subpal.isPalindrome(pal); //check if first letter is a letter, drop if not
}
else {
Palindrome subpal = new Palindrome(pal.substring(0,pal.length()-1));
return subpal.isPalindrome(pal); //check if first letter is a letter, drop if not
}
}//close isPalindrome
public boolean isPalindrome2(String UserInput){
pal = UserInput.toUpperCase();
pal = pal.replaceAll("\\W", "");//gets rid of space and punctuation
StringBuffer check = new StringBuffer(pal);//reverses pal string and creates new stringbuffer for check
check.reverse();
if (check.toString().equals(pal)){//checks for equality between pal and it's reverse
return true;
}
else {
return false;
}
}//close isPalindrome2
public static void main (String[]args)
{
new PalHelper();
}//close main
}//close class
Aside from my comment above, there is a problem that I noticed: in some cases, you construct a new Palindrome instance with the substring, but pass the full string while recursing to the isPalindrome() method. This causes the recursion to never terminate (which also makes your code hard to follow).
Your example is missing something, the following line has missing closing brackets:
Palindrome subpal = new Palindrome(pal.substring(1,pal.length()-1);
Your comments dont seem to match the code:
return subpal.isPalindrome(pal); //check if first letter is a letter, drop if not
Try adding Output to the Method isPalindrome() or debug it. You are probably not calling it with the right Strings and end up looping over the same Strings over and over.
public boolean isPalindrome(String UserInput) {
System.out.println(UserInput);
...
Edit: If your code really is exaclty like you posted then vhallac is right, you call isPalindrome() with the full String.
I have this problem converting object into string... I make use of the toString() function... and since the conversion of object into string were inside the try{}catch(exception e){}, i keep on receiving an output error: For input string: ""
What should be the problem if i keep on receiving an error message like that?
More elaboration:
the Object came from a jComboBox
which consists of items from a
database.
I am using a JFrame Form instead of
a Java Class.
All i want to do is to capture the selected Item from the JComboBox which happens to be an object. And then after capturing it. I'll use the value for my query in the database.
Here's my code(partial):
private void SUBMITActionPerformed(java.awt.event.ActionEvent evt) {
try {
Class.forName(Connect.DRIVER);
Connection con = DriverManager.getConnection(Connect.CONNECTION_STRING,
Connect.USERNAME, Connect.PASSWORD);
Object obj = jComboBox1.getSelectedItem();
String item_name = obj.toString();
int month = jMonthChooser.getMonth();
int q_box = Integer.parseInt(quantity_box_txtbox.getText());
double unit_price_box = 0;
int q_pc = Integer.parseInt(quantity_pc_txtbox.getText());
double unit_price_pc = 0;
double sub_total_box = 0;
double sub_total_pc = 0;
double grand_total = 0;
//Testing
System.out.println(jMonthChooser.getMonth());
System.out.println(item_name);
} catch (Exception e) {
System.out.println("Error: "+e.getMessage());
}
}
If you have anything you don't understand regarding with the way I explain my question please tell me... i'll try my best to elaborate further.
Thanks in advance.
:)
here's the complete error:
Error: java.lang.NumberFormatException : For input string: ""
Well, to start with:
Don't catch just Exception; catch specific subclasses
Don't just catch the exception; you almost certainly want to propagate it up to the caller
Don't log just the message - log the whole exception, including the stack trace and exception type.
The exception looks like it's trying to parse a string - not trying to convert an object to a string. I strongly suspect that the problem is one of these lines:
int q_box = Integer.parseInt(quantity_box_txtbox.getText());
int q_pc = Integer.parseInt(quantity_pc_txtbox.getText());
My guess is that one of the textboxes is empty - so you're effectively calling Integer.parseInt("") which is failing.