Java学习之【IO流】

简介

1、什么是IO?

(1)I:Input

(2)O:Output

(3)通过IO可以完成硬盘文件的读写

2、IO流的分类

(1)按照流的方向:(以内存为参照物)

a.往内存中去,叫做输入(Input),或者叫读(Read)

b.从内存中出来,叫做输出(Output),或者叫写(Write)

(2)按照读取数据方式:

a.按照字节的方式读取数据,一次读取1个字节byte,等同一次读取8个二进制码,这种流是万能的,什么类型的文件都可以读取。【字节流】

b.按照字符的方式读取数据,一次读取一个字符,这种流是为了方便读取普通文本文件.txt而存在的。【字符流】

3、java中所有的流都在:java.io.*;下

4、IO流的类

(1)字节流【以Steam结尾】

a. java.io.InputStream

b. java.io.OutputStream

(2)字符流【以Reader和Writer结尾】

a. java.io.Reader

b. java.io.Writer

5、所有的流都实现了:java.io.Closeable接口,都是可关闭的,都有close()方法。【流是一个管道,是内存和硬盘之间的通道,用完之后一定要关闭,不然会耗费(占用)很多资源。】

6、所有的输出流都实现了:java.io.Flushable接口,都是可刷新的,都有flush()方法。输出流在最终输出之后,一定要记得flush()刷新一下,这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用就是清空管道。

7、主要使用的流:

(1)文件专属

java.io.FileInputStream

java.io.FileOutputStream

java.io.FileReader

java.io.FileWriter

(2)转换流:将字节流转换成字符流

java.io.InputStreamReader

java.io.OutputStreamWriter

(3)缓冲流专属

java.io.BufferedReader

java.io.BufferedWriter

java.io.BufferedInput

java.io.BufferedOutput

(4)数据流专属

java.io.DataInputStream

java.io.DataOutputStream

(5)标准输出流

java.io.PrintWriter

java.io.PrintReader

(6)对象专属流

java.io.ObjectInputStream

java.io.ObjectOutputStream

 FileInputStream

介绍

1、文件字节输入流,万能的,任何类型的文件都可以采用这个流来读

2、字节的方式,完成输入的操作,完成读的操作。

