一、流的概念
java将IO比喻为"流",即:stream. 就像生活中的"电流","水流"一样,它是以同一个方向顺序移动的过程.只不过这里流动的是字节(2进制数据).所以在IO中有输入流和输出流之分,我们理解他们是连接程序与另一端的"管道",用于获取或发送数据到另一端.。
java io可以让我们用标准的读写操作来完成对不同设备的读写数据工作.
java将IO按照方向划分为输入与输出,参照点是我们写的程序.
输入:用来读取数据的,是从外界到程序的方向,用于获取数据.
输出:用来写出数据的,是从程序到外界的方向,用于发送数据.
二、Java定义了两个超类(抽象类):
java.io.InputStream:所有字节输入流的超类,其中定义了读取数据的方法.因此将来不管读取的是什么设备(连接该设备的流)都有这些读取的方法,因此我们可以用相同的方法读取不同设备中的数据
java.io.OutputStream:所有字节输出流的超类,其中定义了写出数据的方法.
java将流分为两类:节点流与处理流:
节点流:也称为低级流.节点流的另一端是明确的,是实际读写数据的流,读写一定是建立在节点流基础上进行的.
处理流:也称为高级流.处理流不能独立存在,必须连接在其他流上,目的是当数据流经当前流时对数据进行加工处理来简化我们对数据的该操作.
三、文件流
文件流是一对低级流,用于读写文件数据的流.用于连接程序与文件(硬盘)的"管道".负责读写文件数据.。
java.io.FileInputStream和java.io.FileOutputStream,作用是真实连接我们程序和文件之间的"管道"。其中文件输入流用于从文件中读取字节。而文件输出流则用于向文件中写入字节。
文件流是节点流
JAVA IO将流划分为两类:节点流和处理流
节点流:俗称"低级流",特点:
1.真实连接我们程序和另一端的"管道",负责实际读写数据的流
2.文件流就是典型的节点流,真实连接我们程序与文件的"管道",可以读写文件数据了。
处理流:俗称"高级流"
特点:
1:不能独立存在(单独实例化进行读写操作不可以)
2:必须连接在其他流上,目的是当数据"流经"当前流时,可以对其做某种加工操作,简化我们的工作、流的连接:实际开发中经常会串联一组高级流最终到某个低级流上,对数据进行流水线式的加工读写。
1.文件输入流(FileInputStream)
import java.io.*;
class FIODemo{
public static void main(String[] args){
FileInputStream fis = new FileInputStream(./fos.dat);
//fos.dat文件中有几个数据就有几个字节
int d = fis.read();
System.out.println(d);//输入-1时会返回11111111,转成十进制就是255
d = fis.read();
System.out.println(d);//读到最后时会返回-1
}
}
2.文件输出流(FileOutputStream)
class FOSDemo{
public static void main(String[] args){
FileOutputStream fos = new FileOutputStream("./fos.dat");
// File file = new File("./fos.dat");
// FileOutputStream fos = new FileOutputStream(file);
fos.write(-1);//写入1个字节(二进制的低八位)
fos.write(-2);//写入两个字节
fos.write(256);
System.out.println("写出完毕");
fos.close();//关闭流,释放底层资源
}
}
注:在指定相对路径时,如果是从"当前目录"(./)开始的,那么"./"是可以忽略不写的,因为在相对路径中,默认就是从"./"开始
四、文件复制
public class CopyDemo {
public static void main(String[] args) throws IOException{
//输入流
FileInputStream fis = new FileInputStream("./fos.txt");
//输出流
FileOutputStream fos = new FileOutputStream("./fos_copy.txt");
int b = 0;
long start = System.currentTimeMillis();
while( (b=fis.read())!=-1 ){ //只要读不到-1就会一直执行下去
fos.write(b);
}
System.out.println("复制完毕");
long end = System.currentTimeMillis();
System.out.println((end-start)+"ms");//获取程序执行时间
fis.close();
fos.close();
}
}
-块读写的文件复制:
int read(byte[] data) 一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。 返回值为实际读取到的字节量。若返回值为-1则表示读取到了文件末尾。
块写操作 void write(byte[] data) 一次性将给定的字节数组所有字节写入到文件中。
void write(byte[] data,int offset,int len) 一次性将给定的字节数组从下标offset处开始的连续len个字节写入文件。
class CopyDemo{ public static void main(String[] args){ FileInputStream fis = new FileInputStream("./被复制文件名"); FileOutputStream fos = new FileOutputStream("./复制后的文件名"); int d = 0; //如果不用块读写文件的话会有多余的数据装入文件中(脏数据) byte[] data = new byte[1024*10];//将10kb大小的的块装入byte[]中 while((d=fis.read())!=-1){ fos.write(data,0,d);//从data中写入0,到d的数据量 } fis.close; fos.close; } }
五、写文本数据
String提供方法: byte[] getBytes(String charsetName) 将当前字符串转换为一组字节
参数为字符集的名字,常用的是UTF-8。 其中中文字3字节表示1个,英文1字节表示1个。
public class WriteStringDemo { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("fos.txt");//默认,重新写入会覆盖 FileOutputStream fos = new FileOutputStream("fos.txt",true);//追加写入 String line = "学习io"; byte[] data = line.getBytes(StandardCharsets.UTF_8); fos.write(data); line = "学习java"; data = line.getBytes(StandardCharsets.UTF_8); fos.write(data); System.out.println("写出完毕!"); fos.close(); } }
六、读文本数据
import java.io.*;
class ReadStringDemo{
public void static main(String[] args) throws IOException{
File file = new File("./demo.txt");
FileOutStream fis = new FileOutStream(file);
long len = file.length();
byte[] data = new byte[(int)len];//根据文件大小创建等长的字节数组
fis.read(data);//块读取,一次性将文件所有数据读取到字节数组中
//利用String的构造器,将字节数组中所有内容按照指定的UTF-8字符集还原为字符串
String line = new String(data,StandardCharsets.UTF_8);
System.out.printn(line);
fis.close;
}
}
七、流
java将流分为节点流与处理流两类:
节点流:也称为低级流
<1是真实连接程序与另一端的"管道",负责实际读写数据的流。
<2读写一定是建立在节点流的基础上进行的。
<3节点流好比家里的"自来水管"。连接我们的家庭与自来水厂,负责搬运水。
处理流:也称为高级流,
<1不能独立存在,必须连接在其他流上,目的是当数据经过当前流时对其进行某种加工处理,简化我们对数据的同等操作。
<2高级流好比家里常见的对水做加工的设备,比如"净水器","热水器"。有了它们我们就不必再自己对水进行加工了。
1.缓冲流
java.io.BufferedOutputStream和BufferedInputStream.
缓冲流是一对高级流,作用是提高读写数据的效率。(搭配使用)
缓冲流内部有一个字节数组,默认长度是8K.缓冲流读写数据时一定是将数据的读写方式转换为块读写来保证读写效率。通过缓冲流写出的数据会被临时存入缓冲流内部的字节数组,直到数组存满数据才会真实写出一次 。 缓冲流的flush()方法用于强制将缓冲区中已经缓存的数据一次性写出。
FileInputStream fis = new FileInputStream("ppt.pptx"); BufferedInputStream bis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream("ppt_cp.pptx"); BufferedOutputStream bos = new BufferedOutputStream(fos); int d; long start = System.currentTimeMillis(); while((d = bis.read())!=-1){//使用缓冲流读取字节 bos.write(d);//使用缓冲流写出字节 } long end = System.currentTimeMillis(); System.out.println("耗时:"+(end-start)+"ms"); bis.close();//关闭流时只需要关闭高级流即可,它会自动关闭它连接的流 bos.close(); ------------------------------------------------------------------- FileOutputStream fos = new FileOutputStream("bos.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); String line = "奥里给!"; byte[] data = line.getBytes(StandardCharsets.UTF_8); bos.write(data); System.out.println("写出完毕!"); bos.flush();//刷新 bos.close();
2. 对象流
java.io.ObjectOutputStream和ObjectInputSteam
对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化。
对象序列化:将一个java对象按照其结构转换为一组字节的过程
对象反序列化:将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节,反序列化也就是将写出的对象按照其结构转换为一组字节的过程。)//对象序列化 String name = "苍老师"; int age = 55; String gender = "男"; String[] otherInfo = {"摄影技术一流","是一名技术老师"}; //将该Person对象写入文件person.obj中 Person p = new Person(name,age,gender,otherInfo); FileOutputStream fos = new FileOutputStream("person.obj"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(p); System.out.println("写出完毕!"); oos.close(); -------------------------------------------------------------------------- //反序列化 FileInputStream fis = new FileInputStream("person.obj"); ObjectInputStream ois = new ObjectInputStream(fis); Person p = (Person)ois.readObject(); System.out.println(p);需要进行序列化的类必须实现接口:java.io.Serializable
实现序列化接口后最好主动定义序列化版本号这个常量。 这样一来对象序列化时就不会根据类的结构生成一个版本号,而是使用该固定值。 那么反序列化时,只要还原的对象和当前类的版本号一致就可以进行还原。transient关键字可以修饰属性,用于在进行对象序列化时忽略不必要的属性,达到对象瘦身的目的。
3.字符流(以字符为最小单位(char)读写数据)
java将流按照读写单位划分为字节流与字符流.java.io.InputStream和OutputStream是所有字节流的超类而java.io.Reader和Writer则是所有字符流的超类,
它们和字节流的超类是平级关系.Reader和Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法.字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由字符流完成。
4.转换流
java.io.InputStreamReader和OutputStreamWriter
转换流(是一对高级流,同时是一对字符流)
作用: 1:衔接字节流与其他字符流
2:将字符与字节相互转换FileOutputStream fos = new FileOutputStream("osw.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); //高级流使用必须搭配低级流 String len = "噢噢噢噢噢"; osw.write(len); System.out.println("写出完毕"); osw.close(); -------------------------------------------------------------- //转换字符输入流,可以将读取的字节按照指定的字符集转换为字符 FileInputStream fis = new FileInputStream("./osw.txt"); InputStreamReader isr = new InputStreamReader(fis); int d; while((d=isr.read())!=-1){ System.out.print((char) d); } isr.close();



