1、什么是IO
通过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 main(String[] args) {FileInputStream fis = null;try {//创建文件字节输入流对象fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\temp.txt");//开始读int readData = fis.read();//这个方法的返回值是:读取到的“字节”方法本身System.out.println(readData);//97readData = fis.read();System.out.println(readData);//98readData = fis.read();System.out.println(readData);//99readData = fis.read();System.out.println(readData);//100readData = fis.read();System.out.println(readData);//101readData = fis.read();System.out.println(readData);//102//已经读到文件的末尾了,在读的时候读取不到任何数据,返回-1readData = fis.read();System.out.println(readData);// -1readData = fis.read();System.out.println(readData);//-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();}}}}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class FileInuputStreamtest2 {public static void main(String[] 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.println(readData);}//改造while循环int readData = 0 ;while ((readData =fis.read())!= -1){System.out.println(readData);}} 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 read(byte[] b)
一次最多读取b.length个字节
减少硬盘和内存的交互,提高程序的执行效率。
往byte[] 数组当中读
import java.io.FileInputStream;
import java.io.IOException;public class FileInputStreamtest3 {public static void main(String[] 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.read(bytes);System.out.println(readCount);//将字节数组全部转化为字符串System.out.println(new String(bytes));//不应该全部都转换,应该是读取了多少字节,转换多少个System.out.println(new String(bytes,0,readCount));readCount = fis.read(bytes);//第二次只能读取到2个字节System.out.println(readCount);//2System.out.println(new String(bytes));System.out.println(new String(bytes,0,readCount));readCount = fis.read(bytes);//第三次1个字节都没有读取到返回-1System.out.println(readCount);//-1System.out.println(new String(bytes));}catch (IOException e){e.printStackTrace();}finally {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}
}
import java.io.FileInputStream;
import java.io.IOException;public class FileIuputStreamtest4 {public static void main(String[] args) {FileInputStream fis = null;try {fis = new FileInputStream("temp");byte[] bytes = new byte[4];while(true){int readCount = fis.read(bytes);if (readCount == -1){break;}System.out.print(new String(bytes,0, readCount));}
或/*int readCount1 = 0;while ((readCount1 = fis.read(bytes))!= -1){System.out.print(new String(bytes,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.println(fis.read(bytes));System.out.println(new String(bytes));
6FileOutputStream
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class FileOutputStreamtest1 {public static void main(String[] args) {FileOutputStream fos = null;try {//myfile文件不存在的时候会自动新建fos = new FileOutputStream("myfile");//开始写byte[] bytes = {97,98,99,100,101,102};//将byte数组全部写出!fos.write(bytes);//将byte数组的一部分写出fos.write(bytes,0,2);//写完之后,一定要刷新fos.flush();}catch (FileNotFoundException e) {e.printStackTrace();} catch(IOException 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 main(String[] 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.read(bytes))!= -1){fos.write(bytes,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 main(String[] args) {FileReader reader = null;try {//创建文件字符输入流reader = new FileReader("temp");//开始读char[] chars= new char[4];//一次读取4个字符int readCount = 0;while ((readCount = reader.read(chars)) != -1){System.out.print(new String(chars,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 main(String[] args) {FileWriter out = null;try {//创建文件字符输出流对象out = new FileWriter("file");//如果想拼接字符,在后面加上true//开始写char[] chars = {'我','是','中','国','人'};out.write(chars);out.write(chars,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 main(String[] 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.read(chars)) != -1){out.write(chars,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 main(String[] args) throws IOException {//对于这个程序来说:FileReader就是一个节点流,BufferedReader就是一个包装流/处理流。FileReader reader = new FileReader("src/Copy01.java");BufferedReader br = new BufferedReader(reader);//读一行String firstLine = br.readLine();System.out.println(firstLine);String secondLine = br.readLine();System.out.println(secondLine);String thirdLine = br.readLine();System.out.println(thirdLine);String s = null;while((s = br.readLine()) != null){System.out.println(s);}//关闭流//对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭。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 main(String[] args) throws Exception {
/* //字节流FileInputStream in = new FileInputStream("");//通过转换流转换//in是节点流,reader是包装流InputStreamReader reader = new InputStreamReader(in);//这个构造方法只能传一个字符流,不能传字节流//reader是节点流,br是包装流BufferedReader br = new BufferedReader(reader);*///合并BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("src/Copy01.java")));String line = null;while ((line = br.readLine()) != null){System.out.println(line);}//关闭最外层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 main(String[] args) throws IOException {BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new 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():返回一个抽象路径名数组,表示此抽象路径名表示的目录中的文件。(即获取当前目录下的所有子文件)