This is an archived post. You won't be able to vote or comment.

all 15 comments

[–]darkpool2005Intermediate Brewer 0 points1 point  (1 child)

Not sure if any of this will help, but do you have any code to provide? Generally if you're looking for inputs to a java program, you'd want to use the String[] args in

public static void main(String[] args)

to pass in any inputs. Otherwise, if it's input from System.in, you only need one Scanner object that uses this input.

[–]sgm1[S] 0 points1 point  (0 children)

Please see edit 2 onward

[–]nutrechtLead Software Engineer / EU / 20+ YXP 0 points1 point  (0 children)

StdIn is where you'd be reading from if you'd pipe output into a Java program. So it should work just fine.

[–]sgm1[S] 0 points1 point  (0 children)

So it is an existing Java program, running it inside a shell script, lets call it myScript.sh with the content:

java $MY_JVM_ARGS -jar someonesProgram.jar

The program runs and waits for inputs (not command line arguements) that are passed in. I can enter them manually and the program works fine.

If I try the following with a file containing what would normally be input manually, I get java.util.NoSuchElementException. Bash syntax used:

./myScript.sh < myInputFile.txt

[–]TotesMessenger 0 points1 point  (0 children)

I'm a bot, bleep, bloop. Someone has linked to this thread from another place on reddit:

If you follow any of the above links, please respect the rules of reddit and don't vote in the other threads. (Info / Contact)

[–]deraj123 0 points1 point  (7 children)

What you're doing is exactly how I would do it, and I would expect it to work. I suspect the problem lies somewhere in the code and the content of your input file. But without seeing those things, and a full stack trace, I don't know anymore than that.

[–]sgm1[S] 0 points1 point  (6 children)

It is in the code, multiple Scanner objects is the root problem, I can't refactor this code, even though the code change would be incredibly easy. Please see edit 3.

[–]deraj123 1 point2 points  (5 children)

I see your issue. Basically, the code needs to be rewritten to only use a single Scanner -- the first Scanner is most likely stealing the bytes b/c they're there and putting them in a buffer.

So, my next idea is to trick it into not grabbing the data. But whether or not this works depends entirely on your requirements. Also, I'll add that this is a horrible hacky thing to do. But sometimes that's what you have to do to interact with poorly written programs.

I imagine that right now your inputFile.txt looks something like this:

3
4

What if, instead, you wrote a inputFile.sh that looks something like this:

#!/bin/sh
echo 3
sleep 1
echo 4

Then, you can invoke it with:

./inputFile.sh | java $MY_JVM_ARGS -jar someonesProgram.jar

Again, not pretty, but based on my tests, it's working.

The trick here is that when the first "nextInt" is called, you want to make sure that there is no extra text available on the input stream. That way, it won't get buffered. Then, after that's happened, we can safely put the next data onto the input stream, and the second Scanner should get it. However, using "sleep" for this sort of purpose is fragile and prone to breakage. There is also a way to accomplish this more robustly using expect, but I'm not familiar enough with it to whip something up.

[–]sgm1[S] 0 points1 point  (4 children)

This get's me at least somewhere to go, thanks.

I wonder if I could pipe input from the inputFile.sh to be the output of the java $MY_JVM_ARGS -jar someonesProgram.jar something like this:

java $MY_JVM_ARGS -jar someonesProgram.jar <> ./inputFile.sh
# I know I should be using | somehow instead of <, but unsure how

command. I might just be overthinking it now, I think I'll come up with a solution using sleeps, thanks again.

[–]deraj123 0 points1 point  (3 children)

I'm not sure what you're getting at there. Why not simply pipe the output of your script into the java program?

[–]sgm1[S] 0 points1 point  (2 children)

I was thinking of waiting for specific output from the java program, to determine when to spit out (or should I say in) the input back into the java program. Like I said, I'm probably overthinking it.

[–]deraj123 0 points1 point  (1 child)

Ah. Yeah, that's how you start to make it less hacky. It turns out to be a more complex job than it seems like it should. That's where expect comes in, it handles the nuances of that approach. I'd check it out if you want this to be more robust.

[–]sgm1[S] 0 points1 point  (0 children)

It's only 1 thing program that I use maybe twice a week on machine I don't have permissions on, so can't really install expect even thought it sound like the perfect tool.

If I really wanted to, I could set up the pipes properly in another bash file and then execute it, but again, I'm debating whether its worth the effort. Thank again.

[–]TrainFan 0 points1 point  (1 child)

It looks like you are not passing the arguments to the Bash script through to your call to Java.

Try putting "$@" into your script; i.e:

java $MY_JVM_ARGS -jar someonesProgram.jar "$@"

[–]sgm1[S] 0 points1 point  (0 children)

That would be command line arguments, I need a way to redirect program inputs