ファイル・標準入力の中身をまとめて1つの文字列として取得するには (file_get_contents)

ファイル名から簡単にその中のテキストを文字列として取得する方法のまとめ。 PHPだと file_get_contents という1つの関数で簡単にできるんだが。

あと、ファイルの他に標準入力をまとめて取得する方法も。

Go言語

package main

import "os"
import "io/ioutil"

func main() {
    var input, _ = os.Open("./foo.txt"))
    var content, _ = ioutil.ReadAll(input)
    input.Close()
    os.Stdout.Write(content)
}

ioutil.ReadAll(input) の代わりに、ioutil.ReadAll(os.Stdin) とすると、標準入力をまるごと読み込める。

この例ではエラーを無視しちゃってる、、、

Scala

どういう方法が一番スマートなのかわからないが、以下はJavaっぽく java.io.Reader を使う例。

val input = new java.io.FileReader(filePath);
val str = try {
  val text = new java.lang.StringBuilder();
  val buf = new Array[Char](1024);
  while ({
    val len = input.read(buf);
    if (len < 0) {
      false;
    } else {
      text.append(buf, 0, len);
      true;
    }
  }){}
  text.toString;
} catch { case e: java.io.IOException =>
  ""; // TODO エラー処理
} finally {
  input.close();
}

最初、上記コードの中で java.lang.StringBuilder を単に StringBuilder と書いてしまっていてハマった。

単に StringBuilder と書くと、 scala.collection.mutable.StringBuilder を指してしまい、これには #append(buf: Array[Char], offset: Int, length: Int) というメソッドがなく、なんの警告もなしに代わりに #append(obj: Any) が呼び出されてしまう。このメソッドに引数を複数与えると勝手にタプルに変換されてしまうので、結果的に ([C@65b164f2,0,6)([C@65b164f2,0,3) みたいな意味のない文字列が生成されてしまう。

PHP

$str = file_get_contents('./hoge.txt');

失敗した場合は FALSE を返される。

ファイル名ではなくURLを与えると、HTTPアクセスしてレスポンス本体を文字列で取得できる。この関数でHTTPアクセスすると、$http_response_header という名前のローカル変数が勝手に作られ、 HTTPレスポンスヘッダがこの変数に配列で保存される。 404などのエラーの原因はこの配列の1つ目の要素から文字列で取得できる。ホスト名が違うなど、そもそもサーバにアクセスできなかった場合には、この変数が定義されないので、参照しようとすると Undefined variable のPHP Notice が発生してしまう。以下のようにガードしたほうがよさそう。

$source = @file_get_contents($url);
if (isset($http_response_header)) {
    var_export($http_response_header);
    ...;
}

出力例

array (
  0 => 'HTTP/1.1 200 OK',
  1 => 'Server: nginx',
  2 => 'Date: Mon, 18 Jan 2016 01:35:17 GMT',
  3 => 'Content-Type: text/html; charset=UTF-8',
  4 => 'Connection: close',
  ...

それにしても関数を呼び出すだけで特定の名前のローカル変数が勝手に作られるのは気持ち悪いものである。失敗した場合には FALSE が入るとかではなく、変数が作られない、というのも。

ファイル名の代わりに php://stdin と書けば標準入力をまるごと文字列で取得することもできる。

$str = file_get_contents('php://stdin');

file_get_contents関数の代わりにfile関数を使うと、全体で1つの文字列ではなく、改行ごとの配列にしてくれる。各行の最後の改行は残ったままである。

$lines = file('./hoge.txt');

file_get_contents 関数 | PHP Manual
http://php.net/manual/ja/function.file-get-contents.php

file 関数 | PHP Manual
http://php.net/manual/ja/function.file.php

$http_response_header 変数 | PHP Manual
http://php.net/manual/ja/reserved.variables.httpresponseheader.php

Python

fh = open("./hoge.txt")
str = fh.read()
fh.close()

Ruby

str = File.read('./hoge.txt')

または

str = File.open('./hoge.txt').read

標準入力を1つの文字列にしたい場合は

str = STDIN.read

Perl

open(IN, '<', './hoge.txt') or die "Cannot open";
my @lines = <IN>;
my $str = join('', @lines);
# @lines には行単位の配列で、各行には最後の改行を含む
close IN;

手抜きでcatコマンドを使う方法

my $str = `cat ./hoge.txt`;

以下のようにすると、標準入力をまるごと読み込める。

my @lines = <STDIN>;
my $str = join('', @lines);

# または
my $str = join('', (<STDIN>);

sh (シェルスクリプト)

str=`cat ./hoge.txt`
このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。