您的位置:首页 > 职场人生

黑马程序员 IO流(二)

2015-08-28 21:07 633 查看
------- android培训java培训、期待与您交流! ----------

5.转换流

字符转换流要用到的情况:字节流转换为字符流,字符流转换为字节流。或者需要流编码转换,使用其他流的功能的时候,可以使用字符转换流。

字节流转换成字符流:

InputStreamReader(InputStream in,String charsetName):构造方法可以看出字节转换成字符流时可以指定一个字符集,字节流可以按指定字符集解码。当不填入字符集时则使用系统默认的字符集。
OutputStreamWriter(OutputStream out,String charsetName): 将字符转换成字节,编码,同样可以按照指定的字符集编码。

当想要使用字符流中的方法时,也可以将字节流转换成字符流,比如在BufferedReader中有一个readline方法,而在字节输入流中没有这个方法。这种情况常见于控制台输入。

下面是一个控制台输入后转换成字符流输出的例子

import java.io.*;
import java.util.*;

/**
* 需求,定义一个学生类,包括学生名字,英语,数学,语文三门科目成绩
* 		从键盘接受学生的属性,并按照总成绩排序记录在硬盘中
*
* 思路:从硬盘接受学生属性,即字节输入流转换为字符输出流保存在硬盘文件中
* 		按成绩排序且不包括重复数据,就要使用到TreeSet
*
*
* 		输入流				输出流
* 		System.in			FileWriter
* */
class student_IOPrt implements Comparable<student_IOPrt>
{
private String name;
private	int ma;
private int cn;
private int en;
private int num;
student_IOPrt(String name,int ma,int cn,int en)
{
this.name=name;
this.ma=ma;
this.cn=cn;
this.en=en;
num=ma+cn+en;
}

public String getName()
{
return name;
}
public int getCount()
{
return num;
}

public String toString()
{
return "[student:"+name+"  "+ma+","+cn+","+en+"\tcount:"+num+"]";
}

public int compareTo(student_IOPrt o) {

if(o.num==this.num)
{
//if(stu.name.compareTo(this.name))
return o.name.compareTo(this.name);
}
return o.num-this.num;
}
}
class MyCompareator implements Comparator<student_IOPrt>
{
public int compare(student_IOPrt o1,student_IOPrt o2)
{
if(o1.getCount()==o2.getCount())
{
//if(stu.name.compareTo(this.name))
return o1.getName().compareTo(o2.getName());
}
return o1.getCount()-o2.getCount();
}

}
public class IOStreamPrt {

public static void main(String[] args) throws IOException
{
//建立TreeSet集合用于存储student对象
TreeSet<student_IOPrt> ts = new TreeSet<student_IOPrt>(Collections.reverseOrder(new MyCompareator()));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//字节流转换成字符流输入,然后使用读一行的方法加快效率

String line = null;

while((line=br.readLine())!=null)//读取每一行输入并转换成student对象存入集合
{

if("over".equals(line))
break;
String[] arr = line.split(",");
student_IOPrt stu = new student_IOPrt(arr[0],
Integer.parseInt(arr[1]),
Integer.parseInt(arr[2]),
Integer.parseInt(arr[3]));
ts.add(stu);
}

//写入文件
BufferedWriter bos = new BufferedWriter(new FileWriter("F:\\学习\\java\\IOPRT.txt"));

for(student_IOPrt stus : ts)
{
bos.write(stus.toString());
bos.newLine();
bos.flush();
}

br.close();
bos.close();
}

}


6.SequenceInputStream串联流。

SequenceInputStream表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

从SequenceInputStream的构造函数public SequenceInputStream(Enumeration<? extends InputStream> e)可以看出SequenceInputStream在对象初始化的时候必须要有一个包含输入流的枚举对象。

这个对象一般用于多个流按顺序输入。

文件合并的例子可以很好的说明这个流的使用

import java.io.*;
import java.util.*;

