zoukankan      html  css  js  c++  java
  • 【Java中级】(三)IO

    1. 流分为字节流和字符流
    2. 字节流下面常用的又有数据流和对象流
    3. 字符流下面常用的又有缓存流

    文件对象
    文件和文件夹都用File表示
    //file path : 文件的绝对路径或相对路径File file=new File("file path");
    注:文件路径可能不存在
    File的常用方法自行查阅API
    什么是流(Stream),流就是一系列的数据
    当不同的介质之间有数据交互的时候,JAVA就使用流来实现。
    数据源可以是文件,还可以是数据库,网络甚至是其他的程序
    比如读取文件的数据到程序中,站在程序的角度来看,就叫做输入流
    输入流: InputStream
    输出流:OutputStream
    3.1、字节流,关闭流的方式
    以字节的形式读取和写入数据
    所有的数据存放在计算机中都是以数字的形式存放的。 所以字母就需要转换为数字才能够存放。
    比如A就对应的数字65,a对应的数字97. 不同的字母和符号对应不同的数字,就是一张码表。
    ASCII是这样的一种码表。 字包含简单的英文字母,符号,数字等等。 不包含中文,德文,俄语等复杂的。

    3.1.1、输入字节流
    InputStream是字节输入流,同时也是抽象类,只提供方法的生命,不提供方法的实现。
    FileInputStream是InputStream的子类以FIleInputStream为例进行文件读取:
    package stream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    public class TestStream {
    public static void main(String[] args) {
    try {
    //准备文件lol.txt其中的内容是AB,对应的ASCII分别是65 66
    File f =new File("d:/lol.txt");
    //创建基于文件的输入流
    FileInputStream fis =new FileInputStream(f);
    //创建字节数组,其长度就是文件的长度
    byte[] all =new byte[(int) f.length()];
    //以字节流的形式读取文件所有内容
    fis.read(all);
    for (byte b : all) {
    //打印出来是65 66
    System.out.println(b);
    }
    //每次使用完流,都应该进行关闭
    fis.close();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    3.1.2、输出字节流
    OutputStream是字节输出流,同时也是抽象类,只提供方法声明,不提供方法的具体实现。
    FileOutputStream 是OutputStream子类,以FileOutputStream 为例向文件写出数据
    注: 如果文件d:/lol2.txt不存在,写出操作会自动创建该文件。
    但是如果是文件 d:/xyz/lol2.txt,而目录xyz又不存在,会抛出异常
    package stream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    public class TestStream {
    public static void main(String[] args) {
    try {
    // 准备文件lol2.txt其中的内容是空的
    File f = new File("d:/lol2.txt");
    // 准备长度是2的字节数组,用88,89初始化,其对应的字符分别是X,Y
    byte data[] = { 88, 89 };
    // 创建基于文件的输出流
    FileOutputStream fos = new FileOutputStream(f);
    // 把数据写入到输出流
    fos.write(data);
    // 关闭输出流
    fos.close();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    3.1.3、在try中关闭
    在try的作用域里关闭文件输入流,在前面的示例中都是使用这种方式,这样做有一个弊端;
    如果文件不存在,或者读取的时候出现问题而抛出异常,那么就不会执行这一行关闭流的代码,存在巨大的资源占用隐患。 不推荐使用
    package stream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    public class TestStream {
    public static void main(String[] args) {
    try {
    File f = new File("d:/lol.txt");
    FileInputStream fis = new FileInputStream(f);
    byte[] all = new byte[(int) f.length()];
    fis.read(all);
    for (byte b : all) {
    System.out.println(b);
    }
    // 在try 里关闭流
    fis.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    3.1.4、在finally中关闭
    这是标准的关闭流的方式
    1. 首先把流的引用声明在try的外面,如果声明在try里面,其作用域无法抵达finally.
    2. 在finally关闭之前,要先判断该引用是否为空
    3. 关闭的时候,需要再一次进行try catch处理
    这是标准的严谨的关闭流的方式,但是看上去很繁琐,所以写不重要的或者测试代码的时候,都会采用上面的有隐患try的方式,因为不麻烦~
    package stream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    public class TestStream {
    public static void main(String[] args) {
    File f = new File("d:/lol.txt");
    FileInputStream fis = null;
    try {
    fis = new FileInputStream(f);
    byte[] all = new byte[(int) f.length()];
    fis.read(all);
    for (byte b : all) {
    System.out.println(b);
    }
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    // 在finally 里关闭流
    if (null != fis)
    try {
    fis.close();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    }
    3.1.5、使用try()的方式
    把流定义在try()里,try,catch或者finally结束的时候,会自动关闭
    这种编写代码的方式叫做 try-with-resources, 这是从JDK7开始支持的技术
    所有的流,都实现了一个接口叫做 AutoCloseable,任何类实现了这个接口,都可以在try()中进行实例化。 并且在try, catch, finally结束的时候自动关闭,回收相关资源。
    package stream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    public class TestStream {
    public static void main(String[] args) {
    File f = new File("d:/lol.txt");
    //把流定义在try()里,try,catch或者finally结束的时候,会自动关闭
    try (FileInputStream fis = new FileInputStream(f)) {
    byte[] all = new byte[(int) f.length()];
    fis.read(all);
    for (byte b : all) {
    System.out.println(b);
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    综合实例





    3.2、字符流,中文编码问题
    Reader是字符输入流
    Writer是字符输出流
    专门用于字符形式读取和写入数据
    3.2.1、使用字符流读取文件
    FileReader是Reader子类,以FileReader为例进行文件读取
    package stream;
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    public class TestStream {
    public static void main(String[] args) {
    // 准备文件lol.txt其中的内容是AB
    File f = new File("d:/lol.txt");
    // 创建基于文件的Reader
    try (FileReader fr = new FileReader(f)) {
    // 创建字符数组,其长度就是文件的长度
    char[] all = new char[(int) f.length()];
    // 以字符流的形式读取文件所有内容
    fr.read(all);
    for (char b : all) {
    // 打印出来是A B
    System.out.println(b);
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    3.2.2、使用字符流把字符串写到文件
    FileWriter是Writer的子类,以FileWriter为例把字符串写到文件
    package stream;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    public class TestStream {
    public static void main(String[] args) {
    // 准备文件lol2.txt
    File f = new File("d:/lol2.txt");
    // 创建基于文件的Writer
    try (FileWriter fr = new FileWriter(f)) {
    // 以字符流的形式把数据写入到文件中
    String data="abcdefg1234567890";
    char[] cs = data.toCharArray();
    fr.write(cs);
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    3.2.3、常见编码
    工作后经常接触的编码方式有如下几种:
    ISO-8859-1 ASCII 数字和西欧字母
    GBK GB2312 BIG5 中文
    UNICODE (统一码,万国码)

    其中
    ISO-8859-1 包含 ASCII
    GB2312 是简体中文,BIG5是繁体中文,GBK同时包含简体和繁体以及日文。
    UNICODE 包括了所有的文字,无论中文,英文,藏文,法文,世界所有的文字都包含其中
    3.2.4、UNICODE和UTF
    UNICODE因为要存放所有的数据,所以完全按照UNICODE的方式来存储数据,就会有很大的浪费
    在这种情况下,就出现了UNICODE的各种减肥子编码,比如UTF-8对数字和字符就使用一个字节,而对汉字就使用3个字节,从而达到了减肥还能保证健康的效果

    3.2.5、Java采用的Unicode
    写在.java源代码中的汉字,在执行之后,都会变成JVM中的字符。
    而这些中文字符采用的编码方式,都是使用UNICODE.
    3.3、缓存流
    以介质是硬盘为例,字节流和字符流的弊端
    在每一次读写的时候,都会访问硬盘。 如果读写的频率比较高的时候,其性能表现不佳。

    为了解决以上弊端,采用缓存流。
    缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中区读取。

    就好比吃饭,不用缓存就是每吃一口都到锅里去铲。用缓存就是先把饭盛到碗里,碗里的吃完了,再到锅里去铲

    缓存流在写入数据的时候,会先把数据写入到缓存区,直到缓存区达到一定的量,才把这些数据,一起写入到硬盘中去。按照这种操作模式,就不会像字节流,字符流那样每写一个字节都访问硬盘,从而减少了IO操作
    3.3.1、使用缓存流读取数据
    缓存字符输入流 BufferedReader 可以一次读取一行数据
    package stream;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    public class TestStream {
    public static void main(String[] args) {
    // 准备文件lol.txt其中的内容是
    // garen kill teemo
    // teemo revive after 1 minutes
    // teemo try to garen, but killed again
    File f = new File("d:/lol.txt");
    // 创建文件字符流
    // 缓存流必须建立在一个存在的流的基础上
    try (
    FileReader fr = new FileReader(f);
    BufferedReader br = new BufferedReader(fr);
    )
    {
    while (true) {
    // 一次读一行
    String line = br.readLine();
    if (null == line)
    break;
    System.out.println(line);
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    3.3.2、使用缓存流写出数据
    PrintWriter 缓存字符输出流, 可以一次写出一行数据
    package stream;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    public class TestStream {
    public static void main(String[] args) {
    // 向文件lol2.txt中写入三行语句
    File f = new File("d:/lol2.txt");
    try (
    // 创建文件字符流
    FileWriter fw = new FileWriter(f);
    // 缓存流必须建立在一个存在的流的基础上
    PrintWriter pw = new PrintWriter(fw);
    ) {
    pw.println("garen kill teemo");
    pw.println("teemo revive after 1 minutes");
    pw.println("teemo try to garen, but killed again");
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    3.3.3、flush
    有的时候,需要立即把数据写入到硬盘,而不是等缓存满了才写出去。 这时候就需要用到flush
    package stream;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    public class TestStream {
    public static void main(String[] args) {
    //向文件lol2.txt中写入三行语句
    File f =new File("d:/lol2.txt");
    //创建文件字符流
    //缓存流必须建立在一个存在的流的基础上
    try(FileWriter fr = new FileWriter(f);PrintWriter pw = new PrintWriter(fr);) {
    pw.println("garen kill teemo");
    //强制把缓存中的数据写入硬盘,无论缓存是否已满
    pw.flush();
    pw.println("teemo revive after 1 minutes");
    pw.flush();
    pw.println("teemo try to garen, but killed again");
    pw.flush();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }

  • 相关阅读:
    hdu 5352 匈牙利(多重匹配)
    hdu 2112 最短路+stl
    hdu 1811 拓扑排序+并查集+细心
    hdu5407 CRB and Candies
    hdu1018 Big Number
    hdu5410 CRB and His Birthday
    hdu1023 Train Problem II
    hdu4812 D Tree
    hdu1085 Holding Bin-Laden Captive!
    hdu4810 Wall Painting
  • 原文地址:https://www.cnblogs.com/haxianhe/p/9271009.html
Copyright © 2011-2022 走看看