流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
流的分类:按照处理的数据不同,分为字节流和字符流。字节流是以byte为底层数据的,而字符流则是以Char为单位。还有一种Object流,可以用于传递对象。
流的用途:字符流一般是用于处理文字类相关的需要按照字符映射表来编码的数据,如txt格式文本。而字节流则能处理所有的数据,如图片,mp3等。
流向:分为Input (reader) 和output(writer),输入输出流。输入流是用于程序获取数据。而输出流则是用于对外输出数据。
命名: 字符流都以reader ,writer 为结尾。字节流都以InputStream,或OutputStream为结尾。这些结尾都表面了流的流向。 流向前的名词表示了此流的特殊用途。
如PipedReader是用于管道的字符输入流。ObjectOutputStream是用于Object的输出字节流。Buffered代表着是一个缓冲器
基类:Reader和Writer是所有字符流的抽象基类。InputStream和OutputStream是所有字节流的超类。不论什么流,它的最基础都是相同的,InputStream,OutputStream。
所以很多Io类都是装饰器类,是以InputStream,InputStream为基础,(如果是字符流还需要转换),是对基础流的增强。
转换:InputStreamReader将字节流转换成字符流。OutputStreamWriter将字符流转换成字节流。这两者是字节流和字符流之间的桥梁。编码只适用于程序内部,在外部都算是字节流。所以输入的时候才需要将字节转字符,输出的时候才需要字符转字节。
缓冲:缓冲器是一个装饰器,通过调用传入的流对象的方法来增加缓冲的功能。BufferedWriter ,BufferedReader,BufferedOutputStream,BufferedInputStream分别对应于4种不同的缓冲装饰器。
已经用过的:
1.控制台输入 ----BufferReader(new InputStreamReader(System.in))
当时想了好久都没想起来 思路应该是---首先是字符,所以read,需要缓冲以便自动缓冲,所以需要buffer
其次,由于他是一个包装类,所以还需要一个对象,这个对象应该也是reader,所以使用 InputStreamReader,从字符流装饰成缓冲流
最后InputStreamReader也是一个字节到字符的桥梁,需要最底层的字节流,所以需要一个InputStream类型的实体(System)。
控制台输输出---System.out 的类型为PrinterStream;称为打印流,主要是重载了相当多的类型,对于未知类型,会间接调用其toString方法。PrinterStream是以OutputStream为基础,继承了FilterOutputStream,实现了特有的过滤性输出流的方法。System.out则是一个PrinterStream的实例对象。
public static void main(String[] args) throws IOException {
// 字符读取流
BufferedReader strin = new BufferedReader(new InputStreamReader(
System.in));
String str = "";
while (true) {
//读取
str = strin.readLine();
if(str.equals("quit"))
break;
System.out.println(str);
}
}
2.文件输入---FileReader(file),这是一个用来读取字符文件的便捷类,它使用file创建一个FileInputStream作为其底层字节流,通过继承InputStreamReader将FileIputStream传递给父类来将字节流转换成字符流输入。
文件输出---FileWriter(file)用来写入字符文件的便捷类,它使用file创建一个FileOutputStream作为其底层字节流,通过继承OutputStreamWriter将FileOutputStream传递给父类来将字符流转换成字字节流输出。
public static void main(String[] args) throws IOException{
FileReader fr=null;
try{
fr=new FileReader("file");
char[] cbuf=new char[1024];
int length=0;
while((length=fr.read(cbuf))>0){
System.out.println(new String(cbuf,0,length));
}
}
catch(IOException ioe){
ioe.printStackTrace();
}
finally{
if(fr!=null){
fr.close();
}
}
}
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">3.object</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">---要求对象已经序列化,ObjectInputStream ois=new ObjectInputStream(</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">new</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">Fileout</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">putStream(</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">"file"</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">)</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">);从字节流转换成oject流,如一般保存持久数据使用</span>
ObjectInputStream ois=new ObjectInputStream(newFileInputStream("file"));
底层是字节输入输入流,用于持久数据的读取和保存。
try {
/** 保存本地记录 **/
ObjectOutputStream os= new ObjectOutputStream(new FileOutputStream(SAVE_PATH));
os.writeObject(players);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
//未使用过的
4.管道流 ---这是一种程序内部使用的流,通过输入管道的数据可以在输出管道获得,当然:前提是管道已经相连。这种流主要是用于线程间传输数据使用的。
public static void main(String[] args) throws Exception {
PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis = new PipedInputStream(pos);
for (int i = 0; i < 100; i++) {
pos.write((byte) i);
}
int j = 0;
while ((j = pis.read()) != -1){
System.out.println(j);
}
pos.close();
pis.close();
}