创建文件字节输入流对象

        FileInputStream fis = null;
        try {
            // 采用了绝对路径,D:/Windows/新建文本文档.txt  这种形式也可以
            fis = new FileInputStream("D:\\Windows\\新建文本文档.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally{ // 在finally语句块中确保流一定关闭!
            if(fis != null){
            // 关闭前提:流不是null的时候关闭,避免空指针异常
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

注意:IDEA中的默认路径(相对路径):Project的根 

常用方法

available()

语法规则

// int available()
// 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。
System.out.println(fis.available()); // 6,因为文本中只存储了6个英文字符

常用用法【一次性读取文件所有数据】

// 这种方法不适合太大的文件,因为byte[]数组不能太大
// 一次性读取文件所有数据
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
String s = new String(bytes);
System.out.print(s);

skip(long n)

语法规则

//  long skip(long n)
// 从输入流中跳过并丢弃 n 个字节的数据,并返回实际跳过的字节数
System.out.println(fis.skip(3));

read()

read()

// read()方法读取一个字节,并返回其ASCII码
System.out.println(fis.read()); // 结果为97,因为第一个字符为a,其ASCII码为97

 read(byte[] b)

// read(byte[] b)方法是将字节读入byte数组,并返回读入数组的字节数 System.out.println(fis.read(bytes)); // 4,因为定义的byte数组长度为4

int read(byte[] b, int off, int len)
// 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中,并返回当前读入的字节数
int count = 0;
while((count = fis.read(bytes)) != -1){ // 将文本中所有信息输出
    //System.out.println(fis.read(bytes,0,count));
    String s = new String(bytes,0,count);
    System.out.print(s);
}

FileOutputStream

1、文件字节输出流,万能的,任何类型的文件都可以采用这个流来读

2、字节的方式,完成输出的操作,完成写的操作。

3、写完之后一定要刷新:flush()

创建文件字节输出流

第一种【会清空原有数据】

// 若是没有FileOutputStreamTest.txt文件,则会新建
// 这种方法谨慎使用,这种方式会先将源文件清空,然后重新写入
fos = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\FileOutputStreamTest.txt");

 第二种【推荐】

FileOutputStream(String name, boolean append)
name - 与系统有关的文件名
append - 如果为 true,则将字节写入文件末尾处,而不是写入文件开始处
// 以追加的方式,不会清空原文件内容
fos = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\FileOutputStreamTest.txt",true);

常用方法 

write(byte[] b)

// void write(byte[] b)
// 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
// 将bytes数组写入到文件中
fos.write(bytes);
fos.flush();

write(byte[] b, int off, int len) 

// void write(byte[] b, int off, int len)
// 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
fos.write(bytes,0,3);
fos.flush();

write(int b) 

// void write(int b)
// 将指定字节写入此文件输出流。
fos.write(97);
fos.flush();

BufferedReader

介绍

1、带有缓冲区的字符输入流

2、使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组。自带缓存

3、当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流

4、外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流

5、对于包装流来说,只需要关闭最外层就行,里面的节点流会自动关闭

构造方法

// 节点流
FileReader out = new FileReader("Test/src/IOTest/IOTest03/IOTest.java");
// 包装流
BufferedReader in = new BufferedReader(out);

合并写法:

BufferedReader in = new BufferedReader(new FileReader("Test/src/IOTest/IOTest03/IOTest.java"));

常用方法 

readLine()

作用:读取一个文本行,但不带换行符

System.out.println(in.readLine());
String nowLine = null;
while((nowLine = in.readLine()) != null){
    System.out.println(nowLine);
}

BufferedWriter 

用法参考BufferedReader

转换流

使用方式

// 字节流
FileInputStream fis = new FileInputStream("Test/src/IOTest/IOTest03/IOTest.java");
// 通过转换流转换(将字节流转换为字符流)
// in是节点流,isr是包装流
InputStreamReader isr = new InputStreamReader(fis);
// isr是节点流,bfr是包装流
BufferedReader bfr = new BufferedReader(isr);

合并写法:

BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream("Test/src/IOTest/IOTest03/IOTest.java")));

文件拷贝【文件复制】

原理

1、需要用到内存,将数据从源硬盘处读取到内存中,再将内存中读到的数据写入目标硬盘中。【这个过程是一边读一边写】

具体实现

// 输入文件流
fis = new FileInputStream("D:\\BaiduNetdiskDownload\\Java零基础教程\\动力节点Java零基础经典教程\\Java零基础四部曲\\第二部曲\\001-我们要学什么目标是啥.avi");
// 输出文件流
fos = new FileOutputStream("D:\\001-我们要学什么目标是啥.avi");
// 1MB(一次最多拷贝1MB)
byte[] bytes = new byte[1024 * 1024];
// 核心:一边读一边写
int count = 0;
while((count = fis.read(bytes)) != -1){
    fos.write(bytes,0,count);
}
// 刷新,输出流最后要刷新
fos.flush();

数据流专属

介绍

1、用DataInputStream写的文件,只能用DataOutputStream去读,并且读的时候需要提前知道写入的顺序。读的顺序要和写的顺序一致,才能正常读出数据。

标准流

1、标准流不需要手动关闭,会自动关闭

java.io.PrintStream

两种写法

1、System.out.println(“”);

2、PrintStream ps = System.out

        ps.println("");

改变输出方向

将输出指定到目标文件【一般作为日志工具】

System.setOut(new PrintStream(new FileOutputStream("文件目录")));

对象流

序列化和反序列化

1、参与序列化和反序列化的对象,必须实现Serializable接口,这个接口中什么代码也没有,起到标识作用,使Java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇。

2、Java虚拟机看到Serializalbe这个接口,会为该类自动生成一个序列化版本号

3、序列化版本号:

(1)java中区别类:首先类名对比,类名相同,比较序列化版本号

(2)自动序列化版本号:缺陷:源代码确定之后,不能修改,一旦修改,必然重新编译,此时会生成全新的序列化版本号,这时Java就认为是全新的类。

(3)建议自己手写序列化版本号:

private static final long serialVersioUID = 序列化版本号;

(4)IDEA工具自动化生成序列化版本号:File->Settings->Editor->Code Style->Inspections->搜索Serializable class without ‘serialVersionUID’ 

序列化(Serialize)

1、将内存中的Java对象的状态保存下来的过程。

2、ObjectOutputStream

3、单个对象实现序列化

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student"));
Student s = new Student("张三", "02111");
// 将Student对象写入
oos.writeObject(s);
// 刷新
oos.flush();
// 关闭
oos.close();

4、多个对象实现序列化

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student"));
List stuList = new ArrayList<>();
stuList.add(new Student("张三", "0211"));
stuList.add(new Student("张三", "0212"));
stuList.add(new Student("张三", "0213"));
// 写入
oos.writeObject(stuList);
// 刷新
oos.flush();
// 关闭
oos.close();

反序列化(DeSerialize)

1、将硬盘上的数据重新恢复到内存中,恢复成Java对象。

2、ObjectInputStream

3、单个对象实现反序列化

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("student"));
// 获取对象
Object obj = ois.readObject;
// 输出对象信息
System.out.println(obj);
// 关闭
ois.close();

4、多个对象实现反序列化

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("student"));
// 获取List对象
List stuList = (List)ois.readObject();
// 遍历List对象,输出每个Student对象信息
for(Student stu : stuList){
    System.out.println(stu);
}
// 关闭
ois.close();

transient关键字 

1、修饰成员变量,表示游离的,不参与序列化

IO和Properties联合使用

简介

(1)IO:文件的读和写

(2)Properties:是一个Map集合,key和value都是String类型

作用

(1)将某个文件中的数据加载到Properties对象当中

(2)Java中经常变动的信息,可以单独写到一个文件中,使用程序动态读取,将来只需要修改这个文件的内容,java代码不需要改动,不需要重新编译,服务器也不需要重启,就可以拿到动态数据,这种文件被称为配置文件当配置文件中内容格式为【key=value】时,称为属性配置文件。(3)java规范要求:属性配置文件要以properties结尾,但这不是必须的。Properties是专门存放属性配置文件内容的一个类。

(4)属性配置文件

a.key和value中不要有空格

错误:key  =  value

正确:key=value或key:value【不建议使用冒号】

b.#是注释符号

c.key重复,则value自动覆盖

实现

// 新建一个输入流对象
FileReader reader = new FileReader("Test/src/IOTest/IOTest06/username");

// 新建一个Map集合
Properties pro = new Properties();

// 调用Properties中的load()方法将文件中的数据加载到Map集合中
pro.load(reader);

// 通过key来获取value
System.out.println(pro.getProperty("username"));
System.out.println(pro.getProperty("password"));

File类

介绍

1、Flie类不能完成读和写

2、File对象代表文件和目录路径名的抽象表示形式。一个File对象有可能是对应的目录也可能是文件。

File类中常用方法

构造方法

File f1 = new File("C:/windows");

exists()

若目录存在,返回true,若不存在,返回false

f1.exists();

createNewFile()

以文件形式新建

f1.createNewFile()

 mkdir()

以目录形式新建

f1.mkdir()

mkdirs()

以多重目录形式新建

f1.mkdirs()

getParent()

获取文件的父路径

f1.getParent()

getAbsolutePath()

获取绝对路径 

f1.getAbsolutePath()

 getName()

获取文件名

f1.getName()

isDirectory()

判断是否为目录 

f1.isDirectory() 

 lastModified()

获取文件最后一次修改时间【返回毫秒数,是1970年到现在的毫秒数】

f1.lastModified()

 length()

获取文件大小

f1.length()

 listFile()

获取当前目录下的所有子文件【返回File类型数组】

f1.listFile()

你可能感兴趣的:(Java学习,java,学习)