Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

So I was a Java developer from 2006-2012. I still occasionally touch Java at work.

Off the top of my head, right now, in this text box, without google, I can't write the code to copy standard input to standard output.

System.out.println(System.in)? That's wrong. You need some kind of InputReader, or BufferedInputReader, or Buffered...something. I think System.in is an InputStream, so presumably I need to do new InputReader(System.in)? Or BufferedInputReader? Should I buffer the output?

Ok, let's do some API googling (ie, not StackOverflow).

So I was... pretty wrong. I think what you want is:

public class CopyInput { public static void main(String[] args) { while (true) System.out.write(System.in.read); } }

I haven't tried to run this though.

In my defence, I have never, in all my years of working, had to ever read standard input, let alone write it out again.



I was about to say the exact same thing: I'd probably walk out of an interview if remembering how to read stdin was part of it, because it comes up maybe once every couple of years in real work, better to just Google it.

Don't tailor from-memory standard library questions to bits of code that almost nobody ever has to use.


I think that is sort of the point of the article though (or at least one of the points...). Dealing with stdin/stdout is not uncommon in itself, though it is probably rare in java. Choosing the right tool for the job is kind of important in most aspects of software, so doing a simple script in say python or a few lines of C or whatever is important - it shows a familiarity with the environment, not just the language(s).

For example:

Whenever I'm dealing with a data processing pipeline I tend to design things as if they would be used from a unix command line. I tell the team to make their classes etc as if they would be wrapped with a simple chunk of code to parse a text stream then serialize to it later. During the course of testing, I almost always will then write those tools to allow simple command line pipes to push test data around. It helps prevent reliance on certain toolsets and certainly helps stop us from conflating bugs in our code with bugs or operator error about a pipeline framework. Later we can go back and more closely integrate with the chosen operating environment, if performance demands it. On the other hand going from a situation where code is written to the environment and migrating to another environment can be very daunting, difficult and error prone.


It depends. If the job is Unix/Linux based then I'd say you definitely should know how to do stdio.


> Don't tailor from-memory standard library questions to bits of code that almost nobody ever has to use.

So seriously? You almost never need to read & write to streams?


No. I almost never need to read from stdin, as I said.

Again, most of us write real apps, not command line utilities.


Yeah, I've spent 10 years as a Java developer and I'd have to think about how to do it in Java. It just isn't a problem Java was designed to fix - sledgehammers, nuts and all that.


Seriously? You've never read from or written to a stream?


I've never copied one stream to another by hand, byte by byte. There's a method in one of the apache commons libraries for that. But most of the time the only reason I'd ever read an input stream is using a CSV parser or a JSON parser or the like, in which case the idiom is usually to just hand the stream to the parser.


> I've never copied one stream to another by hand, byte by byte.

Yeah, but you've probably done a read and write independently. This is just about joining the two together.

> There's a method in one of the apache commons libraries for that.

Yup, and that's great to use that, and you'll no doubt end up with more efficient code most of the time if you do. But... you still should be able to write correct code for reading bytes from one stream, writing to another, without losing data in between.


> you still should be able to write correct code for reading bytes from one stream, writing to another, without losing data in between.

With access to Google and the library documentation sure, but I don't use those APIs often enough to be worth keeping in memory.


> With access to Google

Why the heck would you need Google

> and the library documentation

It's an online quiz.

> sure, but I don't use those APIs often enough to be worth keeping in memory.

You don't worry about it, but it tends to accumulate in one's mind anyway.

Here's the thing though. People are posting solutions on HN... and getting it wrong.


Of course. These days though I don't tend to get much closer than something like Properties.load(InputStream). I really would have had to think about it.

I guess I've been stuck in webapps and NoSQL libraries for a while now.


Where does HN find these guys... It's amazing how many long term "java" developers there are here.


I honestly am at a loss for this. Reading & writing data from a stream without losing any information seems like a pretty basic thing you'd want to know how to do in your chosen programming language.


The reason for this is that if you're doing IO in Java you'll usually use some kind of buffered input reader rather than stdio. I've written a command line in Java that reads commands, runs native commands, streams output to the console and even that doesn't need to read stdio as a stream. It's not that Java can't do that, it's that there are better idioms for most problems.


> The reason for this is that if you're doing IO in Java you'll usually use some kind of buffered input reader rather than stdio.

The methods are the same with a buffered input reader.

> I've written a command line in Java that reads commands, runs native commands, streams output to the console and even that doesn't need to read stdio as a stream.

So, the thing that you are struggling with is how to get to System.in? But no problem doing System.out?

That's not even what the various code samples that have been posted have failed.

> It's not that Java can't do that, it's that there are better idioms for most problems.

Java's actually very good at doing IO efficiently, and as has been demonstrated, the code for this is quite simple. Sure, you wouldn't implement "cat" in Java, but you would read and write to sockets & files with it, which provides all the knowledge one might need to figure out how to solve this. As has been pointed out, the Apache Commons libraries make it so this is a two line program with no branching or looping. That's about as simple as it gets.


I'm not struggling with it at all. I'm an ex C,C++ programmer, i'd do a while not eof read loop.


Which seems pretty amazing to me. Granted I'm not a Java developer, but it seems like such a basic feature of any language.


But how often do you read stdin in Java? It's a language that is used heavily to build web apps and (though less so) desktop GUI apps. I also programmed in Java for nearly a decade in the late nineties till about 2004 and have never used System.in for anything.


