1、什么是IO
I:Input
O:Output
通过IO可以完成硬盘文件的读和写
Java中所有的流都在java.io.*
下
2、IO流的分类
有多种分类方式:输入流、输出流、字节流、字符流
1、一种方式是按照流的方向进行分类: 以内存作为参照物。
往内存中去,叫做输入Input)。或者叫做读Read)。
从内存中出来,叫做输出Output)。或者叫做写Write)。
2、另一种方式是按照读取数据方式不同进行分类:
有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件。。。
假设文件file.txt,采用字节流的话是这样读:
a中国bc张三fe
第一次读:一个字节,正好读到 ‘ a ’
第二次读:一个字节,正好读到 ‘ 中 ’ 字符的一半。
第三次读:一个字节,正好读到 ‘ 中 ’ 字符的另一半。
有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯文本文件,连word文件都无法读取。
假设文件file.txt,采用字符流的话是这样读:
a中国bc张三fe
第一次读: ‘ a ’字符(a字符在window系统中占用1个字节)
第二次读: ‘ 中 ’ 字符( ‘ 中 ’ 字符在window系统中占用2个字节)
3、流的四大家族
四大家族的首领:
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Reader 字符输入流
java.io.Writer 字符输入流
四大家族的首领都是抽象类(Abstract class)
所有的流都实现了:
java.io.Closeable接口,都是可关闭的,都有close)方法。流毕竟是一个管道,这个是内存和硬盘之间的通道,用完一定要关闭,不然会耗费大量很多资源。养成好习惯,用完流一定要关闭。
所有的输出流都实现了:
java.io.flushable接口。都是可刷新的,都有flush)方法。养成一个好习惯,输出流在最终输出之后,一定要 记得flush )刷新一下。这个刷新表示将通道道/管道当中剩余未输出的数据强行输出完清空管道!) 刷新的作用就是清空管道。
注意:如果没有flush)可能会导致丢失数据。|
注意:在Java中只要“类名”以Stream结尾的都是字节流。以Reader/Writer结尾的都是字符流。
4、``java.io``包下需要掌握的流
java.io包下需要掌握的流有16个:
文件专属:
java.io.FileInputStream(掌握)
java.io.FileOutputStream(掌握)
java.io.FileReader
java.io.FileIWriter
转换流:(将字节流转为字符流)
java.io.InputStreamReader
java.io.OutputStreamWriter
缓冲流专属:
java.io.BufferedReader
java.io.BufferedWriter
java.io.BufferedInputStream
java.io.BufferedOutputStream
数据流专属:
java.io.DataInputStream
java.io.DataOutputStream
标准输出流
java.io.PrintWriter
java.io.PrintStream(掌握)
对象专属流:
java.io.ObjectInputStream(掌握)
java.io.ObjectOutputStream(掌握)
5FileInputStream
java.io.FileInputStream
:
1、文件字节流,万能的,任何类型的文件都可以采用这个流来读。
2、字节的方式,完成输入的操作,完成读的操作(硬盘–>内存)
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class FileInputStreamtest1 {public static void mainString[] args) {FileInputStream fis = null;try {//创建文件字节输入流对象fis = new FileInputStream"C:\\Users\\Administrator\\Desktop\\temp.txt");//开始读int readData = fis.read);//这个方法的返回值是:读取到的“字节”方法本身System.out.printlnreadData);//97readData = fis.read);System.out.printlnreadData);//98readData = fis.read);System.out.printlnreadData);//99readData = fis.read);System.out.printlnreadData);//100readData = fis.read);System.out.printlnreadData);//101readData = fis.read);System.out.printlnreadData);//102//已经读到文件的末尾了,在读的时候读取不到任何数据,返回-1readData = fis.read);System.out.printlnreadData);// -1readData = fis.read);System.out.printlnreadData);//-1} catch FileNotFoundException e) {e.printStackTrace);} catch IOException e) {e.printStackTrace);} finally {//在finally语句块当中确保流一定关闭if fis != null) {//关闭流的前提是:流不是空。流是null的时候没必要关闭。try {fis.close);} catch IOException e) {e.printStackTrace);}}}}
}
temp文件:
运行结果:
演示:
对上一个程序进行改进(使用while循环输出字节):
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class FileInuputStreamtest2 {public static void mainString[] args) {FileInputStream fis = null;try {fis = new FileInputStream"C:\\Users\\Administrator\\Desktop\\temp.txt");while true){int readData = fis.read);if readData == -1){break;}System.out.printlnreadData);}//改造while循环int readData = 0 ;while readData =fis.read))!= -1){System.out.printlnreadData);}} catch FileNotFoundException e) {e.printStackTrace);} catch IOException e) {e.printStackTrace);} finally {//在finally语句块当中确保流一定关闭if fis != null) {//关闭流的前提是:流不是空。流是null的时候没必要关闭。try {fis.close);} catch IOException e) {e.printStackTrace);}}}}
}
运行结果:
1.2 int readbyte[] b)
一次最多读取b.length个字节
减少硬盘和内存的交互,提高程序的执行效率。
往byte[] 数组当中读
import java.io.FileInputStream;
import java.io.IOException;public class FileInputStreamtest3 {public static void mainString[] args) {FileInputStream fis = null;try {//相对路径的话呢?相对路径一定是从当前所在的位置作为起点开始找!//在IDEA中默认的当前路径是哪里? 工程Project的根就是IDEA的默认当前路径fis = new FileInputStream"temp");//开始读,采用byte数组,一次读取多个字节。最多读取:数组.length 个字节byte[] bytes = new byte[4];//准备一个4个长度的byte数组,一次最多读取4个字节。//这个方法的返回值是:读取到的字节数量不是字节本身)int readCount = fis.readbytes);System.out.printlnreadCount);//将字节数组全部转化为字符串System.out.printlnnew Stringbytes));//不应该全部都转换,应该是读取了多少字节,转换多少个System.out.printlnnew Stringbytes,0,readCount));readCount = fis.readbytes);//第二次只能读取到2个字节System.out.printlnreadCount);//2System.out.printlnnew Stringbytes));System.out.printlnnew Stringbytes,0,readCount));readCount = fis.readbytes);//第三次1个字节都没有读取到返回-1System.out.printlnreadCount);//-1System.out.printlnnew Stringbytes));}catch IOException e){e.printStackTrace);}finally {try {fis.close);} catch IOException e) {e.printStackTrace);}}}
}
运行结果:
改进后(while循环):
import java.io.FileInputStream;
import java.io.IOException;public class FileIuputStreamtest4 {public static void mainString[] args) {FileInputStream fis = null;try {fis = new FileInputStream"temp");byte[] bytes = new byte[4];whiletrue){int readCount = fis.readbytes);if readCount == -1){break;}System.out.printnew Stringbytes,0, readCount));}
或/*int readCount1 = 0;while readCount1 = fis.readbytes))!= -1){System.out.printnew Stringbytes,0,readCount1));}*/}catch IOException e){e.printStackTrace);}finally {if fis != null){try {fis.close);} catch IOException e) {e.printStackTrace);}}}}
}
运行结果:
1.3int available)
:返回流当中剩余的没有读到的字节数量
在上述代码的前提下进行修改:
fis = new FileInputStream"temp");System.out.println"总字节数量" + fis.available));//读取1个字节int readByte = fis.read);System.out.println"剩下多少字节没有读:" + fis.available));
运行结果:
也可采用以下方法输出文件(不适合太大的文件,因为byte[]数组不能太大大)
byte[] bytes = new byte[fis.available)];System.out.printlnfis.readbytes));System.out.printlnnew Stringbytes));
6FileOutputStream
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class FileOutputStreamtest1 {public static void mainString[] args) {FileOutputStream fos = null;try {//myfile文件不存在的时候会自动新建fos = new FileOutputStream"myfile");//开始写byte[] bytes = {97,98,99,100,101,102};//将byte数组全部写出!fos.writebytes);//将byte数组的一部分写出fos.writebytes,0,2);//写完之后,一定要刷新fos.flush);}catch FileNotFoundException e) {e.printStackTrace);} catchIOException e){e.printStackTrace);}finally {if fos != null){try {fos.close);} catch IOException e) {e.printStackTrace);}}}}
}
7使用FileInputStream+FileOutputStream完成文件拷贝
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class Copy01 {public static void mainString[] args) {FileInputStream fis = null;FileOutputStream fos = null;try {//创建一个输入流fis = new FileInputStream"C:\\Users\\Administrator\\Desktop\\简历.txt");//创建一个输出流fos = new FileOutputStream"D:\\简历.txt");//最核心的:一边读,一边写byte[] bytes = new byte[1024*1024];//1MB一次最多拷贝1MB)int readCount = 0;while readCount = fis.readbytes))!= -1){fos.writebytes,0,readCount);}} catch FileNotFoundException e) {e.printStackTrace);}catch IOException e){e.printStackTrace);}finally {if fis != null){try {fis.close);} catch IOException e) {e.printStackTrace);}if fos !=null){try {fos.close);} catch IOException e) {e.printStackTrace);}}}}}
}
8FileReader
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;public class FileReadertest1 {public static void mainString[] args) {FileReader reader = null;try {//创建文件字符输入流reader = new FileReader"temp");//开始读char[] chars= new char[4];//一次读取4个字符int readCount = 0;while readCount = reader.readchars)) != -1){System.out.printnew Stringchars,0,readCount));}} catch FileNotFoundException e) {e.printStackTrace);}catch IOException e){e.printStackTrace);}finally {try {reader.close);} catch IOException e) {e.printStackTrace);}}}
}
9FileWriter
import java.io.FileWriter;
import java.io.IOException;public class FileWritertest {public static void mainString[] args) {FileWriter out = null;try {//创建文件字符输出流对象out = new FileWriter"file");//如果想拼接字符,在后面加上true//开始写char[] chars = {'我','是','中','国','人'};out.writechars);out.writechars,2,3);// 2:起始下标、3:长度out.write"我是一名Java软件攻城狮");out.write"\n");//换行out.write"hello world!");//刷新out.flush);} catch IOException e) {e.printStackTrace);}finally {try {out.close);} catch IOException e) {e.printStackTrace);}}}
}
10复制普通文本文件
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;public class CopyTest2 {public static void mainString[] args) {FileReader in =null;FileWriter out = null;try {//读in = new FileReader"C:\\Users\\Administrator\\Desktop\\简历.txt");//写out = new FileWriter"D:\\copy简历.txt");char[] chars = new char[1024*512];//1MB//一边读一边写int readCount = 0;while readCount = in.readchars)) != -1){out.writechars,0,readCount);}//刷新out.flush);} catch FileNotFoundException e) {e.printStackTrace);} catch IOException e) {e.printStackTrace);}finally {if in != null) {try {in.close);} catch IOException e) {e.printStackTrace);}if out != null){try {out.close);} catch IOException e) {e.printStackTrace);}}}}}
}
11BufferedRead(带有缓冲的字符输入流)
带有缓冲区的字符输入流
使用这些流的时候不需要自定义char数组,或者说不需要自定义byte数组,自带缓冲。
1、节点流和包装流
当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。
外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。
2、readline :读一行字符
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;public class BufferedReadertest1 {public static void mainString[] args) throws IOException {//对于这个程序来说:FileReader就是一个节点流,BufferedReader就是一个包装流/处理流。FileReader reader = new FileReader"src/Copy01.java");BufferedReader br = new BufferedReaderreader);//读一行String firstLine = br.readLine);System.out.printlnfirstLine);String secondLine = br.readLine);System.out.printlnsecondLine);String thirdLine = br.readLine);System.out.printlnthirdLine);String s = null;whiles = br.readLine)) != null){System.out.printlns);}//关闭流//对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭。br.close);}
}
12转换流(InputStreamReader与OutputStreamWriter)
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;public class BufferedReaderTest2 {public static void mainString[] args) throws Exception {
/* //字节流FileInputStream in = new FileInputStream"");//通过转换流转换//in是节点流,reader是包装流InputStreamReader reader = new InputStreamReaderin);//这个构造方法只能传一个字符流,不能传字节流//reader是节点流,br是包装流BufferedReader br = new BufferedReaderreader);*///合并BufferedReader br = new BufferedReadernew InputStreamReadernew FileInputStream"src/Copy01.java")));String line = null;while line = br.readLine)) != null){System.out.printlnline);}//关闭最外层br.close);}
}
13BufferedWrite:(带有缓冲的字符输出流)
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;public class BufferedWriteTest {public static void mainString[] args) throws IOException {BufferedWriter out = new BufferedWriternew OutputStreamWriternew FileOutputStream"temp")));out.write"hello world");out.write"\n");out.write"hello kitty");out.flush);out.close);}
}
18File类
File类和IO流四大家族没有关系,所以File类不能完成文件的读和写。
位于java.io.File 下
File对象代表什么?
文件和路径名的抽象表达式。
一个File对象有可能对应的是目录,也可能是文件
C:\Drivers 是一个File对象
C:\Drivers\Lan\Readme\Readme.txt 也是一个File对象
File只是一个路径名的抽象表达式。
File类的常用方法
创建一个File对象
File f = new File"D:\\file")
19File类的常用方法
boolean exits) 判断文件是否存在
boolean creatNewFile) 以文件的形式创建出来
boolean mkdir) 以目录的形式新建
boolean mkdirs) 多重目录的形式新建
String getParent) 获取文件的父路径
File getParentFile) 获取文件的父文件
File getAbsoluteFile):返回抽象路径文件。
String getAbsoulutePath) 获取文件的绝对路径
boolean isAbsolute):测试此抽象路径名是否为绝对路径。
boolean isDirectory):测试此抽象路径名表示的文件是否为目录。
boolean isFile) :测试此抽象路径名表示的文件是否为普通文件。
long lastModified): 返回上次修改此抽象路径名表示的文件的时间。(从1970年到现在的毫秒)
File[] listFiles):返回一个抽象路径名数组,表示此抽象路径名表示的目录中的文件。(即获取当前目录下的所有子文件)