首先,流是什么?
流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以“流”的方式进行。设备可以是文件,网络,内存等。
流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的流向是程序至设备,我们成为输出流,反之我们称为输入流。
可以将流想象成一个“水流管道”,水流就在这管道中形成了,自然就出现了方向的概念。
当程序需要从某个数据源读入数据的时候,就会开启一个输入流,数据源可以是文件、内存或网络等等。相反地,需要写出数据到某个数据源目的地的时候,也会开启一个输出流,这个数据源目的地也可以是文件、内存或网络等等。
流有哪些分类?
可以从不同的角度对流进行分类:
1. 处理的数据单位不同,可分为:字符流,字节流
2.数据流方向不同,可分为:输入流,输出流
3.功能不同,可分为:节点流,处理流
1. 和 2. 都比较好理解,对于根据功能分类的,可以这么理解:
节点流:节点流从一个特定的数据源读写数据。即节点流是直接操作文件,网络等的流,例如FileInputStream和FileOutputStream,他们直接从文件中读取或往文件中写入字节流。
处理流:“连接”在已存在的流(节点流或处理流)之上通过对数据的处理为程序提供更为强大的读写功能。过滤流是使用一个已经存在的输入流或输出流连接创建的,过滤流就是对节点流进行一系列的包装。例如BufferedInputStream和BufferedOutputStream,使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率,以及DataInputStream和DataOutputStream,使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。他们都属于过滤流。
下面是一些简单示例:
字节流字节读取文件大小为34.5M文件
public static void main(String[] args) throws Exception{
Date a = new Date();
InputStream inputStream = new FileInputStream(new File("D:/ioTest/kugou.exe"));
int aa =0;
while (inputStream.read() !=-1) {
aa++;
}
System.out.println(aa);
System.out.println(new Date().getTime() - a.getTime());
}
输出结果分别为:36256832读取次数和字节数完全相同,耗时144840ms,电脑差了点
文件字节流操作
public static void main(String[] args) throws Exception{
//FileInputStream是用来读取文件的,如果文件不存在会报ClassNotFoundException
InputStream inputStream = new FileInputStream(new File("D:/ioTest/kugou.exe"));
//FileOutputStream是用来输出文件的
OutputStream outputStream = new FileOutputStream(new File("D:/ioTest/kugouC.exe"));
byte[] buffer = new byte[512];
int a = 0;
//a是表示读取到的字节数,是用来防止输入流中最后长度不够buffer的长度的,read(byte【】)表示一次性最多读取
//该数组长度的字节
while((a=inputStream.read(buffer)) !=-1){
//输出
outputStream.write(buffer, 0, a);
}
inputStream.close();
outputStream.close();
}
File操作
public static void main(String[] args) throws Exception{
//创建一个文件,该文件不会立刻生成
File file = new File("D:/haha.txt");
//立刻生成该文件
file.createNewFile();
//判断该文件是否存在
System.out.println(file.exists());
//判断该文件是不是文件夹
System.out.println(file.isDirectory());
//立刻生成该文件夹(不过好像有同名的文件的话,该文件夹不会生成)
file.mkdir();
//判断该文件是否存在
System.out.println(file.exists());
//判断该文件是不是文件夹
System.out.println(file.isDirectory());
//经验证,一个file不管是创建了文件,还是创建了文件夹,只会有一个创建
}
写入读取类,该类必须实现Serializable接口,该接口只是一个标记,但是是必不可少的。
public static void main(String[] args) throws Exception{
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:/ioTest/student.txt"));
outputStream.writeObject(new Student("aa", 11));
outputStream.writeObject(new Student("bb", 12));
outputStream.writeObject(new Student("cc", 13));
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:/ioTest/student.txt"));
for(int i=0;i<3;i++){
System.out.println(inputStream.readObject());
}
}
}
//将对象序列化
public static byte[] toBytes(Object object) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch(IOException ex) {
throw new RuntimeException(ex.getMessage(), ex);
} finally {
try {
oos.close();
} catch (Exception e) {}
}
}
//序列化成对象
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(bais);
Object object = ois.readObject();
return object;
} catch(IOException ex) {
throw new RuntimeException(ex.getMessage(), ex);
} catch(ClassNotFoundException ex) {
throw new RuntimeException(ex.getMessage(), ex);
} finally {
try {
ois.close();
} catch (Exception e) {}
}
}
回退流作用就是在读取输入流的时候遇到不需要的还给退还给输入流
public static void main(String[] args) throws Exception{
String s ="www.bukengnidiankeshuidian.com";
ByteArrayInputStream ba = new ByteArrayInputStream(s.getBytes());
PushbackInputStream push = new PushbackInputStream(ba);
int a = 0;
while((a = push.read()) != -1){
if(a == '.'){
push.unread(a);
//如果该行,不写,程序会在这里无限循环,一直打印“回退的”
a=push.read();
System.out.println("回退的"+a);
}else{
System.out.println(a);
}
}
}