大家都知道,或者说都听说过流这个东西,但是他到底是干什么的,或者怎么用,有些编程的同道中人就不清楚了,而且一开始我去读文件或者写文件都会出现乱码的问题,后来自己查阅了资料之后,大体弄明白了一些道道,觉得还是分享一下,也便于自己梳理一下思路,整理一下各种流之间的一些关系。
流就是I/O流了,I就是input,o就是output。其实流呢就是抽象了各种信息,也可以看成管道来传输信息。输入流就是来读数据的,输出流就是用来写数据的。
那么,流能分成几种呢?在java中可以分成字节流,字符流。首先字节流:就是用来处理字节为单位的输入输出,一般用来处理图像和声音文件。字符流:就是以字符为单位的输入输出,一般用于处理文本的信息。
字节流:InputStream是所有字节输入流的祖先类,OnputStream是所有字节输出流的祖先类。
字符流:Reader是所有字符输入流的祖先类,Writer是所有字符输出流的祖先类。
1.那么以FileInputStream来演示字节输入流,FileOutputStream来演示字节输出流:
public class FileInputStreamTest {
public static void main(String[] args) {
// 声明一个文件输入流
FileInputStream fis = null;
try {
//对应的文件路径,文件的内容就是hello world!
fis = new FileInputStream("C:\\Users\\78623\\Desktop\\in.txt");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int input = 0;
try {
//如果不到文件的末尾就一直读
input = fis.read();
while(input != -1){
System.out.print((char)input);
input = fis.read();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出的内容就是 hello world!。典型的FileInputStream的简单应用。看似很成功,但是如果文件里面有汉字那么就会输出乱码,这是为什么呢,其实道理很简单,因为字节流是以字节为单位读取文件内容的,一个汉字虽然在不同 的编码格式中占的字节数量不同,但是最少是两个字节,那么一个字节是表示不了一个汉字的,所以会出现乱码,那么怎么读取汉字,别急,后面会说。
package outputstream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
FileOutputStream fos = null;
String str = "hello world!";
File file = new File("C:\\Users\\78623\\Desktop\\out.txt");
//如果文件不存在就创建一个
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//生成一个byte数组
byte[] b = str.getBytes();
try {
fos.write(b);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(fos != null){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
这个呢就是往文件里面 写数据,如果文件不存在的话就创建一个,运行结果:
同样,这个也不能写中文,但是但这里,大家应该对字节输入输出流有一个了解了。好,接下来我们来看一下字符输入输出流。
2.以来InputStreamReader演示字符输入流,OutputStreamReader来演示字符输出流:
在上面说过,不同的编码方式汉字所占的字节数是不一样的,比如在UTF-8中,一个汉字占3个字节;在GBK编码中,一个汉字占2个字节。那么怎么读入和读出汉字呢,就要用字符流了。
这个类很有趣,名字里既有InputStream又有Reader。其实这个类就是字节流通往字符流的桥梁。看程序:
public class InputStreamReaderTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
FileInputStream fis = null;
InputStreamReader isr = null;
File file = null ;
file = new File("C:\\Users\\78623\\Desktop\\in.txt");
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
fis = new FileInputStream(file);
isr = new InputStreamReader(fis);
//读取数据
int reader = 0;
reader = isr.read();
while(reader != -1){
System.out.print((char)reader);
reader = isr.read();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
if(fis != null){
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(isr != null){
try {
isr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
读取的文件内容是:
但是实际输出的内容却是:
汉字还是乱码,这究竟是为什么,其实原因也很简单,因为读取汉字的时候要指明编码格式,不指明就默认按照当前编译器的编码格式,现在我用的eclipse是用GBK编码,但是读取的文件却是用UTF-8编码的,所以在创建InputStreamReader的时候指明编码格式:
isr = new InputStreamReader(fis,"UTF-8");
然后运行结果:
在这里说一下为什么创建InputStreamReader的时候用到FileInputStream作为参数,因为刚刚说到InputStreamReader就是一个字节通往字符的桥梁,因此在真正读文件数据的时候还是用FileInputStream去读,但是真正处理的时候却是按照编码格式处理的,这时候就用InputStreamReader去处理,最终输出结果。
那么接下来看一下OutputStreamWriter的工作原理:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class OutputStreamWriterTest {
public static void main(String[] args) {
File file = null;
FileOutputStream fos = null;
OutputStreamWriter osw = null;
file = new File("C:\\Users\\78623\\Desktop\\out.txt");
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
fos = new FileOutputStream(file);
osw = new OutputStreamWriter(fos, "UTF-8");
String str = "我的程序,hello my programer";
for(int i = 0; i < str.length(); i++){
try {
osw.write(str.charAt(i));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(osw != null){
try {
osw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
最终结果顺利写入文件: