Java基础之输入输出流

目录

1. 流是什么?

2 流的分类

3 File类

4 四个流父类

5. FileInputStream和FileOutputStream类

 6 异常在IO操作中的应用

7 FileWriter、FileReader与BufferedReader、BufferedWriter

8 使用第三方插件

9 序列化和反序列化

 10 资源文件

11 Properties类

12 封装操作资源文件的工具类


1. 是什么?

        流是通道。在Java中流是提供数据传输的通道。

2 流的分类

        按不同的方式将流进行了不同的分类:

        ① 按方向:参照物是内存输入流和输出流。

            编写一个程序,需要读文件中的内存到程序中,需要使用输入流。写文件用输出流。

        ② 按流量:字节流和字符流。

            1个字符等于2个字节。

            一般字符流都是用来操作文本数据。(文本文件)

            一般字节流都是用来操作二进制数据。(声音,图片,视频)

        最终我们可以得到流应用中的4个父类字节输入,字节输出,字符输入,字符输出。

        ③ 扩展分类:按功能分类:节点流和过滤流。

            节点流是直接操作源对象的流对象。

            过滤流是是操作流对象的流对象。为流对象附加功能。

3 File类

        因为在Java中使用流对象,操作文件是最多的使用方式。

        File是一个用来表示文件或目录的类。

3.1 构造方法

public File(String pathname)

        通过将给定的路径名字符串转换为抽象路径名来创建新的File实例。

        String数据类型的参数:在编写路径过程中分隔符注意使用“/”或“\\”。

File file = new File("E:/photo/1801971.gif");

 3.2 二个静态常量

        目录分隔符:一个路径中每级目录之间的分隔。File.separator:符号\

        路径分隔符:多个路径之间分隔的符号:File.pathSeparator:符号;

四个流父类

        字节与字符。输入与输出。

        在Java中为以下四个类分别创建了父类

            字节输入:InputStream

            字节输出:OutputStream

            字符输入:Reader

            字符输出:Writer

        以上的四个父类都是抽象类。都需要使用父类的子类才可以使用。

        每一个子类都对应一种数据源对象。

        例如:操作文件的输入流,FileInputStream。

        流操作的基本流程分三步:打开流对象;操作流对象;关闭流对象(一定要执行)

5. FileInputStream和FileOutputStream类

        FileInputStream和FileOutputStream 是操作文件的字节流。

        字节流每次操作一个字节。字节是byte,基本数据类型,从-128~127

        字节是计算机文件的最小单位。使用字节流可以操作任意类型的文件。

public static void main(String[] args) throws IOException {
    //第一步:打开
    FileInputStream fis = new FileInputStream("F:/Oracle-Cork.jpg");
    FileOutputStream fos = new FileOutputStream("F:/Cork.jpg");
    //第二步:操作
    byte[] bytes = new byte[1024];//1024个字节的数组。1KB
    int len = -1;//len表示本次读了多少个字节。
    while ((len = fis.read(bytes)) != -1) {
        fos.write(bytes,0,len);
    }
    //第三步:关闭
    fos.flush();//清空缓存
    fos.close();
    fis.close();
    System.out.println("end");
}

 6 异常在IO操作中的应用

        异常:try-catch-finally,可能路径不存在,打开错误。

        IO操作过程中一定要有关闭的过程。一定要执行的部分(finally)。

        第一版:旧的。

