一、IO流基本概念
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。 即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
IO流与操作系统建立连接,将数据传过去,这种方式就是流的传递
二、IO流分类
1、根据处理数据类型的不同分类
(1)字节流
(2)字符流
2、根据数据流向不同分类
(1)输入流:只能进行读操作
(2)输出流:只能进行写操作
三、字节流
1、字节输出流 OutputStream
(1)此抽象类是表示输出字节流的所有类的超类,其子类:FileOutputStream
表示字节输出流(写入)。
(2)OutputStream
的方法
① 构造方法:FileOutputStream(File file):
FileOutputStream fos = new FileOutputStream( "d:\\test\\java.txt");
这个构造方法会在指定路径创建指定文件,如上例会在 d:\test 目录下创建 java.txt 文件。
② write()
方法
- write(int b):写入单个数据
- write(byte[ ] b):写入整个字节数组
- write(byte[ ] b,int off , int len) :写入字节数组的某一部分,int off 表示偏移量,int len 是要写入的字节长度。
Demo:
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream( "d:\\test\\java.txt" , true);
// write(int b) 方法
fos.write(99);
// write(byte[] b) 方法
String str = "abcdefg";
byte[ ] b = str.getBytes( );
fos.write(b);
// write(byte[ ] b,int off , int len) 方法
fos.write(b, 1, 3);
fos.close( );
}
}
运行结果为:
cabcdefgbcd
对应代码中三次写入一次为:c abcdefg bcd
③ 追加模式
追加模式顾名思义就是每次写入不覆盖之前的数据,而是以追加形式写在原有数据的末尾,其构造方法为FileOutputStream(String name ,boolean append)
。
当append为true时是追加模式,false时为覆盖模式,不写的时候默认是覆盖模式。
FileOutputStream fos = new FileOutputStream( "d:\\test\\java.txt" , true);
④ close() 方法
close() 方法表示关流,对应代码执行完之后必须关流。
2、字节输入流 InputStream
(1)此抽象类是表示输入字节流的所有类的超类,子类:FileInputStream
表示字节输入流(读取)。
(2)InputStream
的方法
① 构造方法:FileInputStream(String path)
FileInputStream fis = new FileInputStream( "d:\\test\\java.txt");
②read() 方法
- read():读取单个数据
- read(byte[] b):读取整个字节数组
- read(byte[] b,int off,int len):读取字节数组的某一部分数据
如下Demo:
import java.io.FileInputStream;
import java.io.IOException;
public class Demo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream( "d:\\test\\java.txt");
// read() 方法
int read = fis.read( );
System.out.println( read );
byte read1 = (byte) fis.read( );
System.out.println( read1 );
// read(byte[] b) 方法
byte[ ] bytes1 = new byte[3];
int read2 = fis.read( bytes1 );
System.out.println( read2 );
// read(byte[] b,int off,int len) 方法
byte[ ] bytes2 = new byte[3];
int read4 = fis.read(bytes2);
String read3 = new String ( bytes2 , 1 , read4 );
System.out.println( read3 );
//关流
fis.close();
}
}
注意:read() 方法每次读取后会自动往后推移。
3、案例演示
(1)Demo:输入流异常处理
public class Demo1 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("text.txt");
byte[] bytes = new byte[3];
int read = -1;
while((read = fis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, read));
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
try {
if(fis != null) {
fis.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
(2)Demo:字节流完成文件的复制
① 第一种:
public class Copy {
public static void main(String[] args) throws IOException {
//绑定数据源
FileInputStream fis = new FileInputStream("d:\\test1\\demo.txt");
//明确数据输出目的文件夹
FileOutputStream fos = new FileOutputStream("d:\\test2\\demo.txt",true);
int read = -1;
while((read = fis.read()) != -1) {
fos.write(read);
}
fis.close();
fos.close();
}
}
② 第二种:
public class Copy {
public static void main(String[] args) throws IOException {
//绑定数据源
FileInputStream fis = new FileInputStream("d:\\test1\\demo.txt");
//明确数据输出目的文件夹
FileOutputStream fos = new FileOutputStream("d:\\test2\\demo.txt",true);
byte[] bytes = new byte[10];
int read = -1;
while((read = fis.read(bytes)) != -1) {
fos.write(bytes, 0, read);
}
fis.close();
fos.close();
}
}
(3)4、统计一个文件test…Java文件中有多少个字母”a”和”A”的个数
public class CountAa {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\test.java");
BufferedInputStream bis = new BufferedInputStream(fis);
int read = -1;
byte z;
int count = 0;
while((read = bis.read() )!= -1){
if(read == 65 || read == 97){
count++;
}
}
fis.close();
bis.close();
System.out.print("文件中A和a出现的总次数是:"+count);
}
}
四、字符流
1、字符输出流(写出)FileWriter
(1)FileWriter的主要方法
① 构造方法 FileWriter(File file)
FileWriter fw = new FileWriter("d:\\text");
② 字符写入方法
- write(int c):写出单个字符
- write(char[] c):写入整个字符数组
- write(char[] cbuf, int off, int len):写入字符数组的某一部分
Demo1:
public class Demo1 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("d:\\text",true);
//write(int c)
fw.write(99);
fw.write("你好");
//write(char[] c)
char[] ch = {'我', '在', '写', '入', '数', '据'};
fw.write(ch);
//fw.write(cbuf, off, len);
char[] ch1 = {'我', '也','在', '写', '入', '数', '据'};
fw.write(ch1, 1, 3);
//关流
fw.close();
}
}
2、字符输入流(读取) FileReader
(1)FileReader的主要方法 ① 构造方法
FileReader(File file)`
FileReader fr = new FileReader("d:\\text\\demo.txt");
② 读取方法
- read():读取单个字符。
- read(char[] cbuf):读入整个字符数组。
- read(char[] cbuf, int off, int len):读入字符数组的某一部分。
Demo2:
public class Demo2 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("d:\\text\\demo.txt");
char[] ch = new char[3];
int read = -1;
while((read = fr.read()) != -1) {
System.out.println((char)read);
}
fr.close();
}
}
3、案例演示
(1)Demo:字符流完成文件复制
① 第一种
public class Copy {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("d:\\text1\\demo.txt");
FileWriter fw = new FileWriter("d:\\text2\\demo.txt",true);
int read = -1;
while((read = fr.read()) != -1) {
fw.write((char)read);
}
fr.close();
fw.close();
}
}
② 第二种
public class Copy {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("d:\\text1\\demo.txt");
FileWriter fw = new FileWriter("d:\\text2\\demo.txt",true);
char[] ch = new char[3];
int read = -1;
while((read = fr.read(ch)) != -1) {
fw.write(ch);
}
fr.close();
fw.close();
}
}
(2)在D盘下创建一个HelloWorld.txt文件,判断他是文件还是目录,是目录则再创建一个目录IOTest,并将HelloWorld.txt移动到IOTest目录下去,之后遍历IOTest这个目录下的文件。
public class JavaIO {
public static void main(String[] args) throws IOException {
File file = new File("d:\\HelloWorld.txt");
//创建文件
file.createNewFile();
if(file.isFile()) {
File file1 = new File("d:\\IOTest");
//创建文件夹
file1.mkdir();
FileReader fr = new FileReader(file);
FileWriter fw = new FileWriter(file1 + "\\" + file.getName(),true);
int read = -1;
while((read = fr.read()) != -1) {
fw.write(read);
}
findFile(file1);
fw.close();
fr.close();
//删除原路径的HelloWorld.txt文件
file.delete();
}else {
System.out.println(file + "是一个文件目录");
}
}
//递归
public static void findFile(File file) {
File[] files = file.listFiles();
for(File f: files) {
if(f.isDirectory()) {
//输出这个文件夹名,然后递归调用
System.out.println(f);
findFile(f);
}else if(f.isFile()) {
//输出这个文件名
System.out.println(f);
if(f.getName().equals("HelloWorld.txt")) {
}
}
}
}
}
五、转换流
1、InputStreamReader(InputStream,String charsetName)
in 表示字节输入流 charsetName 表示字符编码的名字: utf-8 、gbk utf-8有一个默认bom头文件,占三个字节:?
InputStreamReader
: 字节流通向字符流的桥梁
OutputStreamWriter
: 字符流通向字节流的桥梁
public class Demo1{
public static void main(String[] args) {
FileInputStream fis = null;
InputStreamReader isr = null;
try {
fis = new FileInputStream("D:\\测试\\123.txt");
isr = new InputStreamReader(fis,"UTF-8");
char[] ch = new char[10];
int read = -1;
while ((read = isr.read(ch)) != -1) {
System.out.print(new String(ch, 0, read));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(isr != null) {
isr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2、转换流完成文件的复制
public class Demo2{
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\测试\\123.txt");
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
FileOutputStream fos = new FileOutputStream("D:\\测试\\test1.txt",true);
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
char[] ch = new char[1024];
int read = -1;
while ( ( read = isr.read(ch) ) != -1) {
osw.write(ch, 0, read);
}
osw.close();
isr.close();
isr.close();
fis.close();
}
}
六、缓冲流
1、缓冲字节流
(1)缓冲字节输入流 BufferedInputStream
- 构造方法
BufferedInputStream(InputStream in)
- 读入方法Demo
read(byte[] b, int off, int len)
(2)缓冲字节输出流 BufferedOutputStream
- 构造方法Demo
BufferedOutputStream(OutputStream out)
- 写出方法Demo
write(byte[] b, int off, int len)
- 写出去 默认缓冲大小8kb,8*1024
(3)转换字节流完成文件的复制
public class Test9 {
//转换字节流
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream( "D:\\Test1\\HelloWorld.txt" );
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream( "D:\\Test1\\IOtest\\HelloWorld.txt" );
BufferedOutputStream bos = new BufferedOutputStream(fos);
int read = -1;
while ( ( read = bis.read( ) ) != -1 ) {
bos.write(read);
}
bos.close();
fos.close();
bis.close();
fis.close();
}
}
(4)缓冲流与字节流比较
public class Test1 {
//字节流与缓冲流比较
public static void main(String[] args) throws IOException {
//复制开始时间,下同
long start = System.currentTimeMillis();
//调用copy_1()方法,下同
copy_1( new File ("D:\\Test1\\Test3\\q.zip"), new File("D:\\Test1\\Test3_1\\q.zip"));
//复制结束时间,下同
long end = System.currentTimeMillis();
System.out.println( "耗时1" + ( end - start ) );
long start2 = System.currentTimeMillis();
copy_2( new File ("D:\\Test1\\Test3\\q.zip"), new File("D:\\Test1\\Test3_2\\q.zip"));
long end2 = System.currentTimeMillis();
System.out.println( "耗时" + ( end2 - start2 ) );
long start3 = System.currentTimeMillis();
copy_3( new File ("D:\\Test1\\Test3\\q.zip"), new File("D:\\Test1\\Test3_3\\q.zip"));
long end3 = System.currentTimeMillis();
System.out.println( "耗时" + ( end3 - start3 ) );
long start4 = System.currentTimeMillis();
copy_4( new File ("D:\\Test1\\Test3\\q.zip"), new File("D:\\Test1\\Test3_4\\q.zip"));
long end4 = System.currentTimeMillis();
System.out.println( "耗时" + ( end4 - start4 ) );
}
//不加缓冲:一次读取一个字节
public static void copy_1( File oldfile , File newfile ) throws IOException {
FileInputStream fis = new FileInputStream(oldfile);
FileOutputStream fos = new FileOutputStream(newfile);
int read = -1;
while ( ( read = fis.read( ) ) != -1 ) {
fos.write(read);
}
fis.close();
fos.close();
}
//不加缓冲:一次读取一个字节数组
public static void copy_2( File oldfile , File newfile ) throws IOException {
FileInputStream fis = new FileInputStream(oldfile);
FileOutputStream fos = new FileOutputStream(newfile);
int read = -1;
byte[] bytes = new byte[1024];
while ( ( read = fis.read(bytes) ) != -1 ) {
fos.write(bytes, 0, read);
}
fis.close();
fos.close();
}
//加缓冲:一次读取一个字节
public static void copy_3( File oldfile , File newfile ) throws IOException {
FileInputStream fis = new FileInputStream(oldfile);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(newfile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int read = -1;
while ( ( read = bis.read( ) ) != -1 ) {
bos.write(read);
}
fis.close();
fos.close();
}
//加缓冲:一次读取一个字节数组
public static void copy_4( File oldfile , File newfile ) throws IOException {
FileInputStream fis = new FileInputStream(oldfile);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(newfile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int read = -1;
byte[] bytes = new byte[1024];
while ( ( read = bis.read(bytes) ) != -1 ) {
bos.write(bytes, 0, read);
}
fis.close();
fos.close();
}
}
2、缓冲字节流
(1)缓冲字符输入流 BufferedReader
- 构造方法
BufferedReader(Reader in)
- 读取方法
readLine()
:一次读取一行,读到末尾返回null
(2)缓冲字符输出流 BufferedReader
- 构造方法
BufferedWriter(Writer out)
- 写出方法
write(int c)
(3)Demo1:缓冲字符流完成文件的复制
public class Demo1 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader( "D:\\Test1\\HelloWorld.txt" );
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter( "D:\\Test1\\IOtest\\HelloWorld.txt" );
BufferedWriter bw = new BufferedWriter(fw);
String line = null;
while ( ( line = br.readLine() ) != null ) {
bw.write(line);
bw.newLine();
}
br.close();
bw.close();
}
}
(4)Demo2:统计一个文件目录下所有Java文件的所有代码行数。
public class Demo2 {
public static int count = 0;
public static void main(String[] args) throws IOException {
File file = new File("d:\\test");
find(file);
System.out.println("所有java文件的代码总行数为:" + count);
}
public static void find(File file) throws IOException {
File[] listFiles = file.listFiles();
for(File f: listFiles) {
if ( f.isDirectory()) {
find(f);
}else if(f.isFile() && f.getName().endsWith(".java")) {
count(f);
}
}
}
public static void count( File file) throws IOException {
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line = null;
while((line = br.readLine()) != null) {
count++;
}
br.close();
fr.close();
}
}
七、对象流
1、对象的序列化与反序列化以及对象流
对象要进行序列化,必须要实现serializable接口 这种接口叫做标记性接口,里面什么东西都没有。
(1)对象的序列化: 将对象转换成字节数组的方式储存
(2)对象的反序列化:将字节数组转换成对象
(3)作用
- 可以将对象持久化保存
- 实现对象的远程调用
(4)应用
分布式系统
2、对象流 Object
(1)对象输出流 ObjectOutputStream
- 构造方法
ObjectOutputStream()
- 写入方法
writeObject()
(2)对象输入流 ObjectInputStream
- 构造方法
ObjectIutputStream()
- 读取方法
readObject()
(3)Demo:对象流完成写入再读取
public class Test3{
//对象流
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream( "D:\\Test1\\HelloWorld.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
FileOutputStream fos = new FileOutputStream( "D:\\Test1\\HelloWorld.txt" );
ObjectOutputStream oos = new ObjectOutputStream(fos);
//写入
Student student = new Student( "zhangsan" , 18 , "nan" );
Student student2 = new Student( "zhangsan" , 18 , "nan" );
Student student3 = new Student( "zhangsan" , 18 , "nan" );
Student student4 = new Student( "zhangsan" , 18 , "nan" );
Student student5 = new Student( "zhangsan" , 18 , "nan" );
oos.writeObject(student);
oos.writeObject(student2);
oos.writeObject(student3);
oos.writeObject(student4);
oos.writeObject(student5);
//读取
Object ro = ois.readObject();
Student s = (Student)ro;
System.out.println(s);
//关流
ois.close();
oos.close();
}
}