I'm writing desktop GUI apps in C# these days. Not the same as Java, but still many people would probably ask the same thing about C# as you've asked about Java: How often would you read stdin in C#? I use it at various prototyping stages of my applications. Oh, I need to handle a new file format. Ok, write the parser and classes to contain the file contents. Then create a quick console app that lets me read in a file and pose questions to it (give me the contents of data block 0x0840, what's its time tag, etc.). Now I need to run analyses on the file, and there's another file format that contains the queries. Create a quick console app that lets me combine those two pieces and a simple text interface to explore it. Then, once the pieces work, I plug them into the GUI. Now, do I do this every week? No, because after a certain point it's all about the GUI and other interactions. But it's a great way (for me) to prototype, and I'd use this approach regardless of the language for most programming tasks.


> But how often do you read stdin in Java?

Doesn't matter. For this problem it is just a conveniently available InputStream. How often do you read from an InputStream? I'd hope the answer to that isn't 0.

> I also programmed in Java for nearly a decade in the late nineties till about 2004 and have never used System.in for anything.

Okay, then change the problem to implementing this interface:

    public interface Copier {
        public void copy(java.io.InputStream in, java.io.PrintStream out);
    }
That doesn't change the problem.


Sure I am familiar with input streams, but we are talking about doing something from memory. One quick Google search leads to an "oh, of course that is what you would do" moment, but I am just noting that even in my Java hey day I would have needed that Google search before writing the requested code.

Your interface does not change the problem, but it does phrase the problem in a more familiar way and would have been much more easy for me to respond to (in my Java hey day that is).


> Sure I am familiar with input streams, but we are talking about doing something from memory.

It's an online quiz. You don't have to do it from memory.


And it IS a basic feature of Java. Just not one that is used much, and therefore not one that has a particularly clear or succinct idiom.

Java didn't grow up in the world of unix where scripts that read from stdin and write to stdout get chained to produce pipelines. It grew up in the world of long-running stand-alone applications that communicate over sockets (like web applications). Java, because of the virtual machine, has a particularly slow start-up time and would be a poor choice for implementing mini pipeline components like this anyway.


It's definitely a basic feature of any language, including Java. I have no idea what the people upthread are talking about. From memory (may not compile) (edit thanks to cbsmith)

import java.io.*;

public static void main(String[] args) {

  byte[] buf = new byte[4096];

  while (true) {
    int numRead = System.in.read(buf);
    if (numRead < 0) {
      // hit EOF, terminate
      System.out.flush();
      System.exit(0);
    }
    System.out.write(buf,0,numRead);
  }
}


just for the lolz, here is another way to do it without a buffer and using some java 8 features (lambdas) to avoid having to wrap the code in a try catch (technically you still are but it looks prettier IMHO):

    public class SimpleJavaTest 
    {
        public interface RunnableEx
        {
            // can't use Callable<Void> because that run method needs to return a value
            public abstract void run() throws Exception;
        }

        public static void main(String[] args) 
        {
            // write standard in to standard out:
            uncheck( () -> {
                int c;
                while( (c = System.in.read()) > -1)
                {
                    System.out.write(c);
                }
            } ).run();
        }

        public static Runnable uncheck(RunnableEx r)
        {
            return () -> {
                try
                {
                    r.run();
                }
                catch(Exception e)
                {
                    throw new RuntimeException(e.getMessage(), e);
                }
            };
        }
    }


> it looks prettier IMHO

... And here's a fine example of Java culture.

2 lines do stuff, everything else is fluff, and it is considered prettier.

BTW: I did not run this specific code, but dropping the buffer is likely to make this code take much, much more CPU (unless HotSpot is much better these days than it was in 2010 when I last used it). That's another pillar of Java culture - care not about performance.

Disclaimer: I didn't test this, and any mention of performance requires testing, rather than reasoning. I don't have a Java compiler handy anymore, or I would test it.


dropping the buffer makes it perform substantially slower - there are some benchmarks listed elsewhere on this thread


I'm a big believer in benchmarking before saying things, but I think we could skip the benchmarks when asking the question "does 1 4096-byte read or 4096 1-byte reads complete faster".


I would agree ... except that I've seen cases in which it didn't make a difference.

e.g. if the File implementation had an internal buffer (C stdio's "FILE " does), and the read from that* buffer was inlined (from my past experience up to date as of early 2011, HotSpot doesn't, but LuaJIT does), it might not make any difference.

Seriously, LuaJIT does things I've never thought I'd see a compiler (JIT or AOT) for any language (dynamic or statically typed) do. I used to reply to "sufficiently smart compiler" with "one hasn't appeared yet, despite at least 3 decades of waiting". But LuaJIT has appeared.


You need a test for the exit condition (read returning back -1) and you need to flush stdout.


Right, thanks. Either way, it's not rocket surgery.


Agreed. Then again, you did mess it up the first time, so I guess it is an effective test. Everyone uses the buffer, which I find amusing.


> In my defence, I have never, in all my years of working, had to ever read standard input, let alone write it out again.

Yeah, but there is nothing different from this and having to copy data from an input stream to an output stream. If you can't remember how to do that, it kind of raises the question of what you were doing in Java.

Not knowing if you need to buffer is actually fine in my book. That's an optimization thing. Not knowing how to make the code correct though...


Crud apps my man, ones where the framework did all the IO for you.


You probably never use the command line. People like me who use pipelines on *nix [1] every day write these sorts of filters all the time.

[1] http://en.wikipedia.org/wiki/Pipeline_%28Unix%29#Pipelines_i...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: