Skip to content

Instantly share code, notes, and snippets.

@kosta
Created March 26, 2014 06:47
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kosta/9777932 to your computer and use it in GitHub Desktop.
Save kosta/9777932 to your computer and use it in GitHub Desktop.
Copy stdin to stdout in Java
import java.io.IOException;
/**
* Class that copies stdin to stdout, as compained about as not being cleanly
* writable in Java on Hacker News.
* In real code, you would just write IOUtils.copy(System.in, System.out),
* which does basically the same thing.
* This does not catch any exceptions as a) this is just an "exercise" and
* b) all we could do with them is pretty-print them. So let the runtime
* print them for you.
*
* Usage: javac inout.java && echo -e "foo\nbar" | java InOut
*/
class InOut {
public static void main(String[] args) throws IOException {
byte[] buffer = new byte[8192];
while(true) {
int bytesRead = System.in.read(buffer);
if (bytesRead == -1) {
return;
}
System.out.write(buffer, 0, bytesRead);
}
}
}
@radiofreejohn
Copy link

as complained about :)

@ssijak
Copy link

ssijak commented Mar 26, 2014

print(input())
That was in python.
But why would you try to "defend" java from some random comment on the net?

@17twenty
Copy link

@ssijak

Slightly more verbose but yeah, Java clearly wins on clarity :D

!/usr/bin/env python

from sys import stdin
print stdin.read()

@asgeirn
Copy link

asgeirn commented Mar 26, 2014

Even shorter:

public class Cat {
    public static void main(String[] args) throws java.io.IOException {
        int i;
        do {
            System.out.write(i = System.in.read());
        } while (i != -1);
    }
}

And btw, from my reading of the OpenJDK source, System.in and System.out are already buffered:

        FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
        FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
        FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
        setIn0(new BufferedInputStream(fdIn));
        setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
        setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true));

@hugobenichi
Copy link

with buffering:

public static void cat() {
  try {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    for (;;) {
      String line = in.readLine();
      if (line == null) break;
      System.out.println(line);
    }
  } catch (IOException ioe) {}
}

@525c1e21-bd67-4735-ac99-b4b0e5262290

Node.js

process.stdin.pipe(process.stdout)

@deoxxa
Copy link

deoxxa commented Mar 26, 2014

Any terminal that even pretends to act anything like unix:

$ cat

Copy link

ghost commented Mar 26, 2014

perl -pe1

@ajermakovics
Copy link

@bjourne
Copy link

bjourne commented Mar 26, 2014

Seem to have some character encoding issues:

C:\p\c\java> cat test4.txt
latin 1
åke är örjan

C:\p\c\java> cat test4.txt | java InOut
latin 1
Õke õr ÷rjan

C:\p\c\java> cat test5.txt
utf 8
åke är örjan

C:\p\c\java> cat test5.txt | java InOut
utf 8
├Ñke ├ñr ├Ârjan

Yeah I know it wasn't part of the "spec" but most the "competing" solutions in other languages handles it for you transparently by using strings instead of bytes.

@canoon
Copy link

canoon commented Mar 26, 2014

Seems more like a Windows issue. Works fine on linux (admittedly latin1 doesn't display as it's a utf8 terminal). Converting to characters would be huge overhead on utf8 systems where it would convert utf8 to utf16 and back.

cameron@arch-laptop [09:27:44] [~/tmp] 
-> % cat utf8.txt 
åke är örjan
cameron@arch-laptop [09:27:47] [~/tmp] 
-> % cat latin1.txt 
�ke �r �rjan
cameron@arch-laptop [09:27:50] [~/tmp] 
-> % cat utf8.txt | java InOut 
åke är örjan
cameron@arch-laptop [09:27:56] [~/tmp] 
-> % cat latin1.txt | java InOut 
�ke �r �rjan

@be5invis
Copy link

@bjourne @canoon

Hmmm... The STDIN and STDOUT are just bytes, and Java mis-converted them into UTF-16 using the system's default encoding.

@canoon
Copy link

canoon commented Mar 26, 2014

@be5invis It's not that simple. Java isn't converting anything as it's reading it in bytes. I suspect his utf8 file is actually utf16 hence the multibyte characters but either way I think the terminal or cat is doing some funky conversions detecting its going to a terminal not another process which are lost when piped through java. That's the only his terminal can display both unicode and latin1 at the same time.

@rShetty
Copy link

rShetty commented Mar 26, 2014

In Ruby:

puts(gets())

@tonyedgecombe
Copy link

In C#

Console.OpenStandardInput().CopyTo(Console.OpenStandardOutput());

@caisah
Copy link

caisah commented Mar 26, 2014

In Racket:

(display (read (current-input-port)))

@armen
Copy link

armen commented Mar 26, 2014

@jamesmoriarty
Copy link

#!/usr/bin/env ruby
IO.copy_stream(STDIN, STDOUT)

Copy link

ghost commented Mar 26, 2014

C#

using System;

public class Program
{
    public static void Main()
    {
        while(true)
        {
            int input = Console.In.Read();
            if(input == -1) break;
            Console.Out.Write((char)input);
        }
    }
}

@winny-
Copy link

winny- commented Mar 26, 2014

@ssijak I think you misunderstood what that Java program does. It copies the input verbatim to the output.

$ printf 'hello\nworld\n' | python3 -c 'print(input())'
hello
$

It also mangles binary data since it uses print() which will add a newline to the end of its arguments by default (try end='' to never write a final newline).

$ printf 'binarydata' | python3 -c 'print(input())' | hexdump -C
00000000  62 69 6e 61 72 79 64 61  74 61 0a                 |binarydata.|
0000000b

instead of...

$ printf 'binarydata' | hexdump -C
00000000  62 69 6e 61 72 79 64 61  74 61                    |binarydata|
0000000a
$

Observe there is no newline in the last example.

@17twenty I don't think your program respects binary data either because the print statement needs a final comma to suppress the final newline.
@rShetty Your example appears to only copy the first line in Ruby. Does puts add a final newline as well?

Anything that "gets a line" uses a newline as a sentinel value and is not a solution. The sentinel of an input stream is an EOF marker (in python the sentinel is an empty string returned from the .read() method). I think Programming Pearls has a section about the importance of an unique sentinel value.

Python

Using partial as suggested in Transforming Code into Beautiful Idiomatic Python (the example slide):

from functools import partial
from sys import stdout, stdin

for block in iter(partial(stdin.read, 32), ''):
    stdout.write(block)

Note that partial is optional — lambda: stdin.read(32) also works.

@valduze
Copy link

valduze commented Mar 26, 2014

/In C/

include <stdio.h>

int main(int argc, char **argv)
{
int c;
while((c = getchar()) != EOF)
putchar(c);
return 0;
}

@co-dh
Copy link

co-dh commented Mar 26, 2014

in bash:
echo

@joewalnes
Copy link

In French:

Copiez entrée à la sortie

@tcard
Copy link

tcard commented Mar 26, 2014

In Go:

io.Copy(os.Stdout, os.Stdin)

Libraryless:

b := make([]byte, 1024)
for n, err := os.Stdin.Read(b); err == nil; n, err = os.Stdin.Read(b) {
    os.Stdout.Write(b[:n])
}

@nurettin
Copy link

In Turkish:

Girdiyi çıktıya aktar.

@BepBop
Copy link

BepBop commented Feb 21, 2022

uhh I dont understand why this isnt a valid solution 

import java.util.Scanner; 

public class Main
{

  public static void main (String[]args) 
  {
    while(true)
    {
        Scanner sc = new Scanner(System.in);
        System.out.println(sc.nextLine());
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment