IO技术
_01. IO技术概述
- Output
把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作 - Input
把持久设备上的数据读取到内存中的这个动作称为输入(读)Input操作
_02. File类
1、File类的概述和作用
File类是文件和目录路径名的抽象表示形式。
Java中把文件或者目录(文件夹)都封装成File对象。
我们要去操作硬盘上的文件,或者文件夹只要找到File这个类即可。
2、File类静态的成员变量
- pathSeparator
与系统有关的路径分隔符:
是一个分号;
目录的分割(window中环境变量配置各个路径用分号分割,表示一个完整的路径结束)
Linux中是冒号 :
- separator
与系统有关的默认名称分隔符:
向右 \ 目录名称分割 Linux /
3、File类的构造方法
- File(String pathname)
通过将给定路径名字符串转换为一个File对象,之后可以使用File中的方法.
windows中的路径或文件名不区分大小写.
- File(String parent, String child)
传递路径,传递字符串父路径,字符串子路径
好处: 单独操作父路径和子路径
- File(File parent, String child)
传递路径,传递File类型父路径,字符串子路径
好处: 父路径是File类型,父路径可以直接调用File类方法
4、File类创建文件功能
public boolean createNerFile()
File创建文件的功能:
创建的文件路径和文件名,在File构造方法中给出
文件已经存在了,不在创建
5、File类创建目录功能
- public boolean mkdir()
创建文件夹 如果存在这样的文件夹,就不创建了,返回false
创建的路径也在File构造方法中给出
- public boolean mkdirs()
创建的路径也在File构造方法中给出
文件夹已经存在了,不在创建
可以递归创建多层文件夹
6、File类删除功能
public boolean delete()
删除的文件或者是文件夹,在File构造方法中给出
删除成功返回true,删除失败返回false
删除方法,不走回收站,直接从硬盘中删除
删除文件夹时:文件夹不能有内容
7、File获取功能
- String getName()
返回路径中表示的文件或者文件夹名 - long length()
返回路径中表示的文件的字节数 - String getAbsolutePath()
获取绝对路径,返回String对象 - String getAbsoluteFile()
获取绝对路径,返回File对象. eclipse环境中,写一个相对路径,绝对位置工程根目录 - String getParent()
获取父路径,返回String对象 - File getParentFile()
获取父路径,返回File对象
8、文件的判断功能
- boolean exists()
判断File构造方法中封装路径是否存在 - boolean isDirectory()
判断File构造方法中封装的路径是不是文件夹,如果是文件夹,返回true,不是文件返回false - boolean isFile()
判断File构造方法中封装的路径是不是文件
9、File类list获取功能
- String[] list()
获取到,File构造方法中封装的路径中的文件和文件夹名 (遍历一个目录)
返回只有名字. File[] listFiles()
获取到,File构造方法中封装的路径中的文件和文件夹名 (遍历一个目录)
返回的是目录或者文件的全路径static File[] listRoots()
获取系统中的所有根目录.
windows中即盘符 C:\
例:
@Test
public void testFileList(){
File[] fileArr = File.listRoots();
for(File f: fileArr){
System.out.println(f);
}
File file = new File("c:");
fileArr = file.listFiles();
for (File f : fileArr){
System.out.println(f);
}
String[] strArr = file.list();
System.out.println(strArr.length);
for(String str : strArr){
System.out.println(str);
}
}
10、文件过滤器
作用:
过滤一个目录下的指定扩展名的文件,或者包含某些关键字的文件夹。
方法介绍:
1. public String[] list(FilenameFilter filter)
2. public File[] listFiles(FileFilter filter)
例:
/*
* 自定义过滤器
* 实现FileFilter接口,重写抽象方法
*/
public class MyFilter implements FileFilter{
@Override
public boolean accept(File pathname) {
/*
* pathname 接受到的也是文件的全路径
* c:\\demo\\1.txt
* 对路径进行判断,如果是java文件,返回true,不是java文件,返回false
* 文件的后缀结尾是.java
*/
return pathname.getName().endsWith(".java");
}
}
/*
* File类的获取,文件获取过滤器
* 遍历目录的时候,可以根据需要,只获取满足条件的文件
* 遍历目录方法 listFiles()重载形式
* listFiles(FileFilter filter)接口类型
* 传递FileFilter接口的实现类
* 自定义FileFilter接口实现类,重写抽象方法,
* 接口实现类对象传递到遍历方法listFiles
*/
@Test
public void testFileFilter(){
File file = new File("j:\\");
File[] fileArr = file.listFiles(new MyFilter());
for (File f : fileArr) {
System.out.println(f);
}
}
文件过滤器_原理分析:
*listFiles()遍历目录的同时,获取到了文件名全路径,调用过滤器的方法accept,将获取到的路径 传递给accept方法的参数pathname
* accept方法接收了参数pathname,参数是listFiles传递来的
* 在accept方法中,进行判断,如果这个路径是Java文件,返回true,走着返回false
* 一旦方法返回了true
* listFiles将路径保存到File数组中
11、递归遍历全目录
@Test
public void testGetAllDir(){
File dir = new File("j:\\develop");
getAllDir(dir);
}
public void getAllDir(File dir){
System.out.println(dir);
//调用方法listFiles()对目录,dir进行遍历
File[] fileArr = dir.listFiles();
for (File f : fileArr) {
//判断变量f表示的路径是不是文件夹
if(f.isDirectory()){
getAllDir(f);
}else {
System.out.println(f);
}
}
}
12、遍历目录下的所有java文件
/*
* 自定义过滤器
* 实现FileFilter接口,重写抽象方法
*/
public class MyFilter implements FileFilter{
@Override
public boolean accept(File pathname) {
//判断获取的是目录,直接返回true
if(pathname.isDirectory())
return true;
return pathname.getName().toLowerCase().endsWith(".java");
}
}
@Test
public void testFilterJava(){
getAllJava(new File("j:\\"));
}
public static void getAllJava(File dir){
//调用File对象方法listFiles()获取,加入过滤器
File[] fileArr = dir.listFiles(new MyFilter());
for (File f : fileArr){
if(f.isDirectory()){
//递归进入文件夹遍历
getAllJava(f);
}else{
System.out.println(f);
}
}
}
_03字节输出OutputStream流/字节输入InputStream流
java
1、字节输出流OutputStream
* A: 字节输出流OutputStream
* a.概念
* IO流用来处理设备之间的数据传输
* Java对数据的操作是通过流的方式
* Java用于操作流的类都在IO包中
* 流按流向分为两种:输入流,输出流。
* 流按操作类型分为两种:
* 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
* 字符流 : 字符流只能操作纯字符数据,比较方便,(即处理文本文件)。
* b.IO流常用父类
* 字节流的抽象父类:
* InputStream
* OutputStream
* 字符流的抽象父类:
* Reader
* Writer
* c.IO程序书写
* 使用前,导入IO包中的类
* 使用时,进行IO异常处理
* 使用后,释放资源
* d: 方法介绍
* void close(): 关闭此输出流并释放与此流有关的所有系统资源。
* void write(byte[] b): 将 b.length 个字节从指定的 byte 数组写入此输出流
* void write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
* abstract void write(int b) : 将指定的字节写入此输出流。
2、字节输出流FileOutputStream写字节 与 写字节数组
* A: 字节输出流FileOutputStream写字节
* a: FileOutputStream
* 写入数据文件,学习父类方法,使用子类对象
* b: FileOutputStream构造方法
* 作用:绑定输出的输出目的
* FileOutputStream(File file)
* 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
* FileOutputStream(File file, boolean append)
* 创建一个向指定 File 对象表示的文件中写入数据的文件输出流,以追加的方式写入。
* FileOutputStream(String name)
* 创建一个向具有指定名称的文件中写入数据的输出文件流。
* FileOutputStream(String name, boolean append)
* 创建一个向具有指定 name 的文件中写入数据的输出文件流,以追加的方式写入。
* c: 流对象使用步骤
* 1. 创建流子类的对象,绑定数据目的
* 2. 调用流对象的方法write写
* 3. close释放资源
* d: 注意事项
* 流对象的构造方法,可以创建文件,如果文件存在,直接覆盖
* B: 字节输出流FileOutputStream写字节数组
* a: 方法介绍
* void write(byte[] b): 将 b.length 个字节从指定的 byte 数组写入此输出流
* void write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
例:写字节
@Test
public void testFileOutputStream() throws IOException{
FileOutputStream fos = new FileOutputStream("j:\\test1.txt");
//流对象的方法write写数据
//写1个字节
fos.write(98);
fos.close();
}
例:写字节数组
@Test
public void testFileOutputStreamBtyes() throws IOException{
FileOutputStream fos = new FileOutputStream("j:\\test.txt");
//流对象的方法write写数据
//写字节数组
byte[] bytes = {65,66,67,68};
fos.write(bytes);
//写字节数组的一部分,开始索引,写几个
fos.write(bytes, 1, 2);
//写入字节数组的简便方式
//写字符串
fos.write("hello".getBytes());
fos.close();
}
3、文件的续写和换行符号
* a: 文件的续写
* FileOutputStream构造方法, 的第二个参数中,加入true
* b: 换行符号
* 在文件中,写入换行,符号换行 \r\n
* \r\n 可以写在上一行的末尾, 也可以写在下一行的开头
* linux中为 \n
例:
@Test
public void testXuxie() throws IOException{
File file = new File("j:\\test.txt");
FileOutputStream fos = new FileOutputStream(file, true);
fos.write("nihao\r\n".getBytes());
fos.write("yanshuang".getBytes());
fos.close();
}
4、字节输入流InputStream
* a: 方法介绍
* abstract int read() :
* 从输入流中读取数据的下一个字节。
* int read(byte[] b)
* 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
* int read(byte[] b, int off, int len)
* 将输入流中最多 len 个数据字节读入 byte 数组。
* void close()
* 关闭此输入流并释放与该流关联的所有系统资源。
* java.io.InputStream 所有字节输入流的超类
5、字节输入流FileInputStream读取字节 与 字节数组
* A: 字节输入流FileInputStream读取字节
* a: 方法介绍
* abstract int read() :
* read()执行一次,就会自动读取下一个字节
* 返回值,返回的是读取到的字节, 读取到结尾返回-1
* int read(byte[] b)
* 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
* 读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
* int read(byte[] b, int off, int len)
* 将输入流中最多 len 个数据字节读入 byte 数组。
* void close()
* 关闭此输入流并释放与该流关联的所有系统资源。
* B: 字节输入流FileInputStream读取字节数组
* a: 方法介绍
* int read(byte[] b)
* 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
* 读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
* int read(byte[] b, int off, int len)
* 将输入流中最多 len 个数据字节读入 byte 数组。
例:读字节
@Test
public void testFileInputStream() throws IOException{
FileInputStream fis = new FileInputStream("j:\\test1.txt");
//读取一个字节,调用方法read 返回int
int len = 0;//接受read方法的返回值
while((len = fis.read()) != -1) {
System.out.print((char)len);
}
fis.close();
}
例:读字节数组
@Test
public void testFileInputStreambytes() throws IOException{
FileInputStream fis = new FileInputStream("j:\\test.txt");
// 创建字节数组
byte[] b = new byte[2];
int len = fis.read(b);
System.out.println(new String(b)); //ab
System.out.println(len); //2
len = fis.read(b);
System.out.println(new String(b)); //cd
System.out.println(len); //2
len = fis.read(b);
System.out.println(new String(b)); //ed
System.out.println(len); //1
len = fis.read(b);
System.out.println(new String(b)); //ed
System.out.println(len); //-1
fis.close();
}
以上代码充分说明:字节数组b时一个缓存区。
读取文件:
@Test
public void testFileInputStreambytes() throws IOException{
FileInputStream fis = new FileInputStream("j:\\test1.txt");
// 创建字节数组
byte[] b = new byte[1024];
int len = 0;
while((len = fis.read(b)) != -1){
System.out.print(new String(b));
}
fis.close();
}
6、文件复制
@Test
public void fileCopy(){
long s = System.currentTimeMillis();
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// 建立两个流的对象,绑定数据源和数据目的
fis = new FileInputStream("j:\\1.zip");
fos = new FileOutputStream("h:\\1.zip");
// 定义字节数组,缓冲
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
throw new RuntimeException("文件复制失败");
}finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
throw new RuntimeException("释放资源失败");
}finally {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException("释放资源失败");
}
}
}
long e = System.currentTimeMillis();
System.out.println(e-s);
}
}
7、编码表
* 分类
* 1、ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx
* 2、iso-8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx 负数。
* 3、GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节是负数,第二个字节可能是正数
* GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0
* GB18030:最新的中文码表,目前还没有正式使用。
* 4、unicode:国际标准码表:无论是什么文字,都用两个字节存储。
* Java中的char类型用的就是这个码表。char c = 'a';占两个字节。
* Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。
* 5、UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。
* 6、能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。
* 对于我们开发而言;常见的编码 GBK UTF-8 ISO-8859-1
* 文字--->(数字) :编码。 “abc”.getBytes() byte[]
* (数字)--->文字 : 解码。 byte[] b={97,98,99} new String(b)
_04字符输出流与字符输出流
字符输出流:
- * java.io.Writer* 所有字符输出流的超类
- 写文件,写文本文件
- 字符输出流写数据时,必须要运行一个刷新功能,flush()
1、字符输出流写文本FileWriter类
* a: 方法介绍
* void write(int c)
* 写入单个字符
* void write(String str)
* 写入字符串
* void write(String str, int off, int len)
* 写入字符串的某一部分
* void write(char[] cbuf)
* 写入字符数组
* abstract void write(char[] cbuf, int off, int len)
* 写入字符数组的某一部分
例:
@Test
public void testFileWriter1() throws IOException{
FileWriter fw = new FileWriter("j:\\1.txt");
//写1个字符
fw.write(100);
fw.flush();
//写一个字符数组
char[] c = {'a','b','c','d','e'};
fw.write(c);
fw.flush();
//写字符数组的一部分
fw.write(c, 0, 2);
fw.flush();
//写字符串
fw.write("hello");
fw.flush();
fw.close();
}
2、字符输入流读取文本FileReader类
* a: 方法介绍
* int read()
* 读取单个字符
* int read(char[] cbuf)
* 将字符读入数组
* abstract int read(char[] cbuf, int off, int len)
* 将字符读入数组的某一部分。
例:
@Test
public void testFileReader() throws IOException{
FileReader fr = new FileReader("j:\\test1.txt");
char[] ch = new char[1024];
int len = 0;
while((len = fr.read(ch)) != -1){
System.out.println(new String(ch));
}
fr.close();
}
3、flush()方法和close()方法区别
*a: flush()方法
* 用来刷新缓冲区的,刷新后可以再次写出,只有字符流才需要刷新
*b: close()方法
* 用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出
4、字符流复制文本文件
@Test
public void copyTxtFile(){
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("j:\\test1.txt");
fw = new FileWriter("j:\\test1_1.txt");
char[] ch = new char[1024];
int len = 0;
while ((len = fr.read(ch)) != -1) {
fw.write(ch, 0, len);
fw.flush();
}
} catch (IOException e) {
throw new RuntimeException("复制文本文件失败");
}finally{
if(fw != null){
try {
fw.close();
} catch (IOException ex) {
throw new RuntimeException("释放资源失败");
} finally {
try{
fr.close();
}catch (IOException e) {
throw new RuntimeException("释放资源失败");
}
}
}
}
}
_05转换流
1、字符转字节的过程
* OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节
* 将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去
即:OutputStreamWriter >> OutputStream >> 文件
* OutputStreamWriter
* java.io.OutputStreamWriter 继承Writer类
* 就是一个字符输出流,写文本文件
* write()字符,字符数组,字符串
* 字符通向字节的桥梁,将字符流转字节流
* OutputStreamWriter 使用方式
* 构造方法:
* OutputStreamWriter(OuputStream out)接收所有的字节输出流
* 字节输出流: FileOutputStream
* OutputStreamWriter(OutputStream out, String charsetName)
* String charsetName 传递编码表名字 GBK UTF-8
* OutputStreamWriter 有个子类, FileWriter
例:
@Test
public void testWrite() throws IOException{
//创建字节输出流,绑定文件
FileOutputStream fos = new FileOutputStream("j:\\utf.txt");
//创建转换流对象,构造方法保证字节输出流,并指定编码表是UTF-8
OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
osw.write("你好");
osw.close();
osw = new OutputStreamWriter(new FileOutputStream("j:\\gbk.txt"),"gbk");
osw.write("你好");
osw.close();
}
注:默认编码与工作空间的编码一致。
2、字节转字符流过程
* InputStreamReader
* java.io.InputStreamReader 继承 Reader
* 字符输入流,读取文本文件
* 将字节流转字符流
* 读取的方法:
* read() 读取1个字符,读取字符数组
* 技巧
* OuputStreamWriter写了文件
* InputStreamReader读取文件
* OutputStreamWriter(OutputStream out)所有字节输出流
* InputStreamReader(InputStream in) 接收所有的字节输入流
* 可以传递的字节输入流: FileInputStream
* InputStreamReader(InputStream in,String charsetName) 传递编码表的名字
例:
@Test
public void testReader() throws IOException{
//创建自己输入流,传递文本文件
FileInputStream fis = new FileInputStream("j:\\utf.txt");
//创建转换流对象,构造方法中,包装字节输入流,同时写编码表名
InputStreamReader isr = new InputStreamReader(fis);
char[] ch = new char[1024];
int len = isr.read(ch);
System.out.println(new String(ch,0,len));
isr.close();
isr = new InputStreamReader(new FileInputStream("j:\\gbk.txt"),"gbk");
len = isr.read(ch);
System.out.println(new String(ch,0,len));
isr.close();
}
3、转换流子类父类的区别
* A: 转换流子类父类的区别
* a: 继承关系
OutputStreamWriter:
|--FileWriter:
InputStreamReader:
|--FileReader;
* b: 区别
* OutputStreamWriter和InputStreamReader是字符和字节的桥梁:也可以称之为字符转换流。字符转换流原理:字节流+编码表。
* FileWriter和FileReader:作为子类,仅作为操作字符文件的便捷类存在。
当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。
* 以下三句话功能相同
* InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默认字符集。
* InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"utf-8");//指定GBK字符集。
* FileReader fr = new FileReader("a.txt");
_05缓冲流
提高IO流的读写速度,包括字节缓冲流和字符缓冲流。
1、字节输出流缓冲流BufferedOutputStream
* a: BufferedOutputStream
* 字节输出流的缓冲流
* java.io.BufferedOuputStream 作用: 提高原有输出流的写入效率
* BufferedOuputStream 继承 OutputStream
* 方法,写入 write 字节,字节数组
* 构造方法:
* BufferedOuputStream(OuputStream out)
* 可以传递任意的字节输出流, 传递的是哪个字节流,就对哪个字节流提高效率
例:
@Test
public void testBufferOutputStream() throws IOException{
//创建字节输出流缓冲流的对象,构造方法中,传递字节输出流
BufferedOutputStream bos = new
BufferedOutputStream(new FileOutputStream("j:\\buffer.txt"));
bos.write(55);
byte[] bytes = "HelloWord哎".getBytes();
bos.write(bytes);
bos.write(bytes,0,5);
bos.close();
}
2、字节输入流缓冲流BufferedInputStream
* a: BufferedInputStream
* 字节输入流的缓冲流
* 继承InputStream,标准的字节输入流
* 读取方法 read() 单个字节,字节数组
* 构造方法:
* BufferedInputStream(InputStream in)
* 可以传递任意的字节输入流,传递是谁,就提高谁的效率
* 可以传递的字节输入流 FileInputStream
例:
@Test
public void testBufferInputStream() throws IOException{
BufferedInputStream bis = new
BufferedInputStream(new FileInputStream("j:\\buffer.txt"));
byte[] bytes = new byte[10];
int len = 0;
while((len = bis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
bis.close();
}
3、字节缓冲流文件复制
@Test
public void testBufferedCopy(){
bufferedCopy("j:\\1.zip", "j:\\2.zip");
}
public void bufferedCopy(String src,String desc){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(src));
bos = new BufferedOutputStream(new FileOutputStream(desc));
int len = 0;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
} catch (IOException e) {
throw new RuntimeException();
}finally {
if(bis!=null){
try{
bis.close();
}catch (IOException ex){
throw new RuntimeException();
}finally {
try{
bos.close();
}catch(IOException ex){
throw new RuntimeException();
}
}
}
}
}
4、字符输出流缓冲流BufferedWriter
* 字符输出流缓冲流BufferedWriter
* a: BufferedWriter
* 字符输出流缓冲区流
* java.io.BufferedWriter 继承 Writer
* 写入方法 write () 单个字符,字符数组,字符串
* 构造方法:
* BufferedWriter(Writer w)传递任意字符输出流
* 传递谁,就高效谁
* 能传递的字符输出流 FileWriter, OutputStreamWriter
例:
public class BufferWriterDemo {
public static void main(String[] args) throws IOException {
BufferedWriter bfw = new BufferedWriter(new FileWriter("j:\\buf.txt"));
bfw.write(100);
bfw.flush();
bfw.write("你好");
bfw.flush();
//文本中的换行,系统无关性
bfw.newLine();
bfw.flush();
bfw.write("严霜".toCharArray());
bfw.close();
}
}
5、字符输出流缓冲流BufferedWriter
public class BufferedReaderDemo{
public static void main(String[] args) throws IOException{
int lineNumber = 0;
BufferedReader bfr = new BufferedReader(new FileReader("j:\\buf.txt"));
//调用缓冲流的方法 readLine()读取文本行
String line = null;
while((line = bfr.readLine()) != null){
lineNumber++;
System.out.println(lineNumber+" "+line);
}
bfr.close();
}
}
_06 Properties集合
1、Properties集合简介:
* A: Properties集合的特点
* a: Properties类介绍
* Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串
* b: 特点
* Hashtable的子类,map集合中的方法都可以用。
* 该集合没有泛型。键值都是字符串。
* 它是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化的设备(硬盘、U盘、光盘)上。键值的来源也可以是持久化的设备。
* 有和流技术相结合的方法。
* c: 方法介绍
* load(InputStream inputStream) 把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中
* load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)
* store(OutputStream outputStream,String commonts) 把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息
* stroe(Writer writer,String comments) 以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符
2、Properties集合存储键值对
/*
* 使用Properties集合,存储键值对
* setProperty等同于Map接口中的put
* setProperty(String key, String value)
*
* 获取键值对,getProperty(String key)
*/
@Test
public void testProperties1(){
Properties pro = new Properties();
pro.setProperty("a","1");
pro.setProperty("b", "2");
pro.setProperty("c", "3");
System.out.println(pro);
String value = pro.getProperty("c");
System.out.println(value);
//方法stringPropertyNames,将集合中的键存储到Set集合,类似于Map接口的方法keySet
Set<String> set = pro.stringPropertyNames();
for (String key : set){
System.out.println(key+"..."+pro.getProperty(key));
}
}
}
3、Properties集合的方法load
/*
* Properties 集合特有方法 load
* load(InputStream in)
* load(Reader r)
* 传递任意的字节或字符流
* 流对象兑取文件中的键值对,保存到集合中
*/
@Test
public void testProperties_load()throws IOException{
Properties pro = new Properties();
FileReader fr= new FileReader("j:\\test.properties");
//调用集合的方法load,传递字符输入流
pro.load(fr);
fr.close();
System.out.println(pro);
}
4、Properties集合的方法store
@Test
public void testProperties_store()throws IOException{
Properties pro = new Properties();
pro.setProperty("nihao", "hello");
pro.setProperty("email", "[email protected]");
FileWriter fw = new FileWriter("j:\\test.properties");
//键值对,存回文件,使用集合的方法store传递字符输出流
pro.store(fw, "");
System.out.println(pro);
}
}
_07 对象的序列化与反序列化
* A: 对象的序列化与反序列化
* a: 基本概念
* 对象的序列化
* 对象中的数据,以流的形式,写入到文件中保存过程称为写出对象,对象的序列化
* ObjectOutputStream将对象写到文件中,实现序列化
* 对象的反序列化
* 在文件中,以流的形式,将对象读出来,读取对象,对象的反序列化
* ObjectInputStream 将文件对象读取出来
注:
- 静态不能序列化:
* 原因:
* 序列化是把对象数据进行持久化存储
* 静态的东西不属于对象,而属于类
- transient关键字
* 作用:
* 被transient修饰的属性不会被序列化
* transient关键字只能修饰成员变量
1、ObjectOutputStream流写对象与ObjectInputStream流读对象
@Test
public void testObjectStream() throws IOException, ClassNotFoundException{
/*
* ObjectOutputStream
* 构造方法: ObjectOutputStream(OutputSteam out)
* 传递任意的字节输出流
* void writeObject(Object obj)写出对象的方法
*/
//创建字节输出流,封装文件
FileOutputStream fos = new FileOutputStream("j:\\person.txt");
//创建写出对象的序列化流的对象,构造方法传递字节输出流
ObjectOutputStream oos = new ObjectOutputStream(fos);
Person p = new Person("ailisi",19);
//调用序列化流的方法writeObject,写出对象
oos.writeObject(p);
oos.close();
/*
* ObjectInputStream
* 构造方法:ObjectInputStream(InputStream in)
* 传递任意的字节输入流,输入流封装文件,必须是序列化的文件
* Object readObject() 读取对象
*/
FileInputStream fis = new FileInputStream("j:\\person.txt");
//创建反序列化流,构造方法中,传递字节输入流
ObjectInputStream ois = new ObjectInputStream(fis);
//调用反序列化流的方法 readObject()读取对象
Object obj = ois.readObject();
System.out.println(obj);
ois.close();
}
给需要序列化的类上加标记。该标记中没有任何抽象方法
2、Serializable接口的含义
- 作用:给需要序列化的类上加标记。该标记中没有任何抽象方法
- 给需要序列化的类上加标记。该标记中没有任何抽象方法
- 只有实现了 Serializable接口的类的对象才能被序列化
3、序列化中的序列号冲突问题
- 问题产生原因:
- 当一个类实现Serializable接口后,创建对象并将对象写入文件,之后更改了源代码(比如:将成员变量的修饰符有private改成public),再次从文件中读取对象时会报异常。
- 编译器,根据类的定义,会在class文件中计算一个序列号出现
- 新编译后的class文件中序列号,与原来的文件person.txt中的序列号不同。
3、序列化中自定义的序列号
public class Person implements Serializable{
public String name;
public /*transient阻止成员变量序列化*/ int age;
//类,自定义了序列号,编译器不会计算序列号
private static final long serialVersionUID = 1478652478456L;
public Person(String name, int age){
this.name=name;
this.age = age;
}
public Person(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
_08 打印流
1、打印流和特性
- a: 概述
- 打印流添加输出数据的功能,使它们能够方便地打印各种数据值表示形式.
- 打印流根据流的分类:
- 字节打印流 PrintStream
- 字符打印流 PrintWriter
- 方法:
- void print(String str): 输出任意类型的数据,
- void println(String str): 输出任意类型的数据,自动写入换行操作
- b: 特点
- 此流不负责数据源,只负责数据目的
- 为其他输出流,添加功能
- 永远不会抛出IOException,但是可能抛出别的异常
- 两个打印流的方法,完全一致
- 构造方法,就是打印流的输出目的端
- PrintStream构造方法
- 接收File类型,接收字符串文件名,接收字节输出流OutputStream
- PrintWriter构造方法
- 接收File类型,接收字符串文件名,接收字节输出流OutputStream, 接收字符输出流Writer
2、打印流输出目的是File对象
@Test
public void testPrintWriter() throws FileNotFoundException{
/*
* 打印流,向File对象的数据目的写入数据
* 方法print println 原样输出
* write方法走码表
*/
File file = new File("j:\\file.txt");
PrintWriter pw = new PrintWriter(file);
pw.println(true);
pw.write(100);
pw.close();
}
3、输出语句是char数组
@Test
public void testPrintWriterDemo(){
int[] arr={1};
System.out.println(arr);
char[] ch = {'a','b','c'};
System.out.println(ch);
byte[] b = {};
System.out.println(b);
}
- 结果分析
- println数组,只有打印字符数组时只有容,其余均打印数组的地址
- 因为api中定义了打印字符数组的方法,其底层是在遍历数组中的元素
- 而其他打印数组的方法,都是将数组对象编程Object,其底层再将对象编成String,调用了String s = String.valueOf(x);方法
4、打印流开启自动刷新
@Test
public void testPrint() throws FileNotFoundException{
/*
* 打印流,可以开启自动刷新功能
* 满足2个条件:
* 1. 输出的数据目的必须是流对象
* OutputStream Writer
* 2. 必须调用println,printf,format三个方法中的一个,启用自动刷新
*/
FileOutputStream fos = new FileOutputStream("j:\\6.txt");
PrintWriter pw = new PrintWriter(fos,true);
pw.println("I");
pw.println("love");
pw.println("you");
pw.close();
}