public static void main(String[] args){
    //第一步:打开
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
        fis = new FileInputStream("F:/Oracle-Cork.jpg");
        fos = new FileOutputStream("F:/Cork.jpg");
        //第二步:操作
        byte[] bytes = new byte[1024];//1024个字节的数组。1KB
        int len = -1;//len表示本次读了多少个字节。
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }
    }catch (IOException e){
        e.printStackTrace();
    }finally {
        //第三步:关闭
        try {
            if(fos!=null) {
                fos.flush();//清空缓存
                fos.close();
            }
            if(fis!=null) {
                fis.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    System.out.println("end");
}

        第二版:新的方式:try-resources方式。

        使用这种新格式,可以自动实现流对象的关闭。

try(声明流对象,这个流对象在使用完成之后。可以自动关闭。){

        try块的代码,流对象的操作。

}cathc(Exception e){

        e.printStackTrace();

}

public static void main(String[] args){
    try(//第一步:打开
        FileInputStream fis = new FileInputStream("F:/Oracle-Cork.jpg");
        FileOutputStream fos = new FileOutputStream("F:/Cork.jpg"); ) {
        //第二步:操作
        byte[] bytes = new byte[1024];//1024个字节的数组。1KB
        int len = -1;//len表示本次读了多少个字节。
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }
    }catch (IOException e){
        e.printStackTrace();
    }
    System.out.println("end");
}

7 FileWriter、FileReader与BufferedReader、BufferedWriter

        ① FileWriter 字符输出流;FileReader 字符输入流。

        字符流一般用来操作文本文件。每次读写一个字符。

        ② BufferedReader:带缓存的字符输入流;BufferedWriter:带缓存的字符输出流。

        这二个是过滤流对象。不直接操作源对象。直接操作的是另一个流对象。

        过滤流是对节点流功能的扩展。Buffered是扩展的缓存。

public class FileReaderTest {
    public static void main(String[] args) {
        try (FileReader fileReader = new FileReader("F:/b.txt");//节点流
             BufferedReader br = new BufferedReader(fileReader);//过滤流
        ) {
            while(br.ready()) {
                String s = br.readLine();
                System.out.println(s);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
public class FileWriterTest {
    public static void main(String[] args) {
        try (FileWriter fw = new FileWriter("F:/b.txt");
             BufferedWriter bw = new BufferedWriter(fw)) {
            bw.write("这是一行文本!!");
            bw.newLine();
            bw.write("这是一行新文本!!!");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

使用第三方插件

        commons-io.jar 这是第三方提供的Jar包。

        Jar包是个class文件的压缩包。可以在Java工程中导入,放在lib目录中。

public static void main(String[] args) {
        try {
            FileUtils.copyFile(
                    new File("f:/Cork.jpg"),
                    new File("f:/Cork-1.jpg"));
            System.out.println("end");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
public static void main(String[] args) {
        try {
            IOUtils.copy(
                    new FileInputStream("F:/Oracle-Cork.jpg"),
                    new FileOutputStream("F:/Cork-2.jpg"));
            System.out.println("end");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

序列化和反序列化

9.1 什么叫序列化和反序列化

        序列化:将对象保存到文件的过程称为序列化。

        反序列化:从文件中读一个对象的客称为反序列化。

9.2 序列化接口Serializable

        接口表示了一种能力。当我们自己编写的类实现了某一个接口就表示具备有某一种能力。

 public interface Serializable {}

        这个接口中没有任何方法。只表示了一种能力。

        我们自己编写的类。实现了Serializable接口,才能被序列化和反序列化。 

/**
 * Goods类实现了Serializable接口。表示Goods类可以被序列化和反序列化。
 */
public class Goods implements Serializable {
    private Integer id;
    private String name;
    private Double price;

    private Type type;

}

 9.3 序列化使用的流对象

        序列化操作是写文件:输出

        对象的类型是很多种,所以使用字节流

        序列化是将对象保存到文件的过程。使用操作文件的流对象。

        能确定第一个节点流对象:FileOutputStream.

        还需要一个过滤流对象:ObjectOutputStream.

public static void main(String[] args) {
    try (
            FileOutputStream fos = new FileOutputStream("F:/obj.data");
            ObjectOutputStream oos = new ObjectOutputStream(fos)
    ) {
        Goods goods = new Goods(1,"小米13Pro",3900D);
        //可以使用集合
        oos.writeObject(goods);
        System.out.println("end");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

9.4 反序列化使用的流对象

        反序列化操作是读文件:输入。

        能确定第一个节点流对象:FileInputStream.

        还需要一个过滤流对象:ObjectInputStream.

public class TestObjectInputStream {
    public static void main(String[] args) {
        try(FileInputStream fis=new FileInputStream("F:/obj.data");
            ObjectInputStream ois=new ObjectInputStream(fis)
        ) {
            Goods goods = (Goods) ois.readObject();
            System.out.println(goods);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

 10 资源文件

        资源文件是一个以.properties为后缀的文本文件。

        资源文件还是一个Key-Value的文本文件。一定要符合Map接口的格式。

        在资源文件中所有内容都是如下格式编写的:

         中文转码的工具是:jdk/bin/native2ascii.exe

11 Properties类

        Properties类是用来专门操作资源文件的类。

        Properties是Map接口的一个实现类,也是一种Key-Value的集合类

        我们使用Properties对象来加载资源文件中的内容。

        加载的过程需要使用到流对象进行文件加载。

        ① 构造方法

public Properties()

        创建一个没有默认值的空属性列表。

Properties properties = new Properties();

        ② 加载资源文件

        将一个资源文件(.properties)中内容全部加载到Properties对象中。

public void load(InputStream inStream) throws IOException{ }

        从输入字节流读取属性列表(键对元素)。

        优化路径:在使用流对象时,不要使用绝对路径。使用当前类的路径。

InputStream is = PropertiesTest.class.getResourceAsStream("/test.properties");
properties.load(is);

getResourceAsStream()基于当前类的路径位置去创建流对象。

/test.properties /表示的是类路径的根目录。src是源文件的根目录

        ③ 获取资源文件中的值。按Key取Value。

public String getProperty(String key)

        使用此属性列表中指定的键搜索属性。

String username = properties.getProperty("username");
System.out.println(username);
String password = properties.getProperty("password");
System.out.println(password);

12 封装操作资源文件的工具类

        Properties类是用来操作资源文件的类。

        我们可以将使用Properties实现的具体的功能封装成一个工具类。

        ① 操作资源文件都有哪些行为?和写。

        ② 使用Properties操作资源文件。在类中声明Properites对象。

        ③ 因为这是一个工具类,没必要创建实例。都使用static。

/**
 * 这是一个封装操作资源文件的工具类
 */
public class PropertiesUtils {
    private final static Properties PROPERTIES = new Properties();
    static {
        //加载资源文件
        try(InputStream is = PropertiesUtils.class.getResourceAsStream("/test.properties")
        ) {
            PROPERTIES.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 按Key取Value的方法
     * @param key 关键字
     * @return Value值,如果没有对应的Key,返回null
     */
    public static String getProperty(String key){
        return PROPERTIES.getProperty(key);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值