public static void main(String[] args) throws IOException {
int ch;
while ((ch = System.in.read()) != -1)
System.out.print((char) ch);
} public static void main(String[] args) throws IOException {
int ch;
while ((ch = System.in.read()) != -1)
System.out.print((char) ch);
}I was so wrong.
Three things wrong. The first is pedantic: you need to import IOException. The second though is one of those "scream out loud at the universe* questions: why the heck are you calling print() instead of write()?
Finally, do you think maybe you might need to worry about buffering of System.out's stream?
> you need to import IOException
try {
...
} catch(Exception ex){ ... }
;-)Edit: Or if you want to be just as pedantic, and not write an obnoxious catch-all
try {
...
} catch (java.io.IOException ex) { ... }As to why you'd want to use a catch, I think it's kind of sloppy to let the user see an uncaught exception. You might as well just do
public static void main(String args[]){
try {
...
} catch (Exception e) {
System.out.println("This is horrible software, and you shouldn't use it.");
}
}
... as that's what many users already see when exception goes uncaught.This is bad code as he said.
You're conflating two things. I could just as easily have caught Throwable or Exception and not needed the import. The question is: what would you actually put in the handler that would be so much better? The actually provided sample code is much worse, as it prints to System.out instead of System.err, and it doesn't report an error to the parent process, so you muddy up the output (imagine if the file you were copying actually ended in "This is horrible software, and you shouldn't use it.", how would you even know) and there is not a terribly easy way to detect an error happened.
> This is bad code as he said.
It's not bad code to declare a static exception as escaping your method, particularly if you don't have any logic for handling it. It's bad code to have an exception handler that doesn't.
There are some, but they aren't the ones people usually think of when they say, "I'd always use X instead of Java".
So, for example, if you are in Python3, sys.in and sys.out are by default in text mode, which is not going to end well for anyone.
It's a trivial test, so I'll give you trivial input and not have you worry about "what if someone gives me random bytes".
The test isn't to demonstrate you know off the top of your head how to deal with an edge case. But if it were and I were allowed to pick my language, I'd pick bash and just write
catThe only edge case is knowing you need to flush the output, which is relevant whether you send ASCII text or not. The other edge cases around ASCII are just whether you use the correct API's or not.
print() won't flush to the console unless you pass '\n' and auto-flushing is on. It will flush its internal buffer, but that's okay! The default System.out uses a BufferedOutputStream anyway:
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
...
new PrintStream(new BufferedOutputStream(fdOut, 128), true)
So using print() instead of write() shouldn't cause any extra system calls, although there many be a small CPU cost.Obvious, right? Don't you love java.io? :)
Yes, which is the _problem_, not the _solution_.
To clarify: the problem isn't that the code makes too many syscalls.
public static void main(String[] args) throws IOException {
byte[] buffer = new byte[1 << 12];
for (;;) {
int nRead = System.in.read(buffer);
if (nRead == -1) return;
System.out.write(buffer, 0, nRead);
}
}
If so, fair enough, but it's reasonable to go with the simpler solution if you're not given any particular performance requirements.Try doing this:
dd if=/dev/random of=test_file bs=4000 count=100
java YourClass < test_file > test_output
diff test_file test_outputIn python, this seems to work: import sys sys.stdout.write(sys.stdin.read())
What is being abstracted away/handled by python that I'm not seeing?
Except no. Then you run in to problems with a binary file that might not have a line break.
#include <iostream>
int main ()
{
std::cout << std::cin.rdbuf();
return 0;
}while (<>){ print };
perl -pe ""This is valid JDK 1 code. You only need to read the Javadoc for InputStream and PrintWriter. I think the author needs to check his biases.
Now Javascript... (just kidding).
Okay, that kind of points to the problem. You don't see anything wrong with that code beyond the casting (and avoiding casting is the wrong reason to read in to a byte[].. which opens up some additional complexity too).
So my ideal impl in java would be:
public class F {
public static void main(String [] args) throws Exception {
byte[] buf = new byte[256];
int len = -1;
while ( (len = System.in.read(buf)) != -1) {
System.out.write(buf, 0, len);
}
System.out.flush();
}
}
In python #!/usr/bin/env python -u
import sys
while True:
buf = sys.stdin.read(256)
if buf:
sys.stdout.write(buf)
else:
break
Which both feel roughly the same. Although I kind of wish python would let me assign within the expression - just in this case. The similarity boils down to the fact that they're sitting on top of posix read and write calls. There's not much variation you can get from that.The differences get down to fd stream flushing. Python we enable unbuffered io with -u, java we must flush. In C++ we can count on all FDs being flushed in atexit.
You certainly can muck this problem up for binary files and different charsets if you're not careful. But the OP's solution still works in many cases. A fine first answer. Any time a candidate writes code for you during an interview, the first answer will most likely have issues (stress, trying to finish quickly to impress, etc). I care very little about that stuff if there answer is roughly functional. After they have their first stab out, then you go thru the 'why did you do it this way?' 'what corner cases might you be concerned about?' and so on. The answers to those questions will let you make a good estimate of their knowledge and competence.
And to be clear... the correct answer is that in Java it basically buys you nothing but some extra overhead initializing an array and in Python it merely saves you trips through the repl loop. Either way the choice of 256 bytes is arbitrary.
on my junky MBP running java 6 -
read(byte[]) & write(byte[], int, int):
real 0m6.588s
user 0m0.876s
sys 0m1.406s
vs. read() & write(int) real 0m16.836s
user 0m10.624s
sys 0m4.245s
vs the mighty cat - < in > out: real 0m4.609s
user 0m0.015s
sys 0m0.458s
For a 150 mb file.I'd say read(byte[]) / write(byte[], int, int) performed pretty well.
Now some points.
System.in is an InputStream, System.out is a PrintStream. Assuming anything more about their buffering nature is wrong. AFIAK there is nothing in the java spec that spells out any other explicit behaviour. So if you want to ensure your code works properly, code against the interfaces you're given, not the implementations you expect are sitting behind them.
This question (and stdin/stdout/stderr questions in general) are heavily biased in favour of devs comfortable of working in a Unix-y environment. If you're fine with short changing people that use that other OS that's cool. But if you want a 'trivial' demonstration of programming skill - a FizzBuzz type of question is much less biased way of achieving that.
> So if you want to ensure your code works properly, code against the interfaces you're given, not the implementations you expect are sitting behind them.
A test which the original code, and your initial review, failed on multiple fronts (failed to handle character encoding issues and failed to flush the output stream before exiting).
> This question (and stdin/stdout/stderr questions in general) are heavily biased in favour of devs comfortable of working in a Unix-y environment.
I honestly find it hard to believe that Java devs would have their skills sets be terribly different regardless of platform they run on, and I really would think people would learn the basics of working with streams regardless of the platform they work with, but I grok the gist of what you are saying.
> But if you want a 'trivial' demonstration of programming skill - a FizzBuzz type of question is much less biased way of achieving that.
FizzBuzz doesn't really test for knowledge of the language's libraries though. I always thought the purpose of these tests was more to validate that the programmer had successfully coded in the past, rather than any demonstration of skill.
150000000 iterations of a loop would warm the coldest JIT. JIT speeds up bytecode execution - but if you trace the execution of this code you'll see we often end up crossing between JVM land and native land via JNI to push output to write(2) or pull input from read(2). Crossing the JNI boundary is not free and cannot be optimized with JIT (there's lots of data copying back and forth - maybe some memory pinning etc). Using explicit buffers, you pay this overhead less often. Increasing the buffer size reduces the overhead - but of course with diminishing returns. Using read()/write(int) you pay this penalty more frequently. In general it's almost always a bad idea to use single element methods when the interface also exposes bulk methods and you want to do bulk work.
> A test which the original code, and your initial review, failed on multiple fronts (failed to handle character encoding issues and failed to flush the output stream before exiting).
Mea culpa - OP & I had similar idea and a quick scan of the code seemed generally correct. If I was interviewing him / her I would spend more than a second reading the provided code.
> I honestly find it hard to believe that Java devs would have their skills sets be terribly different regardless of platform they run on, and I really would think people would learn the basics of working with streams regardless of the platform they work with, but I grok the gist of what you are saying.
I'd still argue that stdin/stdout/stderr are instances of IO streams. I'd hope all programmers are relatively confident with manipulating IO streams. But these particular instances are really familiar to people working in Unix and uncommon to Windows people. I'd rather have the candidate thinking about streams and not fumbling in the back of their mind kind of remembering what stdout is.
> FizzBuzz doesn't really test for knowledge of the language's libraries though.
Granted - but I think this thread illustrates that there are a ton of other aspects besides standard library knowledge in play when you dig into this question. If you want to know if the person sitting in front of you can program, FizzBuzz. If you want to know if they grasp the language's standard libraries - ask them a question that requires using collections. If you want to see if they understand the platform their running on do something with File IO.... and so on.
So, if I reframed the question as "copy the contents of one file to another" and asked them to write a class that implements:
public void copy(java.io.InputStream in, java.io.PrintStream out);
Would that change the solution?Ya think!?
Scanner sc = new Scanner(System.in);
String line;
while((line=sc.readLine())!=null)
System.out.println(line);
}What's so verbose about it?
It's amazing though how often the solutions posted are just wrong.