/**
* 需求:把三份文件组合成一份
*
* 思路:把文件从三份组合成一份就需要用到流的合并。流的合并需要用到SequenceInputStream
*
* 源 硬盘文件							目的						硬盘文件
* 输入流对象 FileInputStream-----> SequenceInputStream--->	输出流对象 FileOutputStream
* 输入流对象 FileInputStream-|
* 输入流对象 FileInputStream-|
* */
public class Div_Con_Files {

public static void main(String[] args) throws IOException
{
// TODO Auto-generated method stub
conFiles();

}

public static void conFiles() throws IOException//将多个文件组合成一个文件
{

int part = 1;
ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();
while(part<=4)//将全部的文件都写入输入流并保存在ArrayList中
{
File file = new File("F:\\学习\\java\\"+(part++)+".part");
al.add(new FileInputStream(file));
}

//建立一个枚举对象(匿名内部类),该枚举对象的枚举内容即全部的源文件的输入流
//这个枚举对象用于传递给SequenceInputStream
Iterator<FileInputStream> it=al.iterator();
Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};

//建立输出流
File file = new File("F:\\学习\\java\\success.png");
FileOutputStream fos=new FileOutputStream(file);

//建立SequenceInputStream将所有输入流会合输入
SequenceInputStream sis=new SequenceInputStream(en);
int len=0;
byte[] by=new byte[1024*1024];
while((len=sis.read(by))!=-1)
{
fos.write(by, 0, len);//输出流写入文件
}

fos.close();
sis.close();
}

}


7.输入输出流使用对象规律

在编程中输入输出流对应的源和目的很多,往往让人搞不清使用哪个流对象。

确定使用的流对象可以按以下几步来确定:

1.确定使用的流体系:

字节流 字符流

输入流 InputStream
Reader

输出流 OutputStream
Writer

按照是否需要操作本文和流向来判断使用哪一个流体系。

需要操作本文则使用字符流,不需要则使用字节流。

2.确定流对象对应的源和目的。

源:内存,硬盘文件,键盘输入,其他源。

目的:内存,硬盘文件,控制台,其他目的。

当源是内存中的数据的时候则看使用的流体系能操作的数据类型,比如字节流只能操作char以及char数组,而字符流还可以操作String或String类型的数组。

当源是硬盘文件的时候则使用File类,键盘输入的时候则使用System.in

总结源和目的使用的输入输出流对象如下:

源 内存 硬盘文件
键盘输入 网络

File System.in
Socket

目的 内存 硬盘文件
控制台 网络

File System.out
Socket

3.确定是否需要提高效率或使用增强功能

提高效率或使用增强功能可以使用包装流,这类流有4个

BufferedInputStream BufferedReader

BufferedOutputStream BufferedWriter

分别对应字节输入流,字符输入流,字节输出流和字符输出流。

4.是否需要使用转换流

转换流一般涉及到编码转换或者使用转换后的流对象能加快效率时使用

import java.io.*;

/**
* 需求:从键盘输入多行行字符,以over结束,并将其保存在F盘下,命名为ioprt01.txt
*
*
* 思路:确定输入输出:输入,键盘,字节流,使用InputStream体系
* 			输出,硬盘本文文件,字符流,使用Writer体系
* 			输入使用System.in,提高效率使用BufferedInputStream
* 			输出使用FileWriter类,提高效率使用BufferedWriter
* 			由输入到输出需要体系转换,所以使用InputStreamReader
*
*
* */
public class IOprt01 {

public static void main(String[] args) throws IOException
{
BufferedReader bfr = new BufferedReader (new InputStreamReader(System.in));
BufferedWriter bfw = new BufferedWriter(new FileWriter("F:\\ioprt01.txt"));

String str="";
while((str=bfr.readLine())!=null)//当读到的内容不为空
{
if(str.equals("over"))//当读到的内容为over时结束
break;
bfw.write(str);
bfw.newLine();
bfw.flush();
}
bfr.close();
bfw.close();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: