HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

各言語で標準入力から1バイトずつ読み込んで標準出力に吐き出すプログラムを書いてみる

唐突に、手元にある各言語で標準入力から1バイトずつ読み込んで標準出力にそのまま吐き出すプログラムを書いてみようと思ったメモ。

普段は使わない言語も混じっているが、まぁ気にしない。

環境

手元にあるものということで、環境は以下のものに限定する。

入力ファイル

所謂バイナリデータも含むので、od -cした結果を載せておく。

  • 001.txt
0000000   H   e   l   l   o       W   o   r   l   d   !  \n
0000015
  • 002.txt
0000000  \0 001 002 003 004 005 006  \a  \b  \t  \n  \v  \f  \r 016 017
0000020 020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037
0000040       !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
0000060   0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
0000100   @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
0000120   P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
0000140   `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
0000160   p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~ 177
0000200 200 201 202 203 204 205 206 207 210 211 212 213 214 215 216 217
0000220 220 221 222 223 224 225 226 227 230 231 232 233 234 235 236 237
0000240 240 241 242 243 244 245 246 247 250 251 252 253 254 255 256 257
0000260 260 261 262 263 264 265 266 267 270 271 272 273 274 275 276 277
0000300 300 301 302 303 304 305 306 307 310 311 312 313 314 315 316 317
0000320 320 321 322 323 324 325 326 327 330 331 332 333 334 335 336 337
0000340 340 341 342 343 344 345 346 347 350 351 352 353 354 355 356 357
0000360 360 361 362 363 364 365 366 367 370 371 372 373 374 375 376 377
0000400

2つ目のファイルは、制御文字も含めて、8ビットcharとしてありうるものを256個すべて並べたもの。

Java

import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            int ch;
            while ((ch = System.in.read()) != -1) {
                System.out.write(ch);
            }
            System.out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

C

#include <stdio.h>

int main(int argc, char** argv) {
    int ch;

    while ((ch = getchar()) != -1) {
        putchar(ch);
    }

    return 0;
}

C++

#include <iostream>

using namespace std;

int main(int argc, char** argv) {
    char ch;

    while (cin.get(ch)) {
        cout << ch;
    }

    return EXIT_SUCCESS;
}

PHP

<?php

$in = fopen('php://stdin', 'r');
$out = fopen('php://stdout', 'w');
while (($ch = fgetc($in)) !== FALSE) {
    fputs($out, $ch);
}

Python 2

import sys;

while True:
    ch = sys.stdin.read(1)
    if ch == '':
        break
    sys.stdout.write(ch)

Python 3

import sys;

while True:
    ch = sys.stdin.buffer.read(1)
    if ch == b'':
        break
    sys.stdout.buffer.write(ch)

Ruby

while ch = STDIN.getc
    STDOUT.putc(ch.chr)
end

Perl

binmode(STDIN);
while (undef != read(STDIN, $ch, 1)) {
    print $ch;
}

Go

package main

import (
    "bufio"
    "io"
    "os"
)

func main() {
    stdin := bufio.NewReader(os.Stdin)
    stdout := bufio.NewWriter(os.Stdout)
    for {
        ch, err := stdin.ReadByte()
        if err == io.EOF {
            break
        }
        stdout.WriteByte(ch)
    }
    stdout.Flush()
}

bash

実を言うと、bashの場合は2つ目のファイルで正しい結果が得られないという問題がある。readコマンドで読み込むときに1バイトを超えて読み込む場合があるようで、後半部分の出力が期待値と合わない。ただ、7ビットASCIIの範囲では問題なく読み書きできているので一応載せておく。

#! /bin/bash

while IFS= read -r -N 1 ch ; do
    printf "%c" "${ch}"
done