Java中Inputstream与Reader的区别
Reader支持16位的Unicode字符输出,InputStream支持8位的字符输出。
Reader和InputStream分别是I/O库提供的两套平行独立的等级机构,
InputStream、OutputStream是用来处理8位元的流,(字节流)
Reader、Writer是用来处理16位元的流。   (字符流)
而在JAVA语言中,byte类型是8位的,char类型是16位的,所以在处理中文的时候需要用Reader和Writer。
在这两种等级机构下,还有一道桥梁InputStreamReader、OutputStreamWriter负责进行InputStream到Reader的适配和由OutputStream到Writer的适配。 
java.io.Reader 和 java.io.InputStream 组成了 Java输入类。Reader 用于读入16位字符,也就是 Unicode编码的字符;而 InputStream 用于读入 ASCII字符和二进制数据。

IOExcise.java

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;

public class IOExcise {

private static final String FINPATH = "E://fin.txt"; //输入文件

private static final String FOUTPATH = "E://fout.txt"; //输出文件

private static final String content = "HH/HellOword您好00-342345ru9568-q1-"; //写入文件内容

//创建文件
private static void createFile(String path) {
File file = new File(path);
try {
// 是目录并且存在
if (file.isDirectory()) {
return;
}
if (file.exists()) {
if (file.isFile()) {
// 是文件且存在,写入数据
FileOutputStream out = new FileOutputStream(path);
out.write(content.getBytes("UTF-8"));
}
} else {
// 文件或目录不存在的情况
String str = path.substring(path.lastIndexOf('/') + 1);
if (str.indexOf('.') == -1) {
// 需要创建目录
file.mkdirs();
} else {
// 需要创建文件
file.createNewFile();
// 写入数据
FileOutputStream out = new FileOutputStream(path);
out.write(content.getBytes("UTF-8"));
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}

// 方法(1) 文件输入、输出字节
public void readBytes(String finpath, String foutpath) throws Exception {
FileInputStream fis = new FileInputStream(finpath);
FileOutputStream fos = new FileOutputStream(foutpath);
int ch;
while ((ch = fis.read()) != -1) {
fos.write(ch);
}
if (fis != null) {
fis.close();
}
if (fos != null) {
fos.close();
}
}

// 方法(2)带有缓存的文件输入、输出字节
public void readBufferBytes(String finpath, String foutpath)
throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
finpath));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(foutpath));
int i;
while ((i = bis.read()) != -1) {
bos.write(i);
}
if (bis != null) {
bis.close();
}
if (bos != null) {
bos.close();
}
}

// 方法(3)字符流的输入输出
public void readLines(String finpath, String foutpath) throws Exception {
// 标准字符输入
// InputStreamReader ir = new InputStreamReader(System.in);
// BufferReader br = new BufferedReader(ir);
// InputStreamReader只需要把标准输入InputStream 改成File就成文件输入FileReader
BufferedReader br = new BufferedReader(new FileReader(finpath));
BufferedWriter fout = new BufferedWriter(new FileWriter(foutpath));
PrintWriter pw = new PrintWriter(fout);
String str;
while ((str = br.readLine()) != null) {
pw.println(str);
}
}

// 方法(4) 读取文件时,指定字符编码,特别是有中文的情况
public void readLinesCharSet(String finpath) throws IOException {
File f = new File(finpath);
InputStreamReader read = new InputStreamReader(new FileInputStream(f),
"UTF-8");
BufferedReader reader = new BufferedReader(read);
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}

// 方法(5)基本数据类型的输入,输出,注意,写入和读出来一定是要有顺序的
public void readData(String finpath) throws Exception {
DataOutputStream dfout = new DataOutputStream(new FileOutputStream(
finpath));
dfout.writeUTF("中国");
dfout.writeBoolean(5 < 6);
dfout.writeChar('0');
dfout.writeDouble(1.2);
dfout.writeFloat(3.4f);
dfout.writeShort(56);
dfout.writeInt(76);
dfout.writeLong(90);
dfout.writeByte(344);
dfout.flush();
dfout.close();
DataInputStream dfin = new DataInputStream(new FileInputStream(finpath));
System.out.println(dfin.readUTF());
System.out.println(dfin.readBoolean());
System.out.println(dfin.readChar());
System.out.println(dfin.readDouble());
System.out.println(dfin.readFloat());
System.out.println(dfin.readShort());
System.out.println(dfin.readInt());
System.out.println(dfin.readLong());
System.out.println(dfin.readByte());
dfin.close();
}

// 方法(6)对象的输入输去
public void writeObj(String foutpath) throws IOException {
Persion p1 = new Persion(1, "chen");
Persion p2 = new Persion(2, "li");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
foutpath));
try {
oos.writeObject(p1);
oos.writeObject(p2);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if(oos!=null){
oos.close();
}
}
}

// 读取对象
public void readObj(String finpath) throws IOException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
finpath));
Persion persion1;
Persion persion2;
try {
persion1 = (Persion) ois.readObject();
persion2 = (Persion) ois.readObject();
System.out.println(persion1 + "" + persion2);
} catch (Exception ex) {
ex.printStackTrace();
}
}

public static void main(String[] args) {
IOExcise ioex = new IOExcise();
try {
// 创建文件
createFile(FINPATH);
ioex.readBytes(FINPATH, FOUTPATH);
ioex.readBufferBytes(FINPATH, FOUTPATH);
ioex.readLines(FINPATH, FOUTPATH);
ioex.readData(FOUTPATH);
ioex.writeObj(FOUTPATH);
ioex.readObj(FOUTPATH);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

/**
* 对象定义
*
* @author Administrator
*
*/
class Persion implements Serializable {
private int id;

private String name;

public Persion() {
}

public Persion(int id, String name) {
this.id = id;
this.name = name;
}

public String toString() {
return "[ id=" + id + ",name=" + name + "]";
}
}


字节与字符的转化接口

数据持久化或网络传输都是以字节进行的,所以必须要有字符到字节或字节到字符的转化。

(1)、字符解码相关类结构

InputStreamReader 类是字节到字符的转化桥梁,InputStream 到 Reader 的过程要指定编码字符集,否则将采用操作系统默认字符集,很可能会出现乱码问题。StreamDecoder 正是完成字节到字符的解码的实现类。



(2)、字符编码相关类结构


通过 OutputStreamWriter 类完成,字符到字节的编码过程,由 StreamEncoder 完成编码过程。