type=class
superclass=Object
included=Enumerable,File=Constants
extended=
library=_builtin
aliases=
aliasof=

基本的な入出力機能のためのクラスです。


File::Constants は、[[c:File]] から IO へ移動しました。

===[a:m17n] 多言語化と IO のエンコーディング

IO オブジェクトはエンコーディングを持ちます。
エンコーディングの影響を受けるメソッドと受けないメソッドがあります。

影響を受けるメソッドでは、IO のエンコーディングに従い読み込まれた文字列のエンコーディングが決定されます。
また IO のエンコーディングを適切に設定することにより、読み込み時・書き込み時に文字列のエンコーディングを
変換させることもできます。

==== エンコーディングの影響を受けるメソッドと受けないメソッド

IO の読み込みメソッドは2種類存在します。
テキスト読み込みメソッドとバイナリ読み込みメソッドです。

テキスト読み込みメソッドは IO のエンコーディングの影響をうけます。
詳しくは「[[ref:io_encoding]]」を参照して下さい。
以下がテキスト読み込みメソッドです。

 * [[m:IO.foreach]]
 * [[m:IO.readlines]]
 * [[m:IO#each_line]]
 * [[m:IO#lines]]
 * [[m:IO#gets]]
 * [[m:IO#getc]]
 * [[m:IO#ungetc]]
 * [[m:IO#read]]
 * [[m:IO#readchar]]
 * [[m:IO#readline]]
 * [[m:IO#readlines]]

バイナリ読み込みメソッドは IO のエンコーディングの影響を受けません。
返す文字列のエンコーディングは常に ASCII-8BIT になります。
以下がバイナリ読み込みメソッドです。

 * [[m:IO#read]](size) 
 * [[m:IO#read_nonblock]]
 * [[m:IO#readpartial]]
 * [[m:IO#sysread]]

また書き込みメソッド [[m:IO#write]] も IO のエンコーディングの影響を受けます。
IO のすべての書き込みメソッドは内部で [[m:IO#write]] を呼びますので、
書き込みメソッドはすべて IO のエンコーディングの影響を受けます。

シーク関連のメソッドはエンコーディングの影響を受けません。
常に1バイトを単位として動作します。

例:

  f = File.open('t.txt', 'r+:euc-jp')
  p f.getc.encoding                             #=> Encoding::EUC_JP
  p f.read(1).encoding                          #=> Encoding::ASCII_8BIT 

====[a:io_encoding] IO のエンコーディングとエンコーディングの変換

IO オブジェクトは外部エンコーディングと内部エンコーディングを持ちます。
外部エンコーディングとは IO が表すファイルなどの文字エンコーディングです。
内部エンコーディングとは IO から読み込まれた文字列、あるいは IO の書き込みメソッドへ渡す文字列
の文字エンコーディングです。

以下の三通りがあります。

: IO のエンコーディングが指定されていない場合

  IO からテキスト読み込みメソッドによって読み込まれた文字列のエンコーディングは [[m:Encoding.default_external]]
  に設定されます。このとき実際の文字エンコーディングは検査されず、変換もされません。

: 外部エンコーディングのみが指定されている場合

 IO からテキスト読み込みメソッドによって読み込まれた文字列のエンコーディングは外部エンコーディング
 に設定されます。このとき実際の文字エンコーディングは検査されず、変換もされません。

 IO へ書き込まれる文字列は外部エンコーディングへと変換されます。
 外部エンコーディングへの変換方法が分からない場合は例外が発生します。

: 外部エンコーディングと内部エンコーディング(あるいは default_internal)が指定されている場合
 IO からテキスト読み込みメソッドによって読み込まれた文字列は、外部エンコーディングから
 内部エンコーディング(あるいは default_internal)へと変換されます。
 指定された文字エンコーディングと実際の文字エンコーディングが違っていた場合、例外が発生します。
 内部エンコーディングと  [[m:Encoding.default_internal]] が両方とも指定されている場合は、
 内部エンコーディングが優先されます。

 IO へ書き込まれる文字列は外部エンコーディングへと変換されます。
 外部エンコーディングへの変換方法が分からない場合は例外が発生します。


IO に対してエンコーディングを指定する方法には、生成時に [[m:IO.open]] や [[m:File.open]] 
に渡すモードとともに指定するものと
生成後に [[m:IO#set_encoding]] を使って指定するものの二通りがあります。詳しくはそれぞれのメソッドの項を
参照して下さい。通常は前者の方法を使います。

例1:

  f = File.open('file1')
  p f.getc.encoding        #=> Encoding::EUC_JP

例2:

  f = File.open('t.txt', 'w+:shift_jis:euc-jp')
  f.write "\xB4\xC1\xBB\xFA"            # 文字列 "漢字" の EUC-JP リテラル
  f.rewind
  s = f.read(4)
  puts s.dump                           #=> "\x8A\xBF\x8E\x9A" 
                                        # エンコーディングがSJISへ変換されていることが分かる。

===== まとめ

以上をまとめると以下の表のようになります。[[m:Encoding.default_external]] は常に設定されているので、省略してあります。

読み込んだ文字列のエンコーディング
                                                    バイナリ読み込みメソッド      テキスト読み込みメソッド
 ----------------------------------------------------------------------------------------------------------
                                         指定無し        ASCII-8BIT                   default_external
 
                            default_internal のみ        ASCII-8BIT                   default_internal
 
                         外部エンコーディングのみ        ASCII-8BIT                 外部エンコーディング
 
                     内部エンコーディング指定あり        ASCII-8BIT                 内部エンコーディング
  
     内部エンコーディングと default_internal 両方        ASCII-8BIT                 内部エンコーディング

エンコーディングの変換
                                               バイナリ読み込みメソッド   テキスト読み込みメソッド   書き込みメソッド
 ---------------------------------------------------------------------------------------------------------------------
                                   指定無し           変換なし                 変換なし                   変換なし

                   外部エンコーディングのみ           変換なし                 変換なし                   変換あり
         
                      default_internal のみ           変換なし                 変換あり                   変換あり 
  
                   内部エンコーディングのみ           変換なし                 変換あり                   変換あり

 外部エンコーディングと内部エンコーディング           変換なし                 変換あり                   変換あり

    外部エンコーディングと default_internal           変換なし                 変換あり                   変換あり

==== デフォルトの外部エンコーディングの指定

[[m:Encoding.default_external]] はコマンドオプション -E で指定します。
-E が指定されなかった場合は次のような優先順位で決定されます。

 -E (最優先) > -K > locale

==== ファイル名のエンコーディング

ファイル名の文字エンコーディングはプラットフォームに依存します。
ファイル名の文字エンコーディングが固定されているプラットフォーム(Win, Mac)では、
エンコーディングは暗黙に変換されます(予定)。UNIX では変換されずそのままシステムコールに渡されます。

[[m:Dir.glob]], [[m:Dir.foreach]] などが返すファイル名のエンコーディングも同様にプラットフォーム依存です。
UNIX では ASCII-8BIT です。

==== binmode

Windows の IO にはテキストモードとバイナリモードという2種類のモードが存在します。
これらのモードは上で説明した IO のエンコーディングとは独立です。改行の変換にしか影響しません。


=== EOF での読み込みメソッドの振る舞いの違い

空ファイルや EOF での各読み込みメソッドの振る舞いは以下のとおりです。
ただし、length を指定できるメソッドに関しては、length に nil または 0 を指定した場合、
EOF であっても常に空文字列 "" を返します。

//emlist{
メソッド                      空のファイルに対して

IO.read(空ファイル)           ""
IO.read(空ファイル, length)   nil
IO.readlines(空ファイル)      []
IO.foreach(空ファイル)        何もしない
//}

//emlist{
メソッド                      既にEOFだったら

IO#each_byte                  何もしない
IO#getc                       nil
IO#gets                       nil
IO#read()                     ""
IO#read(length)               nil
IO#read_nonblock              EOFError
IO#readchar                   EOFError
IO#readline                   EOFError
IO#readlines                  []
IO#readpartial                EOFError
IO#sysread                    EOFError
IO#bytes                      通常どおり
IO#lines                      通常どおり
//}
