目录
一.字节、字符流
1.字节流
字节流,用于操作字节文件(视频、音频、docx文档等),分为输入流和输出流,如下代码中:
第10、11行:定义输入流和输入流变量。
第13、14行:创建输入流和输出流对象,这里要注意,输入流对象的构造方法传入的既可以是File类对象,也可以直接传入目标文件路径的字符串,这里就直接将路径传入了。
第16行:因为操作的是字节文件,所以读取到的都是数字,这里定义一个byte类型的长度为1024的数组,因为如果在流中一个一个的传输数据,效率会非常的低,而定义了这个数组之后,可以在流中一次传输1024个数据,大大提高了传输的效率。但这里要注意的是,数组的长度不能设置的过大,因为计算机的运行内存是有限的,所以如果一次传输的量过大的话对计算机不利。
第17行:定义一个int类型变量来记录car数组中数据的个数,因为假如最后一趟传输的数组中只有一个数据,但是输出流并不知道数组中数据的长度,这时输出流需要在该数组中读取1023个0。
第18行:输入流调用read方法利用数组car对目标文件进行传输。这里要注意,该方法返回值即为数组中装载的数据的个数,将其直接赋值给length即可,且当数据传输完毕后,会返回-1,所以可以用来判断传输是否结束作为循环条件。
第19行:输出流调用write()方法将传输过来的car数组中的数据进行输出,该方法传入的第二个参数是指从数组的第几个元素进行输出。
第21行:该方法用于刷新字符输出流缓冲。这就好比用导管导水的时候,会有部分水沾在导管壁上,输出流也是如此,传输过后可能会有部分数据在流中而未传输到目标文件中,flush()方法的作用就是将输出流中残留的数据传入到目标文件中。
第25行:关闭输入流和输出流。这里要说一点,释放资源的顺序无限制。
package earth;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
FileInputStream fileInputStream =null;
FileOutputStream fileOutputStream=null;
try {
fileInputStream = new FileInputStream("D:\\Program_Files\\useful\\笔记\\4、作业.wmv");
fileOutputStream = new FileOutputStream("D:\\Program_Files\\1.wmv");
byte [] car= new byte[1024];
int length=0;
while((length=fileInputStream.read(car))!=-1) {
fileOutputStream.write(car,0,length);
}
fileOutputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
if(fileInputStream!=null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileOutputStream!=null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.字符流
字符流是用于操作字符文件(如记事本)的IO,大体上与字节流是一样的,代码如下:
第14、15行:字符流创建对象使用的是FileReader和FileWriter。
第17行:字符文件中数据都是以字符形式存储的,所以读取出来的数据自然要用char类型数组来传输。
第19行:对输入流中传输的数据进行遍历,与字节流原理相同。
第22行:输出流调用flush方法,与字节流原理相同。
package earth;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
FileReader fileReader =null;
FileWriter fileWriter =null;
try {
fileReader = new FileReader("D:\\Program_Files\\useful\\123.txt");
fileWriter = new FileWriter("D:\\Program_Files\\1.txt");
char [] car=new char[1024];
int length= 0;
while((length=fileReader.read(car))!=-1) {
fileWriter.write(car,0,length);
}
fileWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
if(fileReader!=null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileWriter!=null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
二.缓冲流
无论是字符流还是字节流,在输入的时候都需要从磁盘上读取数据放到数组中,输出的时候都需要将数组送入磁盘中,这便大大的影响了传输效率,为了进一步提高传输的效率,这里使用了缓冲流,其原理是在磁盘外建立一个缓冲区,输入的时候将一部分数据自动从磁盘放入缓冲区中,然后数组只需要从缓冲区中获取数据即可;输出的时候数组也是只需要将数据输出到缓冲区即可,缓冲区再自动将数据存入磁盘。
下面是缓冲字符流的代码示例,缓冲字节流原理与其相似就不做举例了:
第16、17行:创建缓冲字符输入流对象和缓冲字符输出流对象,这里要注意,该对象创建的时候调用的构造方法,传入的参数必须是字符流类型(FileReader和FileWriter)。
第21行:对输入流中传输的数据进行遍历,与字符流原理相同。
第24行:输出流调用flush方法,与字符流原理相同。
第28行:对缓冲流对象进行资源释放。
package earth;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
BufferedReader bufferedReader=null;
BufferedWriter bufferedWriter=null;
try {
bufferedReader = new BufferedReader(new FileReader("D:\\Program_Files\\useful\\123.txt"));
bufferedWriter = new BufferedWriter(new FileWriter("D:\\Program_Files\\1.txt"));
char [] car = new char[1024];
int length = 0;
while((length=bufferedReader.read(car))!=-1) {
bufferedWriter.write(car,0,length);
}
bufferedWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
if(bufferedReader!=null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bufferedWriter!=null) {
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
我们来看一下运行结果,这是useful目录下的123.txt文件:
但是再来看一下Program_Files目录下的1.txt文件,打印结果是一堆乱码:
这便是编码的格式不同而产生的乱码,要解决这个问题就需要使用下一种要说的流了。
三.转换流
第13行:创建字符转换输入流对象,该类的构造方法中第一个参数还是字符流的对象,第二个参数是读取目标文件使用的编码类型,这里我们使用UTF-8编码来读取。
第14行:创建字符转换输出流对象,第二个参数传入的是输出目标文件使用的编码类型,这里要注意,输入流的编码类型一定要和输出流的编码类型相同。
其余的都不做改动。
package earth;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Test {
public static void main(String[] args) {
try {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("D:\\Program_Files\\useful\\123.txt"),"UTF-8");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("D:\\Program_Files\\1.txt"),"UTF-8");
char [] car=new char[1024];
int length = 0;
while((length=inputStreamReader.read(car))!=-1) {
outputStreamWriter.write(car,0,length);
}
outputStreamWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
但是要注意,使用转换流的时候不仅要保证输入流和输出流的编码类型相同,还要保证所读取的文件的编码类型与读取的类型相同:
四.数据流
以上三种流都是传输文件使用的,但如果想从程序中向文件中传输数据,这时就需要使用数据流了:
第12行:定义一个double类型数据待写入。
第14行:创建一个数据输出流对象,构造方法传入的参数为字节流对象。
第15行:输出流对象调用writeDouble方法输出double类型数据,输出什么类型数据就是用writeXXX方法。
第16行:任何流都需要对输出流进行flush,数据流也不例外。
第22行:创建一个数据输入流对象,构造方法传入的参数为字节流对象。
第23行:输入流调用readXXX方法从文件中读取相应数据类型的数据,这里使用的是readDouble()。
package earth;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Test {
public static void main(String[] args) {
double price=9.9;
try {
DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("D:\\data.temp"));
dataOutputStream.writeDouble(price);
dataOutputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
try {
DataInputStream dataInputStream = new DataInputStream(new FileInputStream("D:\\data.temp"));
double p=dataInputStream.readDouble();
System.out.println(p);
} catch (Exception e) {
e.printStackTrace();
}
}
}