一、数据流的基本概念
数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。对数据读取程序来说,看不到数据流在写入时的分段情况,每次可以读取其中的任意长度的数据,但只能先读取前面的数据后,再读取后面的数据。不管写入时是将数据分多次写入,还是作为一个整体一次写入,读取时的效果都是完全一样的。
在电脑上的数据有三种存储方式,一种是外存,一种是内存,一种是缓存。比如电脑上的硬盘,磁盘,U盘等都是外存,在电脑上有内存条,缓存是在CPU里面的。外存的存储量最大,其次是内存,最后是缓存,但是外存的数据的读取最慢,其次是内存,缓存最快。这里总结从外存读取数据到内存以及将数据从内存写到外存中。对于内存和外存的理解,我们可以简单的理解为容器,即外存是一个容器,内存又是另外一个容器。那又怎样把放在外存这个容器内的数据读取到内存这个容器以及怎么把内存这个容器里的数据存到外存中呢?
java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。将数据冲外存中读取到内存中的称为输入流,将数据从内存写入外存中的称为输出流。
流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。
二、流的分类
按照数据流的方向分为:输入流(Input), 输出流(Output)
输入流: 从文件往程序走数据
输出流: 从程序往文件走数据
按照处理数据的单位不同:
八大数据类型所占字节数:
byte(1), short(2), int(4), long(8)
float(4), double(8)
boolean(1)
char(2)
字节流(以stream结尾的), 字符流(以Reader, Writer结尾的)
字节流: 一个字节占8位, 以一个字节为单位读数据
字符流: 一个字符占两个字节, 以一个字符为一个单位
按照功能分:节点流, 处理流
节点流: 只有一个根管道套在文件上进行传输
处理流: 将节点流处理一下, 增强管道的功能, 相当于在管道上套一层
三、细说流
JDK提供的流:提供了四个基本抽象类: InputStream, OutputStream, Reader, Writer
InputStream的基本方法:
int read(): 每次调用这个方法, 就读取一个字节, 以整数的形式返回
int read(byte[] buffer---缓冲区): 让流每次读满一个缓冲区, 再统一处理, 先存在缓冲区里, 返回值int是返回实际当中读取了多少字节数(伤硬盘的原理)
int read(byte[] buffer, int offset, int length): 也是一个缓冲区, 读取length长度的字节数, 存到buffer的缓冲区里, 从buffer的offset位置开始存, 返回值是实际读了多少字节数
close(): 关闭资源
OutputStream的基本方法:
void write(int b)
void write(byte[] b)
int wirte(byte[] buffer, int offset, int length)
close()
flush(): 将缓冲区中的文件全部写出
在使用流的时候的一个良好的习惯, 先flush, 再close
举例1:字节输入流InputStream
package com.hanqi.maya.util;
/**
* 读取一个文件中的内容(文件中不包括汉字,因为一个汉字占两个字节),用InputStream和FileInputStream
* 字节输入流InputStream(抽象类,不能实例化)
* 文件输入流FileInputStream(为了去实现抽象类InputStream)
*
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class InputStreamText {
public static void main(String[] args) {
File file = new File("D:\\0603.txt");
try {
InputStream in = new FileInputStream(file); //InputStream类是字节输入流的抽象类,抽象类不能实例化;这里用多态来实现
int a ; //因为in.read()的返回值为0~255范围内的int字节值,所以这里定义一个整型变量a
//in.read()为从输入流中读取数据的下一个字节,判断是否到结尾,如果没有,依次输出;如果因为已经到达流末尾而没有可用的字节,则返回值-1
while((a = in.read()) != -1){
System.out.print((char)a); //(char)a,这里强转,把整型变量a强转为 字符变量
}
in.close(); //记着流需要关闭
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
举例2:字节输出流OutputStream
package com.hanqi.maya.util;
/**
* 输出流主要是用来把某个文件输出到指定位置上的
* 字节输出流OutputStream(抽象类,不能实例化)
* 文件输出流FileOutputStream(为了去实现抽象类OutputStream)
*
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class OutputStreamText {
public static void main(String[] args) {
File file = new File("D:\\0603.txt"); //原文件
File file_out = new File("E:\\汉企课程学习课件\\汉企二期课程JAVA学习课件\\0731 文件类 流\\abc.txt");//指定输出位置
try {
InputStream in = new FileInputStream(file);
OutputStream out = new FileOutputStream(file_out);
int a;
while((a = in.read()) != -1){
out.write(a); //这里注意与输入流的区别
}
in.close();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Reader的基本方法:
int read()
int read(char[] c)
int read(char[] c, int offset, int length)
close()
Writer的基本方法:
void write()
void write(char[] c)
void write(char[] c, int offset, int length)
void write(String s)
void write(String s, int offset, int length)
close()
flush()
举例:
package com.hanqi.maya.util;
/**
* 读取一个文件中的内容(文件中同时包括汉字,因为一个汉字占两个字节),用Reader、FileReader和BufferedReader
*
* Reader类是字符输入流的抽象类(抽象类,不能实例化)
* FileReader流顺序的读取文件,只要不关闭流,每次调用read()方法就顺序的读取源中其余的内容,直到源的末尾或流关闭。
*
* File file = new File("D:\\0603.txt");
* Reader r = new FileReader(file);
* 通过以上两部来实现Reader抽象类
*
* BufferedReader,带缓冲区的字符流,实际就是一个处理流
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class FileText {
public static void main(String[] args) {
File file = new File("D:\\0603.txt");
Reader r; //Reader类是字符输入流的抽象类
try {
r = new FileReader(file);
//FileReader流顺序的读取文件,只要不关闭流,每次调用read()方法就顺序的读取源中其余的内容,直到源的末尾或流关闭。
BufferedReader br = new BufferedReader(r);//BufferedReader,带缓冲区的字符流,实际就是一个处理流
String s;
while((s = br.readLine()) != null){
//br.readLine()方法:读取一个文本行,并将其返回为字符串;若无数据可读,则返回null。
System.out.println(s);
}
br.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}