Java IO詳細
7343 ワード
参照リンク:
http://ifeve.com/java-io/
http://www.regexlab.com/zh/encoding.htm
Java IOは主に元のデータソースとターゲットメディアとの間でデータを伝送するために使用されます.一般的なデータソースとターゲットメディアは以下の通りです.ファイル パイプライン ネットワーク接続 メモリバッファ System.in、System.out、System.error(注:Java標準入出力、エラー出力) 入出力とはプログラムを中心としたもので、入力とはデータをプログラムメモリに入力し、出力とはデータをメモリからターゲットメディアに出力することです.
流れ
Java_IOでは、ストリームはコア概念である.ストリームは、概念的には連続的なデータストリームである.流れからデータを読み取ることもできますし、流れにデータを書くこともできます.ストリームは、データソースまたはデータの流れの媒体に関連している.Java_IOにおいてストリームは、バイトストリーム(バイト単位で読み書き)であっても良いし、文字ストリーム(文字単位で読み書き)であっても良い.
入力ストリーム:データソース-->メモリ 出力ストリーム:メモリ-->ターゲットメディア
入力ストリーム:InputStream Reader 出力ストリーム:OutputStream Writer
Java IOは主に以下のように使われています.ファイルアクセス ネットワークアクセス メモリキャッシュアクセス スレッド内部通信(パイプライン) バッファ フィルタ 解析 読み書きテキスト(Readers/Writers) 基本タイプデータを読み書きする .読み書き対象 Java IO分類
入出力およびバイト文字、機能特性により、IOを大まかに分類することができます.
バイト、文字、コード
バイト: コンピュータにデータを格納するユニットは、8ビットのバイナリ数であり、非常に具体的な記憶空間である.
文字: 人々が使用する記号、抽象的な意味での記号.
エンコード:各「文字」はそれぞれ1バイトか複数バイトで記憶すると規定されていますが、どのバイトが記憶されていますか?
一般的な符号化方式は:
カテゴリ
コーディング基準
説明
単バイト文字コード
ISO-859-1
最も簡単な符号化ルールは、各バイトごとにユニコムの文字として直接に使用されます.例えば、[0 xD 6,0 xD 0]の2バイトが、iso-859-1で文字列に変換された場合、[0 x 00 D 6,0 x 00 D 0]の2つのユニコム文字が直接に得られます.Ð". 逆に、UNICODE文字列をiso-859-1でバイト列に変換する場合は、0~255の範囲の文字しか正常に変換できません.
ANSIコード
GB 2312、BIG 5、ShiftchuJIS、ISO-859-2…
UNICODE文字列をANSI符号化により「バイト列」に変換する場合、各符号化の規定により、一つのUNICODE文字が一つのバイトまたは複数のバイトに変換されます.逆に、バイト列を文字列に変換すると、複数のバイトが一つの文字に変換されることもあります.例えば、[0 xD 6,0 xD 0]の2バイトは、GB 2312を通じて文字列に変換されると、文字列に変換されます.[0 x 4 E 2 D]は、「中」という文字です.「ANSI符号化」の特徴:1.これらの「ANSI符号化規格」は、それぞれの言語範囲内のUNICODE文字しか処理できません.2.「UNICODE文字」と「変換されたバイト」の関係は人為的に規定されています.
ユニットコード
UTF-8、UTF-16、Unicode Big…
「ANSI符号化」と同様に、文字列をUNIcodeで符号化して「バイト列」に変換すると、一つのUNICODE文字が1バイト以上に変換されます.ANSI符号化とは異なり、1.これらの「UNIKODEコード」は全てのUNIKODE文字を処理することができます.2.「UNICODE文字」と「変換されたバイト」です.間は計算によって得られます.
文字列は抽象的な表現方法であり、例えば「文字列123」には6文字の構成が考えられ、漢字と数字はいずれも1文字と考えられます.
バイト列は、記憶の観点から言えば、各文字は何バイト記憶されていますか?例えば、GBK符号化方式では、「文字列123」は9バイト記憶されています.ここで、漢字1つと数字1バイトがあります.
Javaでは、具体的な文字とバイトの符号化変換は、Stringにより実現されてもよい.
文字をバイトに変換:
Java IOの基本的な使い方:
バイト出力ストリーム:
文字出力ストリーム:
http://ifeve.com/java-io/
http://www.regexlab.com/zh/encoding.htm
Java IOは主に元のデータソースとターゲットメディアとの間でデータを伝送するために使用されます.一般的なデータソースとターゲットメディアは以下の通りです.
流れ
Java_IOでは、ストリームはコア概念である.ストリームは、概念的には連続的なデータストリームである.流れからデータを読み取ることもできますし、流れにデータを書くこともできます.ストリームは、データソースまたはデータの流れの媒体に関連している.Java_IOにおいてストリームは、バイトストリーム(バイト単位で読み書き)であっても良いし、文字ストリーム(文字単位で読み書き)であっても良い.
入力ストリーム:データソース-->メモリ 出力ストリーム:メモリ-->ターゲットメディア
入力ストリーム:InputStream Reader 出力ストリーム:OutputStream Writer
Java IOは主に以下のように使われています.
入出力およびバイト文字、機能特性により、IOを大まかに分類することができます.
バイト、文字、コード
バイト: コンピュータにデータを格納するユニットは、8ビットのバイナリ数であり、非常に具体的な記憶空間である.
文字: 人々が使用する記号、抽象的な意味での記号.
エンコード:各「文字」はそれぞれ1バイトか複数バイトで記憶すると規定されていますが、どのバイトが記憶されていますか?
一般的な符号化方式は:
カテゴリ
コーディング基準
説明
単バイト文字コード
ISO-859-1
最も簡単な符号化ルールは、各バイトごとにユニコムの文字として直接に使用されます.例えば、[0 xD 6,0 xD 0]の2バイトが、iso-859-1で文字列に変換された場合、[0 x 00 D 6,0 x 00 D 0]の2つのユニコム文字が直接に得られます.Ð". 逆に、UNICODE文字列をiso-859-1でバイト列に変換する場合は、0~255の範囲の文字しか正常に変換できません.
ANSIコード
GB 2312、BIG 5、ShiftchuJIS、ISO-859-2…
UNICODE文字列をANSI符号化により「バイト列」に変換する場合、各符号化の規定により、一つのUNICODE文字が一つのバイトまたは複数のバイトに変換されます.逆に、バイト列を文字列に変換すると、複数のバイトが一つの文字に変換されることもあります.例えば、[0 xD 6,0 xD 0]の2バイトは、GB 2312を通じて文字列に変換されると、文字列に変換されます.[0 x 4 E 2 D]は、「中」という文字です.「ANSI符号化」の特徴:1.これらの「ANSI符号化規格」は、それぞれの言語範囲内のUNICODE文字しか処理できません.2.「UNICODE文字」と「変換されたバイト」の関係は人為的に規定されています.
ユニットコード
UTF-8、UTF-16、Unicode Big…
「ANSI符号化」と同様に、文字列をUNIcodeで符号化して「バイト列」に変換すると、一つのUNICODE文字が1バイト以上に変換されます.ANSI符号化とは異なり、1.これらの「UNIKODEコード」は全てのUNIKODE文字を処理することができます.2.「UNICODE文字」と「変換されたバイト」です.間は計算によって得られます.
文字列は抽象的な表現方法であり、例えば「文字列123」には6文字の構成が考えられ、漢字と数字はいずれも1文字と考えられます.
バイト列は、記憶の観点から言えば、各文字は何バイト記憶されていますか?例えば、GBK符号化方式では、「文字列123」は9バイト記憶されています.ここで、漢字1つと数字1バイトがあります.
public static void main(String[] args) throws Exception {
System.out.println(" ====== "+System.getProperty("file.encoding"));
String str = " 123";
System.out.println(" " + str.length());
System.out.println(" " + str.getBytes().length);
System.out.println("GBK " + str.getBytes("GBK").length + " " + Arrays.toString(str.getBytes("GBK")));
System.out.println("UTF8 " + str.getBytes("UTF8").length + " " + Arrays.toString(str.getBytes("UTF8")));
}
テストは上述のように、文字列の長さが6であることが分かります.符号化方式によって、格納されているバイトの長さが違っています.数字に対してASC 124符号化が採用されています.漢字については、GBKとUTF 8符号化方法は違います. ====== GBK
6
9
GBK 9 [-41, -42, -73, -5, -76, -82, 49, 50, 51]
UTF8 12 [-27, -83, -105, -25, -84, -90, -28, -72, -78, 49, 50, 51]
文字列「文字列123」については、異なる符号化でファイルに保存し、バイトストリームを通して読み取って、1バイトの読み取り毎に、GBKは9回ループし、UTF 8は12回ループするべきである.@Test
public void testByte() throws Exception{
String filepath = "D://debug_drv2-stream.log";
String encode = "UTF8";
OutputStream os = new FileOutputStream(new File(filepath));
os.write(new String(" 123").getBytes(encode));
os.close();
InputStream is = new FileInputStream(new File(filepath));
int n = -1;
int count = 0;
while((n = is.read())!=-1){
count++;
System.out.println(n);
}
System.out.println("count = " + count);
is.close();
byte[] bytes = new byte[1024];
InputStream is2 = new FileInputStream(new File(filepath));
is2.read(bytes);
System.out.println(new String(bytes, encode));
is2.close();
}
出力ストリームを利用して文字列をファイルに書き込む場合は、必ずコードを指定してください.ここでWindowsオペレーティングシステムの理由でデフォルトではGBKコードを使用します.入力ストリームを利用してファイルからバイトを読み出す場合は、バイトを文字列に変換します.コード方式を指定しなければなりません.デフォルトはGBKです.Javaでは、具体的な文字とバイトの符号化変換は、Stringにより実現されてもよい.
文字をバイトに変換:
public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null) throw new NullPointerException();
return StringCoding.encode(charsetName, value, 0, value.length);
}
バイトを文字に変換: public String(byte bytes[], String charsetName)
throws UnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
}
デフォルトでは同じオペレーティングシステムで同じ符号を使って変換すると文字化けが発生しません.符号化方式が一致しないと文字化けが発生します. String str = " 123";
byte[] bytes = str.getBytes("UTF8");
System.out.println(new String(bytes));
System.out.println(new String(bytes,"UTF8"));
?123
123
str.getByttes(「」)はUTF 8を用いて符号化され、Stringに変換されると、第1の方式はデフォルトがGBKと指定されていないため、文字化けが発生しない.第2の指定符号化方式は文字化けが発生しない.Java IOの基本的な使い方:
バイト出力ストリーム:
@Test
public void testOutputStream() throws Exception{
OutputStream os = new FileOutputStream(new File("D://debug_drv2-stream.log"));
os.write(new String(" 123").getBytes());
os.close();
}
バイト入力ストリーム読み:@Test
public void testInputStream() throws Exception{
byte[] bytes = new byte[1024];
InputStream is = new FileInputStream(new File("D://debug_drv2-stream.log"));
// StringBuilder sb = new StringBuilder();
// int n = -1;
// int count = 0;
// while((n = is.read())!=-1){
// count++;
// System.out.println(n);
// sb.append((char)n);
// }
// System.out.println(sb.toString());
// System.out.println("count = " + count);
is.read(bytes);
System.out.println(Arrays.toString(bytes));
System.out.println(new String(bytes));
is.close();
}
バイトストリームを使用する場合は、符号化方式の統一に注意しなければならない.文字出力ストリーム:
@Test
public void testWriter() throws Exception{
Writer w = new FileWriter(new File("D://debug_drv2-writer.log"));
w.write(new String(" 123"));
w.close();
}
文字入力ストリーム:@Test
public void testReader() throws Exception{
//Reader r = new InputStreamReader(new FileInputStream(new File("D://debug_drv.log")));
Reader r = new FileReader(new File("D://debug_drv2-writer.log"));
int c = -1;
int count = 0;
while((c = r.read())!=-1){
count++;
System.out.println(c + "----" + (char)c);
}
System.out.println("count = " + count);
r.close();
}
文字ストリームとバイトストリームは相互に変換できます. InputStream is = new FileInputStream(new File("D://debug_drv2-stream.log"));
InputStreamReader isr = new InputStreamReader(is, "GBK");
ReaderInputStream ris = new ReaderInputStream(isr, "GBK");