1 初识Java IO
IO,即in和out,也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接。
Java 中是通过流处理IO 的,那么什么是流?
流(Stream),是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道。
当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。
一般来说关于流的特性有下面几点:
先进先出:最先写入输出流的数据最先被输入流读取到。
顺序存取:可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile除外)
只读或只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。
输入与输出是相对于应用程序而言的,比如文件读写,读取文件是输入流,写文件是输出流,这点很容易搞反。
2 io流的分类
io流的分类可以分成三种:
- 按数据流的方向:输入流、输出流
- 按处理数据单位:字节流、字符流
- 按功能:节点流、处理流
3 File类
io流可以对文件的内容进行读写操作,而其本身并不能操作文件本身。此时就需要jdk中提供的file类来实现对文件的常规操作(主要用于文件和目录的创建、查找和删除等操作),这也是学习io流的基础。 注意 可以创建目录。
3.1File类的构造方法
public File(String pathname) | 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。 |
public File(String parent, String child) | 从父路径名字符串和子路径名字符串创建新的 File实例。 |
public File(File parent, String child) | 从父抽象路径名和子路径名字符串创建新的 File实例。 |
注意:
1. 一个File对象代表硬盘中实际存在的一个文件或者目录。
2. File类构造方法不会给你检验这个文件或文件夹是否真实存在,因此无论该路径下是否存在文件或者目录,都不影响File对象的创建。
3.绝对路径:一个完整的路径,以盘符开头,例如F://aaa.txt
。
相对路径:一个简化的路径,不以盘符开头,例如//aaa.txt//b.txt
。
下面是具体的代码:
// 文件路径名
String path = "D:\\123.txt";
File file1 = new File(path);
// 文件路径名
String path2 = "D:\\1\\2.txt";
File file2 = new File(path2); -------------相当于D:\\1\\2.txt
// 通过父路径和子路径字符串
String parent = "F:\\aaa";
String child = "bbb.txt";
File file3 = new File(parent, child); --------相当于F:\\aaa\\bbb.txt
// 通过父级File对象和子路径字符串
File parentDir = new File("F:\\aaa");
String child = "bbb.txt";
File file4 = new File(parentDir, child); --------相当于F:\\aaa\\bbb.txt
一般来说,程序只处理一个目录或文件,并且知道该目录或文件的路径,使用第一种构造方法较简单。
3.2常用方法
获取功能的方法:
1、public String getAbsolutePath() :返回此File的绝对路径名字符串。
2、public String getPath() :将此File转换为路径名字符串。
3、public String getName() :返回由此File表示的文件或目录的名称。
4、public long length() :返回由此File表示的文件的长度。
判断功能的方法
1、 public boolean exists() :此File表示的文件或目录是否实际存在。
2、 public boolean isDirectory() :此File表示的是否为目录。
3、public boolean isFile() :此File表示的是否为文件。
创建删除功能的方法
public boolean createNewFile() :文件不存在,创建一个新的空文件并返回true,文件存在,不创建文件并返回false。
public boolean delete() :删除由此File表示的文件或目录。
public boolean mkdir() :创建由此File表示的目录。
public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
3.3目录的遍历
file类中提供了一个list()方法,用来获取目录。
-
public String[] list()
:返回一个String数组,表示该File目录中的所有子文件或目录。 -
public class FileFor { public static void main(String[] args) { File dir = new File("D:\\"); //获取当前目录下的文件以及文件夹的名称。 //用string返回值接收 String[] names = dir.list(); //增强for,遍历names数组 for(String name : names){ System.out.println(name); }
有时我们只需要一种类型的文件,这时候file提供给了我们一种list(FilenameFilter filter)。FilenameFilter是一个函数式接口,接口中定义了一个抽象方法accept(File dire,String name)用于对指定File的所有子目录或文件进行迭代。
-
public class FileFor { public static void main(String[] args) { File file = new File("D:\\java入门基础\\"); //获取当前目录下的文件以及文件夹的名称。 //用string返回值接收 String[] textnames = file.list( //函数式接口,需要用lambda表达式来实现 (dire,name) ->name.endWith(".text"); ); //增强for,遍历names数组 for(String textname : textnames){ System.out.println(textname); }
要遍历子目录下的文件,list()不能满足该需求,此时需要引入
ublic File[] listFiles()
。 -
3.4删除文件及目录
- 删除file时,设计deletedire()方法时
- 需要判断该file下是否还存在file,需要使用遍历得到全部的file。先使用isDirectory()方法,判断其是否为目录,是目录,则递归调用deletedire()方法。如果是文件,将其删除。
-
public static void deleteDir(File files){ //File[]数组接收listFiles File[] listFiles = files.listFiles(); for(File file : listFiles ){ //判断是否为目录 if(file.isDirectory){ //是目录的话,则需要递归 deletDir(file); } //删除文件 file.delete(); } //最后,删除该文件 files.delete(); }
4字节流
- 字节流是针对二进制字节进行输入输出的一个流。inputStream,outputStream是顶级父类(抽象类)
-
4.1父类
- inputStream
-
public void close() 关闭此输入流并释放与此流相关联的任何系统资源 public abstract int read() 从输入流读取数据的下一个字节 public int read(byte[] b) 该方法返回的int值代表的是读取了多少个字节,读到几个返回几个,读取不到返回-1 - outputStream字节输出流
public void close() 关闭此输出流并释放与此流相关联的任何系统资源 public void flush() 刷新此输出流并强制任何缓冲的输出字节被写出 public void write(byte[] b) 将 b.length个字节从指定的字节数组写入此输出流。 public void write(byte[] b, int off, int len) 从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。 也就是说从off个字节数开始读取一直到len个字节结束 public abstract void write(int b) 将指定的字节输出流。 4.2简单FileInputStream和FileOutStream
-
用于操作file,用一串代码来解释该功能:
-
public class zijieio{ public static void main(String[] args)throws Exception{ //创建in,out对象 // 1该文件需要提前存在 //2 创建inputStream对象 //3 把inputStream对象指向这个文件 FileInputStream in = new FileInputStream("source.jpn"); //1、调用系统功能去创建文件【输出流对象才会自动创建】 //2、创建outputStream对象 //3、把foutputStream对象指向这个文件 FileOutputStream out = new FileOutputStream("traget.text"); int len = 0; while(len = in.read()!=-1){ out.write(len); }finlly{ in.close(); out.close(); } } }
注意: 1 read(),write()方法的参数都是字节;输出字符时,需要调用str.getByte();
-
2FileOutputStream(file)会重置原文件,想要保存该文件要使用FileOutputStream(file,ture);
-
使用缓冲的方式也可以使用inputStream读取图片
-
byte[] buff = new byte[1024]; // int read(byte【】) int代表返回的字节的数目 byte[]是按照数组来读取 if(len = in.read(buff)!=-1){ out.write(buff,0,len) }
4.3字节缓冲流
使用缓冲的目的是为了提高文件读取和写入的速率。缓冲的原理就是先创建一片缓冲区域,将流读取得信息缓存在区域内。
因为缓冲流无法直接和源设备,目标设备进行交流,需要先连接字节流,再进行输入输出。
因此,将inputstream作为参数放进BufferedStream的构造方法中是必要的。
public class zijieio{
public static void main(String[] args)throws Exception{
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream ("source/sre.jpg"));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("traget.text"));
int len = 0;
while(len = bis.read()!=-1){
bos.write(len);
}finlly{
bis.close();
nos.close();
}
}
}
5字符流
字符流是用来处理字符的类,其也有两个父类Reader和Writer,常用的是FileReader,FileReader和BufferedReader,BufferedWriter。
字符流与字节流最大的区别就是,字符流reader()和write()方法是以字符为基本基本单位,所读取的int,可以通过char(int)转换为字符。
5.1父类
字符输入流reader
public int read() | 从输入流读取一个字符。 |
public int read(char[] cbuf) | 从输入流中读取一些字符,并将它们存储到字符数组 cbuf 中 |
public void close() | 关闭此流并释放与此流相关联的任何系统资源 |
字符输出流Writer
write(char[] cbuf) | 写入字符数组。 |
write(char[] cbuf, int off, int len) | 写入字符数组的某一部分。 |
write(int c) | 写入单个字符。 |
write(String str) | 写入字符串。 |
write(String str, int off, int len) | 写入字符串的某一部分。 |
flush() : | 刷新该流的缓冲。 |
close() | 关闭此流,但要先刷新它 |
数据先被读到内存中,然后再用数据写到文件中,那么当你数据读完时,我们如果这时调用close()
方法关闭读写流,这时就可能造成数据丢失,为什么呢?因为,读入数据完成时不代表写入数据完成,一部分数据可能会留在缓存区中,这个时候flush()
方法就格外重要了。
5.2FileReader和FileWrter
FileReader构造方法
1、
FileReader(File file)
: 创建一个新的 FileReader ,给定要读取的File对象。
2、FileReader(Strig fileName)
: 创建一个新的 FileReader ,给定要读取的文件的字符串名称。
它读取的len可以通过char(len)强制类型转换,转换成char类型。
FileWrite构造方法
1、 FileWriter(File file)
: 创建一个新的 FileWriter,给定要读取的File对象。
2、FileWriter(String fileName)
: 创建一个新的 FileWriter,给定要读取的文件的名称。
它的write可以有多种参数。
5.3字符缓冲流
BufferedReader和BufferedWrier
多了一个重要方法 readLine()和WriteLine()及一行一行的处理数据。