java文件(File)类与IO流
文件(File)类:
一、文件(File)类的定义:
java.io.file文件和目录路径及名称的抽象表示形式;
java把电脑中的文件和文件夹(目录)封装为了一个file类,可以使用file类对文件和文件夹进行操作;
File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
说明:
1.File类声明在java.io包下
2.File类中涉及关于文件或文件目录的创建、删除、重命名、修改时间、文件大小,判断文件是否存在等方法,并未涉及到写入或读取文件内容的操作,如果需要读取或写入文件内容,必须使用IO流来完成
3.file类是一个与操作系统无关的类,任何操作系统都可以使用这个类中方法
4.后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的“终点”
5.几个关键词:
file:文件,与文件相关的操作
directory:文件夹/目录,与文件夹/目录相关的操作
path:路径,与路径相关操作
注:
路径不区分大小写;路径中的文件名称分隔符Windows使用反斜杠,反斜杠是转义字符,两个反斜杠代表一个普通反斜杠
tip:学习一个类:
首先看此类中是否有静态成员。因为静态成员可以直接通过类名来访问,
第二个学习类中的构造方法,通过构造方法可以创建对象,创建完对象后,通过对象可以直接访问成员方法
二、创建File类的实例:
构造器一(此时不对应硬盘中的文件,此时仅仅只是内存中的一个对象,并不涉及对文件中的数据进行增删改查等操作):
public File(String pathname):
参数:
String pathname:字符串的路径名称
路径可以是文件结尾,也可以是文件夹结尾
路径可以是相对路径,也可以是绝对路径
路径可以是存在,有可以是不存在
创建File对象只是把字符串路径封装为File对象,不考虑路径的真假情况
作用:
通过将给定路径名字字符串转换为抽象路径名来创建一个新File实例。即以pathname为路径创建File对象,可以是绝对路径或相对路径,若pathname是相对路径,则默认的当前路径在系统属性user.dir中存储
>绝对路径:是一个完整路径。是一个固定的路径,从盘符(C:,D:)开始。即包含盘符在内(C:\\)的文件或文件目录的路径
>相对路径:是一个简化路径,相对指的是相对于当前项目的根目录是相对于某个位置开始。即相对于某个路径下,指明的路径
>分隔符:
windows和DOS下默认使用“\”
UNX、Linux和URL下默认使用“/”
为了适应不同平台下的分隔符,java提供了
public static final String separator类,对程序中的路径进行动态分割;
static String separator
与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串;
static char separatorChar
与系统有关的默认名称分隔符。
static String pathSeparator
与系统有关的路径分隔符,为了方便,它被表示为一个字符串
static char pathSeparatorChar
与系统有关的路径分隔符
实例{
灵活:"G:"+File.separator+"WioJiaQi"+File.separator+"javabase"
new File("d:\\workspace\\One.txt");
new File("d:"+File.separator+"workspace"+File.separator+"One.txt");
new File("d:/workspace/One.txt");
}
构造器二(此时不对应硬盘中的文件,此时仅仅只是内存中的一个对象,并不涉及对文件中的数据进行增删改查等操作):
public File(String parent,String child):
以parent为父路径,child为子路径创建File对象,
这个file对象可以是一个文件目录,也可以是一个文件。
即由parent路径名字符串和child路径名字符串创建一个File实例。
参数:把路径分成了两部分
String parent:父路径
String child:子路径
好处:
父路径和子路径可以单独书写,使用起来非常灵活:父子路径都可以变换
构造器三(此时不对应硬盘中的文件,此时仅仅只是内存中的一个对象,并不涉及对文件中的数据进行增删改查等操作):
public File(File parent,String child):
根据一个File对象和子文件路径创建File对象,
指定目录下创建指定目录或文件。
即由parent路径名字符串和child路径名字符串创建一个File实例
参数:把路径分成了两部分
String parent:父路径
String child:子路径
好处:
父路径和子路径可以单独书写,使用起来非常灵活:父子路径都可以变换
父路径是File类型,可以使用file的方法对路径进行一些操作,再使用路径创建对象
三、File类的常用方法:
1.文件类的获取功能
public String getAbsolutePath():
获取绝对路径。即返回此File的绝对路径名字符串
获取构造方法中传递的路径
无论路径是绝对路径还是相对路径,
getAbsolutePath方法返回都是绝对路径
public String getPath():
获取路径。将此File转换为路径字符串
获取构造方法中传递的路径
toString()调用的是getPath方法
源码:
public String toString(){
return getPath();
}
public String getName():
获取名称。返回由此File表示的文件或目录的名称。
获取的就是构造方法传递路径的结尾部分(文件/文件夹)
public String getParent():
获取上层文件目录路径。若无,返回null;
public long length():
获取文件长度(即:字节数)。不能获取目录长度。
返回由此File表示的文件长度
获取的是构造方法指定的文件的大小,以字节为单位
注:
文件夹无大小概念,不能获取文件夹的大小
若构造方法中给出的路径不存在,则length方法返回0
public long lastModified():
获取最后一次修改时间,毫秒值
2.适用于文件目录
public String[] list():
获取指定目录下的所有文件或文件目录的名称数组,
要求文件或目录存在,否则报错。返回一个String数组,
表示该目录中的所有子文件或目录。遍历构造方法中给出的目录,
会获取目录中所有文件/文件夹的名称,
把获取到的多个名称存储到一个String类型数组中能够访问隐藏文件夹
public File[] listFiles():
获取指定目录下的所有文件或文件目录的File数组,
若直接输出则输出包含绝对路径的文件名称,返回一个file数组,
表示该目录中的所有子文件或目录。遍历构造方法中给出的目录,
会获取目录中所有文件/文件夹的名称,把文件/文件夹封装为File对象,
多个file对象存储到file数组中
注:
list方法和listFiles方法遍历的是构造方法中给出的目录
若构造方法中给出的目录的路径不存在,会抛出空指针异常
若构造方法中给出的路径不是一个目录,会抛出空指针异常
public boolean renameTo(File dest):
把文件重新命名为指定的文件路径
如file1.renameTo(file2)为例子:要想保证返回是true,
需要保证file1在硬盘中是存在的,且file2不能在硬盘中存在
3.文件类的功能判断
public boolean isDirectory():
判断是否是目录文件。此File表示的是否为目录
用于判定构造方法中给定路径是否以文件夹结尾
是:true
否:false
public boolean isFile():
判断是否是文件。此File表示的是否为文件
用于判定构造方法中给定路径是否以文件夹结尾
是:true
否:false
注:
电脑硬盘中只有文件,文件夹,两个方法互斥
这两个方法使用前提,路径必须存,在否则均返回false
public boolean exists():
判断是否存在。此File表示的文件或者目录是否存在
用于判断构造方法中的路径是否存在
存在:true
不存在:false
public boolean canRead():
判断是否可读
public boolean canWrite():
判断是否可写
public boolean iSHidden():
判断是否隐藏
4.文件的创建:
public boolean createNewFile():
创建文件。若文件存在则不创建,并且返回false;
当且仅当具有该名称的文件夹不存在时,创建一个新的空文件夹。
创建文件的路径和名称在构造方法中给出(构造方法的参数)
返回值:布尔值
true:文件不存在,创建文件,返回true
false:文件存在,不会创建文件夹,返回false
注:
此方法只能创建文件,不能创建文件夹
创建文件的路径必须存在,否则会抛出异常
public boolean createNewFile() throws IOException
createNewFile()申明抛出IOException异常,
调用此方法必须处理此异常,
要么throws,要么try...catch
public boolean mkdir():
创建文件目录。若此文件目录存在,就不创建,
若此文件目录的上层目录不存在,也不创建。
创建由此File表示的目录(单级文件夹)。
创建文件夹的路径和名称在构造方法中给出(构造方法的参数)
返回值:布尔值
true:文件夹不存在,创建文件夹,返回true
false:文件夹存在,不会创建文件夹,返回false;
构造方法中给出的路径不存在,返回false
注:
此方法只能创建文件夹,不能创建文件
public boolean mkdirs():
创建文件目录,若上层目录不存在,一并创建。
创建由此File表示的目录,包括任何必须但不存在的父目录(单级,多级均可以)。
创建文件夹的路径和名称在构造方法中给出(构造方法的参数)
返回值:布尔值
true:文件夹不存在,创建文件夹,返回true
false:文件夹存在,不会创建文件夹,返回false;
构造方法中给出的路径不存在,返回false
注:
此方法只能创建文件夹,不能创建文件
5.文件类的删除功能:
public boolean delete():
删除指定文件或文件夹,要删除一个文件目录,
则必须确保该文件目录内部包含任何文件或文件目录。
删除由此File表示的文件或者目录。
此方法可以删除构造方法中给出的文件/文件夹
返回值:布尔值
true:文件/文件夹删除成功,返回true
false:文件夹中有内容不会删除,返回false;
构造方法中路径不存在,返回false
注:
delete方法直接走硬盘删除,不走回收站删除,删除需谨慎
四、关于过滤器FileFilter:
创建过滤器FileFilter的实现类,重写过滤方法accept,定义过滤规则
过滤规则:在accept方法中,判断File对象是否以指定后缀结尾,是返回true,不是返回false
文件搜索,只要指定后缀结尾的文件
可以使用过滤器来实现:
在File类中有两个和ListFiles重载的方法,方法的参数传递的就是过滤器
File[] listFiles(FileFilter filter)
java.io.FileFilter接口:用于抽象路径名(File对象)的过滤器;作用是用于过滤文件(File对象)
抽象方法:用于过滤文件的方法:
boolean accept(File pathname):
测试指定抽象路径名是否应该包含在某个路径名列表中
参数:
File pathname:使用ListFiles方法遍历目录,得到每一个文件对象
File[] listFiles(FilenameFilter filter)
java.io.FilenameFilter接口:此接口的类实例可用于过滤文件名;作用:用于过滤文件名
抽象方法:用来过滤文件的方法
boolean accept(File dir,String name):
测试文件是否应该包含在某一文件列表中
参数:
File dir:构造方法中传递的被遍历的目录
String name:使用ListFiles方法遍历目录,获取每一个文件/文件夹的名称
注意:
两个过滤器接口是没有实现类的,需要自己写实现类,重写过滤方法accept,在方法中自己定义过滤的规则
过滤器原理:
必须明确两件事情:
1. 过滤器中的accept方法是谁调用的;2.accept方法的参数pathname是什么
listFiles干了3件事:
1.listFiles方法会对构造方法中传递的目录进行遍历,获取目录中的每一个文件/文件夹-->封装为File对象
2.listFiles方法会调用参数传递的过滤器中的方法accept
3.listFiles方法会把遍历得到的每一个File对象,传递过accept方法的参数pathname
accept方法的返回值是一个布尔值:
true:就会把传过去的File对象保存在File数组中
false:就不会把传过去的File对象保存在File数组中
IO流
一、IO流概述:
I:input 输入(读取),把硬盘中的东西放到内存中
O:output 输出(写入),把内存中的东西写入到硬盘中
流:数据(字符,字节)1个字符=2个字节,1个字符=8个二进制位
字节流:字节输入流InputStream,字节输出流:OutputStream
字符流:字符输入流:Reader,字符输出流:Writer
一切皆为字节:计算机中的所有文件数据(如MP4,mp3等)在存储时,都是以二进制数字的形式保存。即计算机中任何存储文件均是以二进制字节存储。因此字节流可以传输任何文件数据
二、IO流的分类:
1.四种分类方式:
java的io流是以程序(内存)为视角,即文件到程序(内存)的方向即为输入
io流以操作数据单位的不同分为:
字节流(8bit){适合用于图片,视频等非文本二进制数据},字符流(16bit){适合用于处理文本char型数据}
io流以角色分:
结点流{作用于文件上的流:
文件流(结点流):
FileInputStream,
FileOutputStream,
FileReader,
FileWriter
}
处理流{作用于已经存在流的流,除4个结点流外的流:
缓冲流:
BufferedInputStream,
BufferedOutputStream,
BufferedReader,
BufferedWriter
转换流:
InputStreamReader,
OutputStreamWriter(属于字符流)
对象流:
ObjectInputStream,
ObjectOutputStream
等等
}
流的分类(只看后缀名称):
抽象基类 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
三、流的体系结构:
抽象基类:
InputStream、OutputStream、Reader、Writer
结点流:
FileInputStream(read(byte[] buffer))、
FileOutputStream(write(byte[] buffer,0,len))、
FileReader(read(char[] cbuf))、
BufferedWriter(write(char[] buffer,0,len))
缓冲流(处理流中的一种,内置了flush()方法,不必显式调用):
BufferedInputStream(read(byte[] buffer))、
BufferedOutputStream(write(byte[] buffer,0,len))、
BufferedReader(read(char[] cbuf))、
BufferedWriter(write(char[] buffer,0,len))
四、结点流的使用:
1.流的使用步骤:
1、File类的实例化
2、流的实例化,将File的实例作为流的构造器参数
3、读入/写出的操作,造相应的字符/字节数组
4、资源的关闭
5、异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try...catch...finally结构处理
2.文件字符流/文件字节流:
输入操作:
从硬盘的某个文件中将数据以字符/字节为单位读入到内存中
读取数据的原理(硬盘-->内存)
java程序-->JVM-->OS-->OS读取数据的方法-->读取文件
FileReader/FileInputStream:
java.io.reader:字符输入流,是字符输入流的顶层父类,定义了一些共性的成员方法,是一个抽象类
共性成员方法:
int read():
读取单个字符并返回
FileReader(字符流状态)从硬盘中读入文件中的一个字符到内存中,若达到文件末尾,返回-1
FileInputStream(字节流状态)从硬盘中读入文件中的一个字节到内存中,若达到文件末尾,返回-1
int read(char/byte[] c/bbuf):
一次读取多个字符,将字符读入数组
FileReader(字符流状态)返回每次读入cbuf数组中的字符的个数,若达到文件末尾则返回-1
FileInputStream(字节流状态)返回每次读入cbuf数组中的字节的个数,若达到文件末尾则返回-1
void close:
关闭该流并释放与之相关的所有资源
在关闭前先判断关闭的流是否为空。
java.io.FileReader extends InputStreamReader extends Reader
FileReader:
文件字符输入流
作用:
把硬盘文件中的数据以字符的方式读取到内存中
构造方法:
FileReader(String fileName)
FileReader(File file)
参数:读取文件的数据源
String fileName:文件的路径
File file:一个文件
FileReader构造方法的作用:
1.创建一个FileReader对象
2.会把FileReader对象指向要读取的文件
字符输入流的使用步骤:
1.创建FileReader对象,构造方法中绑定要读取的数据源
2.使用FileReader对象中的方法read读取文件
3.释放资源
string类的构造方法
String(char[] value)
把字符数组转换成字符串
String(char[] value,int offset,int count)
把字符数组一部分转换为字符串,offset:数组开始索引;count:转换的个数
java.io.InputStream:字节输入流:
此抽象类是表示所有字节输入流的父类。
定义了所有子类共性的所有方法:
int read():
从输入流中读取数据的下一个字节。
int read(byte[] b):
从输入流中读取一定数量的字节,将其存入缓冲区数组b中
void close():
关闭此输出流并释放与该流关联的所有系统资源
java.io.FileInputStream extends InputStream
FileInputStream:
文件字节输入流
作用:
把硬盘文件中的数据,读取到内存使用中
构造方法:
FileInputStream(String name)
FileInputStream(File file)
参数:读取文件的数据源
String name :目的地是一个文件的路径
File file:目的地是一个文件
构造方法的作用:
1.会创建一个FileInputStream对象
2.会把FileInputStream对象指定构造方法中要读取的文件。
字节输入流的使用步骤:
1.创建FileInputStream对象,构造方法中要绑定要读取的数据源
2.使用FileInputStream对象中的方法read,读取文件
3.释放资源
字节流一次读入多个字节的方法:
int read(byte[] b)从输入流中读取一定数量的字节,将其存入缓冲区数组b中
数组的长度一般定义为1024(1Kb)或者是1024的整数倍
String类的构造方法:
String(byte[] bytes):
把字节数组转换成字符串
String(byte[] bytes,int offset, int length):
把字节数组中的一部分转换为字符串,offset:开始索引,length:装换的字节个数
读入的文件一定要存在,否则报异常FileNotFoundException
读取字节原理:
一次读取一个字节:
首先在硬盘中存有a.txt。在程序开始运行时,创建一个FileInputStream对象指针指向a.txt文件中的第一个字符内容,然后fis.read()方法调用OS,OS利用自己的方法来读取数据,数据通过OS->JVM->fis.read()读出来一个字读完,指针移向下一个字节,当指针移动到结束标记时,在fis.read()中读出的就是-1
一次读取多个字节:
首先在硬盘中存有a.txt。在程序开始运行时,创建一个FileInputStream对象指针指向a.txt文件中的第一个字符内容,然后fis.read()方法调用OS,OS利用自己的方法来读取数据,数据通过OS->JVM->fis.read()读出来一个字读完,发现数组中还有空位于是读取下一字节,当当指针移动到结束标记时,停止读取
输出操作:
从内存中写出以字符/字节为单位的数据到硬盘的指定文件中
写入数据的原理(内存-->硬盘)
java程序-->JVM-->OS-->OS写数据的方法-->把数据写到文件中
FileWriter/FileOutputStream:
java.io.Writer:字符输出流,是所有字符输出流最顶层的父类,是一个抽象类 共性的成员方法:
- void write(int c):
写入单个字符
FileWriter(字符流状态)从内存中将数据以字符的形式写到硬盘的指定文件中,文件如果不存在则自动创建文件
FileOutputStream(字节流状态)从内存中将数据以字节的形式写到硬盘的指定文件中,文件如果不存在则自动创建文件
- void write(char/byte[] b/cbuf):
写入字符数组.
一次写多个字节的情况:
若写的第一个字节是正数(0-127),则显示时会查询ASCII表
若第一个字节是负数,那么第一个字节会和第二个字节一起组成一个中文显示,查询系统默认码表(GBK)
byte[] getBytes() 把字符串转换为字节数组
- void write(字符串.toCharArray())方法:
仅针对FileWriter(字符流状态)从内存中将数据以字符串的形式写到硬盘的指定文件中,
文件如果不存在则自动创建文件
- void write(String str):
写入字符串
写入字符的方法:可以使用string类中的方法把字符串转换为字节数组
- abstract void write(char cbuf,int offset,int len):
写入字符数组某一部分,offset数组开始索引,len写的字符个数
- void write(String str,int off,int len):
常见- void write(c/bbuf,0,len);
写入字符串某一部分,offset数组开始索引,len写的字符个数
FileWriter(字符流状态)从内存中将数据以字符数组的形式写到硬盘的指定文件中,文件如果不存在则自动创建文件
FileOutputStream(字节流状态)从内存中将数据以字节数组的形式写到硬盘的指定文件中,文件如果不存在则自动创建文件
- void flush():
刷新该流的缓冲
- void close():
关闭此流先要刷新它,关闭此节点流,在关闭前先判断关闭的流是否为空。
flush方法和close方法的区别
- flush:刷新缓冲区,流对象可以继续使用
- close:先刷新缓冲区,然后通知系统释放资源,流对象不能再使用了
java.io.FileWriter extends OutputStreamWriter extends Writer
FileWriter:
文件字符输出流
作用:
把内存中字符数据写入文件中
构造方法:
FileWriter(File file)由给定的File对象构造一个FileWriter对象
FileWriter(String fileName)根据给定的文件名构造一个FileWriter对象
参数:写入数据的目的地
String fileName:文件的路径
File file:是个文件
构造方法的作用:
1.会创建一个FileWriter对象
2.会根据构造方法中传递的文件/文件路径,创建文件
3.会把FileWriter对象指向创建好的文件
字符输出流的使用步骤
1.创建FileWrite对象,构造方法中要绑定写入数据的目的地
2.使用FileWrite中write方法,把数据写到内存缓冲区中(字符转换到字节的过程)
3.使用FileWrite中flush方法,把内存缓冲区中的数据,刷新到文件中
4.释放资源(先把内存缓冲区中的资源刷新到文件中)
续写和换行
写出的文件可以不存在,若不存在则直接自动创建此文件;若文件存在则{
new FileWriter(new File,false)/new FileWriter(new File):对原有文件进行覆盖
new FileWriter(new File,true):对原有文件进行追加
}
续写,追加写:使用两个参数的构造方法
FileWrite(String fileName,boolean append)
FileWriter(File file,boolean append)
参数:
String fileName, File file:写入数据的目的地
boolean append:
续写开关,true不会创建新的文件覆盖源文件;
false创建新的文件覆盖源文件
换行:
Windows:\r\n
linux:/n
mac:/r
java.io.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开始输出到此输出流
-public abstract void write(int b);
将指定的字节输出流。
java.io.FileOutputStream extends OutputStream
FileOutputStream:
文件字节输出流
作用:
把内存中的数据写入到硬盘的文件中。
FileOutputStream流底层实现:
首先创建一个FileOutputStream对象,然后根据写入的路径在相应硬盘创建一个文件,之后流对象指向创建好的流对象。在写数据是会将十进制数据转换成二进制数据,硬盘中存储的数据都是字节(字节是硬盘中存储的最小单位)1字节等于8位。任意文本编辑器在打开时均会查询编码表,把字节转换到字符表示:0-127查询ASCII表,其他数值查询系统默认码表
构造方法:
FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流
FileOutputStream(File file):创建一个向指定 File 对象表示的文件中写入数据的文件输出流
参数:写入数据的目的
String name :目的地是一个文件的路径
File file:目的地是一个文件
构造方法的作用:
1.创建一个FileOutputStream对象
2.会根据构造方法中传递的文件/文件路径,创建一个空的文件
3.会被FileOutputStream对象指向创建好的文件
字节输出流的使用:
1.创建fileOutPutStream对象,构造方法中传递写入数据的目的地
2.使用fileOutPutStream对象中的方法write,把数据写入到文件中
3.释放资源(流使用会占用一定内存,使用完毕要把内存清空,提高程序的效率)
追加写/续写:使用两个参数的构造方法
FileOutputStream(String name,boolean append)
创建一个想具有指定name的文件中写入数据的输出文件流
FileOutputStream(File file,boolean append)
创建一个想指定file对象表示的文件中写入输出的文件输出流
参数:
String name,File file:写入数据的目的地;
boolean append:追加写开关;
true:创建对象不会覆盖源文件,继续在文件末尾追加写数据
false:创建一个新文件覆盖源文件
写换行:写换行符号。
Windows:\r\n
linux: /n
mac: /r
tip:
tip1.针对文本文件(.txt,.java,.c,.cpp)应该采用字符流进行操作,如果采用字节流进行操作容易出现乱码,若采用字节流,则应该避免在控制台输出
tip2.针对非文本文件(.doc,.jpg,.mp3,.mp4,.avi,.ppt。。。)应该采用字节流进行操作
tip3.NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作,NIO将以更加高校的方式进行文件的读写操作
tip4.知道循环次数用for不知道循环此时用while
tip5.使用字节流读取中文文件
1个中文:
GBK:占用两个字节
UTF-8:占用3个字节
五、处理流的使用:
1.处理流之一:缓冲流的使用
1.缓冲流基本知识:
缓冲流就是对基本流{字节输入,输出流;字符输入,输出流}的加强。
传统的基本流中:读写文件均以字符为单位,效率低下。
缓冲流中:读写文件均以字符数组为单位,改进了传统基本流的效率低下问题。
java读写数据的过程:java程序中有相应的输入输出流,这些流调用JVM,然后JVM调用OS,OS完成相应操作
2.缓冲流:
BufferedInputStream,BufferedOutputStream{二者不用处理文本文件}
BufferedReader,BufferedWriter{二者不用于处理非文本文件}
java.io.BufferedInputStream extends InputStream
BufferedInputStream:字节缓冲输入流
继承自父类的共性成员方法:
int read():
从输入流中读取数据的下一个字节
int read(byte[] b):
从输入流中读取一定数量的字节,将其存储在缓冲区数组b中
void close():
关闭此输入流并释放与此年流有关的所有资源
构造方法:
BufferedInputStream(InputStream in)
创建一个新的BufferedInputStream并保存其参数,即输入流in,以便将来使用
BufferedInputStream(InputStream in,int size)
创建具有指定缓冲区大小的BufferedInputStream并保存其参数,即输入流in,以便将来使用
参数:
InputStream in:
字节输入流,可以传递FileInputStream,
缓冲流会给FileInputStream增加一个缓冲区,
通过FileInputStream的读取效率
int size:
指定缓冲流内部缓冲区的大小,不指定默认
使用步骤:
1.创建FileInputStream对象,构造方法中绑定读取的数据源
2.创建BufferedFileInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象的读取效率
3.是用BufferedFileInputStream对象中的read方法,读取文件
4.释放资源
java.io.BufferedOutputStream extends OutputStream
BufferedOutputStream:字节缓冲输出流
继承自父类的共性成员方法:
- public void close():
关闭此输出流并释放与此输出流有关的所有资源
- public void flush():
刷新此输出流并强制任何缓冲的输出字节被写出
- public void write(byte[] b):
将b.long字节从指定的字节数组写入此输出流
- public void write(byte[] b,int off.int long):
从指定的字节数组写入len字节,从偏移量off开始半输出到此输出流
- public abstract void write(int b):
将指定的字节输出流
构造方法:
BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out,int size)
创建一个新的缓冲输出流,将具有指定缓冲区大小的数据写入底层输出流。
参数:
OutputStream out:
字节输出流:可以传递FileOutputStream,
缓冲流会给FileOutputStream增加一个缓冲区,
提高FileOutputStream写入效率
int size:
指定缓冲流内部缓冲区的大小,不指定默认
使用步骤:
1.创建FileOutputStream对象,构造方法中要绑定输出目的地
2.创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象,提高FileOutputStream对象使用效率
3.使用BufferedOutputStream对象的write方法,把数据写到内部缓冲区
4.使用BufferedOutputStream对象的flush方法,把缓冲区中的数据刷新到文件中
5.释放资源(先调用flush方法刷新数据,使得第4不可以省略)
java.io.BufferedReader extends Reader
继承父类共性成员方法:
int read():
读取单个字符并返回
int read(char[] cbuf):
一次读取多个字符,间字符读入数组
void close():
关闭该流并释放与值相关的所有资源
构造方法:
BufferedReader(Read in)
创建一个使用默认大小缓冲区的缓冲字符输入流
BufferedReader(Read in,int sz)
创建一个指定大小输入缓冲区的缓冲字符输入流
参数:
Reader in:
字符输入流,传递FileReader,
缓冲流会给FileReader增加一个缓冲区,
提高FileReader的读取效率
int sz:
指定了缓冲区大小
特有成员方法
String readLean():
读取一个文本行,读取一行数据。
行的终止符号:
通过下列终止符号可认为某行已经终止:
换行('\n')、回车('\r')或者回车后直接跟着换行(\r\n)
返回值:
包含该行的字符串,不包含任何终止符,若到达流末尾,则返回NULL
使用步骤:
1.创建字符缓冲流对象,构造方法中传递字符输入流
2.使用字符缓冲输入流对象中的方法read/readLine读取文本
3.释放资源
java.io.BufferedWriter extends Writer
BufferedWriter:字符缓冲输出流
继承自父类的共性成员方法:
- void write(int c):
写入单个字符
- void write(char[] cbuf):
写入字符数组
- abstract void write(char cbuf,int offset,int len)
写入字符数组某一部分,offset数组开始索引,len写的字符个数
- void write(String str)
写入字符串
- void write(String str,int off,int len):
写入字符串某一部分,offset数组开始索引,len写的字符个数
- void flush()
刷新该流的缓冲
- void close()
关闭此流先要刷新它
构造方法:
BufferedWriter(Writer out):
创建一个使用默认大小输出缓冲区的缓冲字符输出流
BufferedWriter(Writer out,int sz):
创建一个使用给定大小输出缓冲区的新缓冲字符输出流
参数:
Writer out:
字符输出流,可以传递FileWriter,
缓冲流会给FileWriter增加一个缓冲区,提高FileWriter的写入效率
int sz:
指定缓冲区大小,不写默认大小
特有成员方法:
void newline()写入一个行分割符,会根据不同的操作系统。获取不同的行分隔符{
换行:
windows:\r\n
linux:/n
mac:/r
}
使用步骤:
1.创建字符缓冲输出流对象,构造方法中传递字符输出流
2.调用字符缓冲输出流中的方法write,把数据写入到内存缓冲区中
3.调用字符缓冲输出流中方法flush,把内存缓冲区中的数据刷新到文件中
4.释放资源
3.作用:
提高流的读取/缓冲的速度{原因:内部提供了一个容量为8192字节大小缓冲区,即8kb}
4.方法:
flush()方法:刷新缓冲区,一般是内置调用,不需要开发者显示调用此函数
newLine()方法:提供换行操作
5.使用步骤:
1、File类的实例化
2、流的实例化:
先实例化节点流,然后再实例化处理流,将节点流作为处理流的参数
3、读入/写出的操作,造相应的字符/字节数组,对处理流进行操作即可
4、资源的关闭:
先关闭外层处理流,再关闭内层节点流;在关闭外层流的同时,内层流也会自动的进行关闭,因此关于内层流的关闭操作可以省略
5、异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try...catch...finally结构处理
6.处理流:
“套接”在已有流的基础之上
2.处理流之二:转换流的使用:(使用步骤同流的使用步骤)
1.转换流(属于字符流):
InputStreamReader:字节输入流转换为字符输入流
new InputStreamReader(new FileInputStream())使用系统默认字符集
new InputStreamReader(new FileInputStream(),charsetName)指明了字符集,由读入文件保存时的字符集决定
OutputStreamWriter:字符的输出流转换为字节的输出流
java.io.InputStreamReader extends Reader
InputStreamReader是字节流通向字符的桥梁,,可以使用的指定的charset将要写入流中的字符编码成字节。(编码:把能看懂的变成看不懂的)
继承自父类共性成员方法:
int read():
从输入流中读取数据的下一个字节
int read(byte[] b):
从输入流中读取一定数量的字节,将其存储在缓冲区数组b中
void close():
关闭此输入流并释放与此年流有关的所有资源
构造方法:
InputStreamReader(InputStream in):
创建一个默认字符集的InputStreamReader
InputStreamReader(InputStream in,String charset)
创建指定字符集的InputStreamReader
参数:
InputStream in:
字节输入流,用于读取文件中保存的字节
String charName:
指定的编码表名称,不区分大小写,
可以是utf-8/UTF-8,gbk/GBK等不指定默认使用utf-8
使用步骤;
1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
2.使用InputStreamReader对象中的方法read读取文件
3.释放资源
注意事项:
构造方法中指定的编码表名称要和文件的编码相同,否则产生乱码
java.io.OutputStreamWriter extends writer
OutputStreamWriter:是字符通向字节流的桥梁,可以使用的指定的charset将要写入流中的字符编码成字节。(编码:把能看懂的变成看不懂的)
继承自父类共性成员方法:
- void write(int c):
写入单个字符
- void write(char[] cbuf):
写入字符数组
- abstract void write(char cbuf,int offset,int len)
写入字符数组某一部分,offset数组开始索引,len写的字符个数
- void write(String str)
写入字符串
- void write(String str,int off,int len)
写入字符串某一部分,offset数组开始索引,len写的字符个数
- void flush()
刷新该流的缓冲
- void close()
关闭此流先要刷新它
构造方法:
OutputStreamWriter(OutputStream out):
创建使用默认字符编码的OutputStreamWriter
OutputStreamWriter(OutputStream out,String charName)
创建使用指定字符集的OutputStreamWriter
参数:
OutputStream out:
字节输出流,可以用来写转换之后的字节到文件中
String charName:
指定的编码表名称,不区分大小写,
可以是utf-8/UTF-8,gbk/GBK等不指定默认使用utf-8
使用步骤:
1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储到缓冲区中(编码)
3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
4.释放资源
2.提供字符流与字节流之间的转换
3.编码与解码:
解码(InputStreamReader):
字节、字节数组 --->字符数组、字符串
字节(看不懂的)-->字符(能看懂的)
编码(按照某种规则将字符存储到计算机中)(OutputStreamWriter):
字符数组、字符串 --->字节、字节数组
字符(能看懂的)-->字节(看不懂的)
字符编码:一套自然语言与二进制数之间的对应规则
4.字符集(由字符编码构成的表):
计算机的底层存储是以二进制存储,为了方便人们使用,让计算机可以识别字符串,于是将数字用于表示字符串,并且一一对应,
于是就形成了一张表,此表就是编码表。常见编码表:
ASCII:
美国标准信息交换码,用一个字节的7位可以表示一个字符,
拓展使用8位表示一个字符,共256个字符,常用128个字符
ISO-8859-1:
拉丁码表,欧洲码表,用一个字节的8位可以表示。兼容ASCII码
GB2312:
中国的中文编码表,最多用两个字节编码所有的字符。
简体中文,兼容ASCII码,收录7000多个汉字
GBK:
中国的中文编码表升级,融合了更多的中文文字符号。
最两个字节编码;以GB2312为基础扩展到21003个汉字,
也支持日韩汉字,使用两个字节存储一个中文{你好-->-55-44,-33-34}
GB19030:
在GBK基础上扩展到70224个汉字,采用多字节编码,
每个字可以采用1个、2个或4个字节组成,同时支持少数民族文字
在中文字符集中字节的区分:
以首位为区分标志,当首位为0,则表示一个字节单独表示一个字符;
当首位为1,则表示两个字节表示一个字符
Unicode:
国际标准码。为每个字符分配唯一的字符码。
所有的文字都用两个字节来表示,表示一个字符集。
由于可能存在存储浪费,或是字符存储不明确等原因。
在具体实现依靠UTF-8/-16/-32。即所有国家的编码,常用utf-8,4个字节
UTF-8:
变长的编码方式,可用1-4个字节来表示一个字符;一个汉字由3个字节存储。
国际标准码表,使用三个字节存储一个中文{你好-->-11-12-13,-19-56-78}
注:
FileReader可以读取IDEA默认编码格式(UTG-8)的文件
FileReader读取系统默认编码(中文GBK)会产生乱码
5.转换流原理
一读:
传统:
硬盘中的文件数据通过字节输入流(FileInputStream)将不同字符集的字节数据交给FileReader,通过FileReader传给java程序FileReader仅查询idea默认的UTF-8表,把字节转换为字符(解码),由于所有字符集转换的格式只有idea默认格式UTF-8故可能产生乱码
使用转换流:
硬盘中的文件数据通过字节输入流(FileInputStream)将不同字符集的字节数据交给InputStreamReader,通过InputStreamReader传给java程序InputStreamReader(是字节流通向字符流的桥梁),可以查询指定的字符集(不限于UTF-8),把字节转换为字符(解码),所以不会产生乱码
一写:
传统:
java程序中的数据通过FileWriter将字符转换为字节(只采用idea仅有的默认UTF-8字符集进行编码),通过FileOutputStream将数据写入硬盘相应文件
使用装换流:
java程序中的数据通过OutputStreamWriter将字符转换为字节(采用指定的字符集进行编码),通过FileOutputStream将数据写入硬盘相应文件
3.处理流之三:对象流的使用:
1.ObjectInputStream
java.io.ObjectInputStream extends InputStream
ObjectInputStream:对象的反序列化流
作用:把文件中保存的对象,以流的方式读取出来
构造方法:
ObjectInputStream(InputStream in):
创建指定InputStream读取的ObjectInputStream
参数:
InputStream in字节输入流
特有的成员方法:
Object readObject()从ObjectInputStream读取对象
使用步骤:
1.创建ObjectInputStream对象,构造方法中传递字节输入流
2.使用ObjectInputStream对象的readObject方法读取保存对象的文件
3.释放资源
4.使用读取出来的对象(打印)
readObject方法抛出了ClassNotFoundException(class文件找不到异常)
当不存在对象的class文件时抛出异常
反序列化前提:
1.类必须实现Serializable
2.必须存在类对应的class文件
2.ObjectOutputStream
java.io.ObjectOutputStream extends OutputStream
ObjectOutputStream:对象序列化流
作用:把对象一流的方式写入文件中保存
构造方法:
ObjectOutputStream(OutputStream out):
创建写入指定OutputStream的ObjectOutputStream
参数:
OutputStream out:字节输出流
特有的成员方法:
void writeObject(Object obj)将指定的对象写入ObjectOutputStream
使用步骤:
1.创建ObjectOutputStream对象,构造方法中传递字节输出流
2.使用ObjectOutputStream对象的writeObject方法把对象写入文件中
3.释放资源
3.作用:
用于存储和读取基本类型数据或对象的处理流,它的强大之处可以把java中的对象写入到数据源中,也能把对象从数据源中还原回来
4.要想一个java对象是可序列化的,需要满足相应的要求
5.序列化与反序列化:
序列化:
将对象从内存持久化保存到磁盘/硬盘中,或者通过网络传输出去
把对象以流的方式写入到文件中保存,叫写对象,也叫对象序列化;对象中不仅仅包含的是字符,使用字节流
ObjectOutputStream:对象的序列化流
对象序列化通过writeObject(对象)将对象从字符转变为字节
反序列化:
将对象从硬盘调入到内存中
把文件中保存的对象,一流的方式读取出来,叫做读对象,也成对象的反序列化
读取的文件保存的都是字节,使用字节流
ObjectInputStream:对象的反序列化
对象的反序列化通过 Object obj=new 类(对象)将文件数据从字节转换为字符(对象)
对象的序列化机制:
允许把内存中的java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地存储在磁盘上,或通过网络将这种二进制流传输到另外一个网络结点。当其他程序获取了这种二进制流,就可以回复成原来的java对象
6.序列化与反序列化的注意事项:
1、序列化和反序列化的时候,会抛出java.io.NotSerializableException没有序列化异常
类通过实现java.io.Serializable接口或实现Externalizable接口以启用其序列化功能。未实现此功能的类将无法使用其任何状态序列化或反序列化
Serializable接口也称标记接口(其内部并未定义任何抽象方法或属性):
要进行序列化和反序列化的类必须实现Serializable接口,就会给了增加一个标记
当进行序列化和反序列化时就会检测类上是否有此标记
有:就可以序列化和反序列化
无:抛出java.io.NotSerializableException异常
需要当前类提供一个全局常量。自定义标识序列版本号:public static final long serialVersionUID = 自定义标识序列L;
使用理由:
serialVersionUID是用于表明类的不同版本间的兼容性,其目的是以序列化对象进行版本控制,有关个版本反序列化时是否兼容。若类没有显式定义serialVersionUID这个静态常量,它的值是java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID可能发生变化,那么在反序列化时可能出错。即java的序列化机制是通过在运行时判断了类的serialVersionUID来验证版本的一致性。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类进行比较如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常(InvalidCastException)
除了当前类需要实现Serializable接口外,还必须保证其内部所有属性也必须是可序列化的(默认情况下,基本数据类型可序列化)
补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量,因为一旦被这两个关键字修饰后,这个属性就不是一个对象私有,而是一个类共有
2、static静态关键字:
静态优先于非静态加载到内存中(静态优先于对象加载到内存)
被static修饰的成员变量不能被序列化,序列化的都是对象
private static int age;
oos.writeObject(new Person("小明",23));
Object o = ois.readObject();
Person{name='小明', age=0}
3、transient瞬态关键字:
被transient修饰的成员变量,不能被序列化
private transient int age;
oos.writeObject(new Person("小明",23));
Object o = ois.readObject();
Person{name='小明', age=0}
4、java.io.InvalidClassException异常:
定义了一个person类实现了Serializable接口,并且实现了构造/get/set方法,编译器java.exe把person.java文件编译生成person.class文件person类实现了Serializable接口,就会根据类的定义给person.class文件添加一个序号serialVersionUID = -7970,生成的person.txt文本中也会存在一个serialVersionUID = -7970序列号。在进行反序列化的时候,会使用person.class文件中的序列号和person.txt文件中的序列号进行比较,如果序列号一直那么反序列化成功,反之则不成功,不成功则抛出java.io.InvalidClassException异常。由此可知:
每次修改类的定义,都会给class文件生成一个新的序列号;若要无论是否对类的定义进行修改都不重新生成新的序列号,那么可以手动给类天机一个序
列号:
格式在Serializable接口规定:
可序列化类可以通过声明为"serialVersionUID"的字段(该字段必须是静态static,是最终final的long型字段)显示声明其自己的serialVersionUID
static final long serialVersionUID =42L; 常量不能改变
4.处理流之四:任意存储文件流的使用:
1.RandomAccessFile直接继承于java.long.Object类,实现了DataInput和DataOutput接口
2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流,用不同的实例化以示区分
3.其构造器
public RandomAccessFile(File file,String mode);
public RandomAccessFile(String name,String mode);
其中mode确定了RandomAccessFile的访问模式:
r:只读方式打开;
rw:打开以便读取和书写
rwd:打开以便读取和书写;同步文件内容的更新
rws:打开以便读取和书写;同步文件内容和元数据的更新
4.若RandomAccessFile作为一个输出流出时,写出到的的文件若不存在,则在执行过程中自动创建;若写出到的文件存在,则会对原有文件内容从首行开始进行覆盖.
5.常用方法:
write():
写或覆盖
long getFilePoint()
获取文件记录指针的当前位置
void seek(long pos)
将文件记录指针定位到pos位置
5.Properties集合的使用:
java.util.Properties集合 extends Hashtable
Properties类表示了一个持久到额属性集,Properties可以保存在流中或从流中加载
Properties集合是唯一一个和IO流相结合的集合
可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
属性列表中每个键及其对应的值都是一个字符串
Properties集合是一个双列集合,key和value默认都是字符串
六、其它流的使用:
1.标准输入/输出流:
1.1基本概念:
System.in:标准输入流,默认从键盘输入
System.out:标准输出流,默认从控制台输出
1.2使用:
System类的serIn(InputStream is)/setOut(PrintStream ps)方式重新指定输入和输出的流
2.打印流:
PrintStream和PrintWriter
提供了一系列重载的print()和println()
java.io.PrintStream:打印流
PrintStream:为其他输出流添加功能,使他们能够方便的打印各种数据值表示形式
PrintStream特点:
1.只负责数据你的输出,不负责数据的读取
2.与其他输出流不同,PrintStream永远不会抛出IOException
3.特有方法:print,println
void print(任意类型值)
void println(任意类型值并换行)
构造方法:
PrintStream(File file):
输出到目的地是一个文件
PrintStream(OutputStream out)
输出到目的地是一个字节流
PrintStream(String fileName)
输出到目的地是一个文件路径
PrintStream extends OutputStream
继承自父类的成员方法:
- public void close():
关闭此输出流并释放与此输出流有关的所有资源
- public void flush():
刷新此输出流并强制任何缓冲的输出字节被写出
- public void write(byte[] b):
将b.long字节从指定的字节数组写入此输出流
- public void write(byte[] b,int off.int long):
从指定的字节数组写入len字节,从偏移量off开始半输出到此输出流
- public abstract void write(int b):
将指定的字节输出流
注:
若使用继承自父类的write方法写数据,那么查看数据的时候会查询编码表97->a
若使用自己特有的方法print/println写数据,写的数据原样输出:97->97
可以改变输出语句的目的地(打印流的流向)
输出语句默认在控制台输出
使用System.setOut方法改变输出语句的目的地改为参数中传递的打印流的目的地
static void setOut(PrintStream out)重新分配“标准”输出流
3.数据流:
DataInputStream和DataOutputStream
作用:
用于读取或写出基本数据类型的变量或字符串,具体实现可以将内存中的字符串、基本数据类型变量写出到文件中
注:
读取不同类型的数据的顺序要与当初保存数据的顺序一致
flush()刷新操作:将内存中的数据写入文件
以上是本篇小节,不喜勿喷,感谢理解
相关链接:
【JAVASE(10)】JAVASE学习--文件(File)类与IO流篇(2)_lixxkv的博客-CSDN博客
【JAVASE(9)】JAVASE学习--泛型篇_lixxkv的博客-CSDN博客