Java的IO常用类

一、File类

1.1 概述

File类:java中IO包中的唯一的一个与文件本身操作有关的类,利用这个File类,我们可以创建文件或者文件夹,修改文件或者文件的名称等操作。

1.2 操作

构造器:

File(File parent, String child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(URI uri)
通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。

常用的方法:

  • createNewFile():用来创建文件
  • delete():删除文件
  • exists():判断此文件是否存在,如果存在则返回true如果不存在则返回false
  • mkdir():用来创建单层文件夹
  • mkdirs():用来创建多层文件夹
  • isDirectory():判断文件是否是一个文件夹,如果是则返回true
  • listFiles():返回当前文件夹下面所有的文件对象,返回的结果是一个File[]类型
  • getAbsolutePath():获取当前文件的绝对路径
  • getName():返回文件或者文件夹本身的名称
  • getParent():返回上一级目录的名称:
  • getParentFile():返回上一级目录的File对象
  • isHidden():判断此文件是否是隐藏文件
  • lastModified():以毫秒数返回文件的最后一次修改时间
  • length():返回文件的长度,也就是字节数
public static void main(String[] args) throws IOException {
        File file = new File("E:"+File.separator+"hello.txt");//用系统名称分隔符
        file.createNewFile();
        //file.delete();//用此方法的文件是直接删除了,不会回到回收站里
        File file1 = new File("E:\\ha\\ha\\ha");
        file1.mkdirs();
        file.getName().endsWith(".txt");
        File[] files = File.listRoots();
        for (File f:files){
            System.out.println("hello");
            System.out.println(f.toString());
        }
        System.out.println("ok");
    }

二、字节流

####字符流与字节流的区别:

​ 1.字节流可以操作任何类型的数据,字符流只能操作字符类型的。
2.字节流是直接对文件进行操作,不会使用到缓冲区。字符流是使用了缓冲区,先将数据写入到或者读取到缓冲区之中,然后在将数据写出到文件或者读取到程序。

2.1 OutputStream输出流
2.1.1 概述

字节流:用来传出字节类型的数据的,例如图片、声音、视频等二进制的数据。

**字节输出流:**OutputStream,被定义为抽象类,就意味着我们不能直接使用OutputStream创建字节输出流对象。字节输出流不光能输出字节类型的数据,也可以输出字符类型的数据,只是需要将字符转变为字节。

注意:在使用输入流的时候,如果文件不存在,则会出现文件找不到异常(FileNotFoundException)。在使用输出流的时候,即便文件不存在,也不会出现异常,会自动将文件创建出来(但是如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开,也是会抛出 FileNotFoundException )。
我们在使用输出流的时候,如果没有名称的指定是否覆盖的时候,默认的就是覆盖的操作,之后执行的输出的内容会将之前执行的输出的内容进行覆盖。

2.1.2 操作

常用FileOutputStream类

构造方法:

FileOutputStream(File file)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 append如果为true则表示不覆盖掉原文件
FileOutputStream(FileDescriptor fdObj)
创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。
FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name, boolean append)
创建一个向具有指定 name 的文件中写入数据的输出文件流。

常用方法:

  • void close() :关闭此文件输出流并释放与此流有关的所有系统资源。
  • void write(byte[] b): 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
  • void write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
  • void write(int b) : 将指定字节写入此文件输出流。
 public static void main(String[] args) throws IOException {
        FileOutputStream fos  = new FileOutputStream("E:\\a.txt");
        FileOutputStream fos2  = new FileOutputStream("E:\\a.txt",true);
        fos.write(new byte[]{65,78,56});
        fos2.write(new byte[]{75,56,45});//只要是第二个流里没设置append为true,就会清空文件再写出
        fos.close();
        fos2.close();
        System.out.println("操作成功");
    }
2.2 InputStream输入流
2.1.1 概述

**字节的输入流:**InputStream,被定义为抽象类,就意味着我们不能直接使用InputStream创建字节输入流的对象。字节输入流不光能读取字节类型的数据,也可以读取字符类型,只是需要将字符转变为字节。

2.1.2 操作

常用FileInputStream类

构造方法:

FileInputStream(File file)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream(FileDescriptor fdObj)
通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。
FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

常用方法:

  • void close():关闭此文件输入流并释放与此流有关的所有系统资源。
  • int read():从此输入流中读取一个数据字节。
  • 返回读入的某一个字节,如果到达文件的末尾, -1 。
  • int read(byte[] b) :从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
  • 返回读入缓冲区的总字节数,如果由于文件末尾已到达而没有更多数据, -1 。
  • int read(byte[] b, int off, int len) :从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
  • long skip(long n) :从输入流中跳过并丢弃 n 个字节的数据。
	   FileInputStream fis2 = new FileInputStream("E:\\a.txt");
        while(true){
            byte b1 = (byte)fis2.read();
            if(b1 == -1){
                break;
            }
            System.out.println((char)b1);
        }
        fis2.close();// 记得关流
2.3文件的加密解密
2.3.1 原理

第一步用字节输入流读取文件,第二步用字节输出流生成加密后的文件

3.3.2 简单实现思路

任何数据异或(^)运算两次后就是原数据。

2.3.3 代码
public static void main(String[] args) throws IOException {
        File oldFile = new File("C:\\Users\\sir\\Desktop","List1.txt");
        File newFile = new File("C:\\Users\\sir\\Desktop","List2.txt");
        encryption(oldFile,newFile);
        System.out.println("操作成功");
    }
    //加密或解密方法
    private static void encryption(File oldFile,File newFile) throws IOException {
        FileInputStream fis = new FileInputStream(oldFile);
        FileOutputStream fos = new FileOutputStream(newFile);
        while(true){
            int len = fis.read();
            if (len==-1) break;
            fos.write(len^10);
        }
    }

三、字符流

3.1 Writer输出流
3.1.1 概述

**字符输出流:**字符输入流只能输出字符数据。

3.1.2 操作

常用FileReader类

构造方法:

FileWriter(File file)
根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(File file, boolean append)
根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(FileDescriptor fd)
构造与某个文件描述符相关联的 FileWriter 对象。
FileWriter(String fileName)
根据给定的文件名构造一个 FileWriter 对象。
FileWriter(String fileName, boolean append)
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。

常用方法:

  • void close(): 关闭此流,但要先刷新它。
  • void flush():刷新该流的缓冲。
  • String getEncoding():返回此流使用的字符编码的名称。
  • void write(char[] cbuf, int off, int len) :写入字符数组的某一部分。
  • void write(int c):写入单个字符。
  • void write(String str, int off, int len) :写入字符串的某一部分。
	public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("E://b.txt");
        fw.write('a');
        //没关流时,字符流是不会将缓冲区的字符写入到文件中去,可以用flush刷新一下
        //fw.flush();
        //append方法叫追加方法,是指的它返回的调用它的对象,所以可以一直连续追加操作
            //是否在文件中接着追加还是看实例化输出流对象时是否指定append参数为true。
        fw.append("锄禾日当午").append(",").append("汗滴禾下土");//
        fw.close();
    }
3.2 Reader输入流
3.2.1 概述

**字符输入流:**字符输入流只能读取字符数据。

3.2.2 操作

常用FileReader类

构造方法:

FileReader(File file)
在给定从中读取数据的 File 的情况下创建一个新 FileReader。
FileReader(FileDescriptor fd)
在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。
FileReader(String fileName)
在给定从中读取数据的文件名的情况下创建一个新 FileReader。

常用方法:

  • void close() :关闭该流并释放与之关联的所有资源。
  • int read() :读取单个字符。
  • int read(char[] cbuf, int offset, int length) :将字符读入数组中的某一部分。
  • boolean ready():判断此流是否已经准备好用于读取。

四、转换流

4.1 InputStreamReader
4.1.1 概述

字节流转字符输入

4.2 OutputStreamWriter
4.2.1 概述

字节流转字符输出

4.3 案例:转换文件编码集
public class TransDemo {
   public static void main(String[] args) {      
    	// 1.定义文件路径
     	String srcFile = "file_gbk.txt";
        String destFile = "file_utf8.txt";
		// 2.创建流对象
    	// 2.1 转换输入流,指定GBK编码
        InputStreamReader isr = new InputStreamReader(new FileInputStream(srcFile) , "GBK");
    	// 2.2 转换输出流,默认utf8编码
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(destFile));
		// 3.读写数据
    	// 3.1 定义数组
        char[] cbuf = new char[1024];
    	// 3.2 定义长度
        int len;
    	// 3.3 循环读取
        while ((len = isr.read(cbuf))!=-1) {
            // 循环写出
          	osw.write(cbuf,0,len);
        }
    	// 4.释放资源
        osw.close();
        isr.close();
  	}
}

五、打印流

5.1 PrintStream & PrintWriter
5.1.1 PrintStream:字节打印流

构造方法:

PrintStream(File file)
创建具有指定文件且不带自动行刷新的新打印流。
PrintStream(File file, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。
PrintStream(OutputStream out)
创建新的打印流。
PrintStream(OutputStream out, boolean autoFlush)
创建新的打印流。
PrintStream(OutputStream out, boolean autoFlush, String encoding)
创建新的打印流。
PrintStream(String fileName)
创建具有指定文件名称且不带自动行刷新的新打印流。
PrintStream(String fileName, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。

常用方法:

  • void println():通过写入行分隔符字符串终止当前行。
  • void println(boolean x):打印 boolean 值,然后终止行。
  • void println(int x) :打印整数,然后终止该行
  • void close() :关闭流。
  • void flush():刷新该流的缓冲。
5.1.2 PrintWriter:字符打印流

构造方法:

PrintStream(File file)
创建具有指定文件且不带自动行刷新的新打印流。
PrintStream(File file, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。
PrintStream(OutputStream out)
创建新的打印流。
PrintStream(OutputStream out, boolean autoFlush)
创建新的打印流。
PrintStream(OutputStream out, boolean autoFlush, String encoding)
创建新的打印流。
PrintStream(String fileName)
创建具有指定文件名称且不带自动行刷新的新打印流。
PrintStream(String fileName, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。

常用方法:

同上

5.2 PrintWriter作转换流
5.2.1 概述

将字节或字符输出流转为打印流,这样可以让文件的原内容不被覆盖

    FileOutputStream fos = new FileOutputStream("E:\\c.txt",true);//append设为true,保证原文件不被覆盖
    //FileWriter fw = new FileWriter("E:\\c.txt");
    PrintWriter pw1 = new PrintWriter(fos);
    pw1.println("嘿嘿嘿");
    pw1.println("嘿嘿嘿");
    pw1.println("嘿嘿嘿");
    pw1.flush();
    pw1.close();
5.3 收集异常日志

原理:就是创建打印流对象,然后将其作为参数传给异常类实例的printStackTrace方法。

public static void main(String[] args) throws FileNotFoundException {
        try {
            String s = null;
            s.toString();
        }catch (Exception e){
            /*
            先用创建一个字节输出流实例,且这个字节输出流的构造方法的append参数指定为true,这样每一次运行不会覆盖之前的信息。
             */
            FileOutputStream fos = new FileOutputStream("E:\\bug.txt",true);
            PrintWriter pw = new PrintWriter(fos);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            pw.println(sdf.format(new Date()));
            e.printStackTrace(pw);
            pw.close();
        }
    }

六、Properties配置文件类

在这里插入图片描述

6.1 Properties类与properties文件

Properties(配置文件类): 主要用于生产配置文件与读取配置文件的信息。 容器类(属于map体系)。它表示一组持久的属性。 Properties可以保存到流中或从流中加载。 属性列表中的每个键及其对应的值都是一个字符串。

properties文件:它是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值"的格式。

6.2 操作

构造方法:

  • Properties() 创建一个无默认值的空属性列表。
  • Properties(Properties defaults) 创建一个带有指定默认值的空属性列表。

常用方法:

  • void setProperty(String key, String value) 调用Hashtable的put方法存键值对在hash表中
  • String getProperty(String key) 根据键获取值
  • viod load(Reader reader) 从输入流中读取键值对
  • void list(PrintWriter out) 将属性列表打印到指定的打印流中
  • void store(Writer writer, String comments) 将键值对加载到输出流中(与list方法不同的是,它是用来输出到配置文件中的)
  • Set stringPropertyNames() 得到一组键

因为 Properties 继承于 Hashtable,所以可对 Properties 对象应用 put 和 putAll 方法。但==不建议使用这两个方法,因为它们允许调用者插入其键或值不是 String 的项。相反,应该使用 setProperty 方法。==如果在“不安全”的 Properties 对象(即包含非 String 的键或值)上调用 store 或 save 方法,则该调用将失败。类似地,如果在“不安全”的 Properties 对象(即包含非 String 的键)上调用 propertyNames 或 list 方法,则该调用将失败。

public static void main(String[] args) throws IOException {
        /*
        //存储文件
        Properties ppt = new Properties();
        ppt.put("Java","入门");
        ppt.put("C++","好");
        ppt.put("Python","不好");
        ppt.setProperty("Go","牛皮");
        FileWriter fw = new FileWriter("E:\\book.properties");
        ppt.store(fw,"存储的图书");
        fw.close();*/
        //读取文件
        Properties ppt = new Properties();
        Reader r = new FileReader("E:\\Book.properties");
        ppt.load(r);
        r.close();
        Set<String> keys = ppt.stringPropertyNames();
        for(String key:keys){
            System.out.println(key+"——>"+ppt.getProperty(key));
        }
    }

七、序列化技术

7.1 概述

序列化与反序列化就是将对象与字节流相互转化

7.2 ObjectOutputStream类

java.io.ObjectOutputStream 类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。

7.2.1 构造方法
  • public ObjectOutputStream(OutputStream out): 创建一个指定OutputStream的ObjectOutputStream。

构造举例,代码如下:

FileOutputStream fileOut = new FileOutputStream("employee.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
7.2.2 序列化操作
  1. 一个对象要想序列化,必须满足两个条件:
  • 该类必须实现java.io.Serializable 接口,Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException
  • 该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰。
public class Employee implements java.io.Serializable {
    public String name;
    public String address;
    public transient int age; // transient瞬态修饰成员,不会被序列化
    public void addressCheck() {
      	System.out.println("Address  check : " + name + " -- " + address);
    }
}

2.写出对象方法

  • public final void writeObject (Object obj) : 将指定的对象写出。
public class SerializeDemo{
   	public static void main(String [] args)   {
    	Employee e = new Employee();
    	e.name = "zhangsan";
    	e.address = "beiqinglu";
    	e.age = 20; 
    	try {
      		// 创建序列化流对象
          ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("employee.txt"));
        	// 写出对象
        	out.writeObject(e);
        	// 释放资源
        	out.close();
        	fileOut.close();
        	System.out.println("Serialized data is saved"); // 姓名,地址被序列化,年龄没有被序列化。
        } catch(IOException i)   {
            i.printStackTrace();
        }
   	}
}
输出结果:
Serialized data is saved
7.3 ObjectInputStream类

ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。

#####构造方法

  • public ObjectInputStream(InputStream in): 创建一个指定InputStream的ObjectInputStream。
7.3.1 反序列化操作1

如果能找到一个对象的class文件,我们可以进行反序列化操作,调用ObjectInputStream读取对象的方法:

  • public final Object readObject () : 读取一个对象。
public class DeserializeDemo {
   public static void main(String [] args)   {
        Employee e = null;
        try {		
             // 创建反序列化流
             FileInputStream fileIn = new FileInputStream("employee.txt");
             ObjectInputStream in = new ObjectInputStream(fileIn);
             // 读取一个对象
             e = (Employee) in.readObject();
             // 释放资源
             in.close();
             fileIn.close();
        }catch(IOException i) {
             // 捕获其他异常
             i.printStackTrace();
             return;
        }catch(ClassNotFoundException c)  {
        	// 捕获类找不到异常
             System.out.println("Employee class not found");
             c.printStackTrace();
             return;
        }
        // 无异常,直接打印输出
        System.out.println("Name: " + e.name);	// zhangsan
        System.out.println("Address: " + e.address); // beiqinglu
        System.out.println("age: " + e.age); // 0
    }
}

对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个 ClassNotFoundException 异常。

7.3.2 反序列化操作2

**另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException异常。**发生这个异常的原因如下:

  • 该类的序列版本号与从流中读取的类描述符的版本号不匹配
  • 该类包含未知数据类型
  • 该类没有可访问的无参数构造方法

Serializable 接口给需要序列化的类,提供了一个序列版本号。serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

public class Employee implements java.io.Serializable {
     // 加入序列版本号
     private static final long serialVersionUID = 1L;
     public String name;
     public String address;
     // 添加新的属性 ,重新编译, 可以反序列化,该属性赋为默认值.
     public int eid; 

     public void addressCheck() {
         System.out.println("Address  check : " + name + " -- " + address);
     }
}

八、try-with-resources

关闭流的操作

jdk1.7时出现的:

try(FileReader fr = new FileReader("E:\\c.txt")){
            int c = fr.read();
            System.out.println((char)c);
        }catch (IOException e){
            e.printStackTrace();
        }

jdk9时进行了优化:

FileReader fr = new FileReader("E:\\c.txt");
PrintWriter pw = new PrintWriter("E:\\d.txt");
try(fr;pw){
    int c = fr.read();
    System.out.println((char)c);
}catch (IOException e){
    e.printStackTrace();
}

九、缓冲流

9.1 概述

缓冲流,也叫高效流,是对4个基本的FileXxx 流的增强,所以也是4个流,按照数据类型分类:

  • 字节缓冲流BufferedInputStreamBufferedOutputStream
  • 字符缓冲流BufferedReaderBufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

9.2 字节缓冲流
9.2.1 构造方法
  • public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。
  • public BufferedOutputStream(OutputStream out): 创建一个新的缓冲输出流。

构造举例,代码如下:

// 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
9.2.2 效率测试

查询API,缓冲流读写方法与基本的流是一致的,我们通过复制大文件(375MB),测试它的效率。

  1. 基本流,代码如下:
public class BufferedDemo {
    public static void main(String[] args) throws FileNotFoundException {
        // 记录开始时间
      	long start = System.currentTimeMillis();
		// 创建流对象
        try (
        	FileInputStream fis = new FileInputStream("jdk9.exe");
        	FileOutputStream fos = new FileOutputStream("copy.exe")
        ){
        	// 读写数据
            int b;
            while ((b = fis.read()) != -1) {
                fos.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
		// 记录结束时间
        long end = System.currentTimeMillis();
        System.out.println("普通流复制时间:"+(end - start)+" 毫秒");
    }
}

十几分钟过去了...
  1. 缓冲流,代码如下:
public class BufferedDemo {
    public static void main(String[] args) throws FileNotFoundException {
        // 记录开始时间
      	long start = System.currentTimeMillis();
		// 创建流对象
        try (
        	BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk9.exe"));
	     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));
        ){
        // 读写数据
            int b;
            while ((b = bis.read()) != -1) {
                bos.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
		// 记录结束时间
        long end = System.currentTimeMillis();
        System.out.println("缓冲流复制时间:"+(end - start)+" 毫秒");
    }
}

缓冲流复制时间:8016 毫秒

如何更快呢?

使用数组的方式,代码如下:

public class BufferedDemo {
    public static void main(String[] args) throws FileNotFoundException {
      	// 记录开始时间
        long start = System.currentTimeMillis();
		// 创建流对象
        try (
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk9.exe"));
		 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));
        ){
          	// 读写数据
            int len;
            byte[] bytes = new byte[8*1024];
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0 , len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
		// 记录结束时间
        long end = System.currentTimeMillis();
        System.out.println("缓冲流使用数组复制时间:"+(end - start)+" 毫秒");
    }
}
缓冲流使用数组复制时间:666 毫秒
9.3 字符缓冲流
9.3.1 构造方法
  • public BufferedReader(Reader in) :创建一个 新的缓冲输入流。
  • public BufferedWriter(Writer out): 创建一个新的缓冲输出流。

构造举例,代码如下:

// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
9.3.2特有方法

字符缓冲流的基本方法与普通字符流调用方式一致,不再阐述,我们来看它们具备的特有方法。

  • BufferedReader:public String readLine(): 读一行文字。
  • BufferedWriter:public void newLine(): 写一行行分隔符,由系统属性定义符号。

readLine方法演示,代码如下:

public class BufferedReaderDemo {
    public static void main(String[] args) throws IOException {
      	 // 创建流对象
        BufferedReader br = new BufferedReader(new FileReader("in.txt"));
		// 定义字符串,保存读取的一行文字
        String line  = null;
      	// 循环读取,读取到最后返回null
        while ((line = br.readLine())!=null) {
            System.out.print(line);
            System.out.println("------");
        }
		// 释放资源
        br.close();
    }
}

newLine方法演示,代码如下:

public class BufferedWriterDemo throws IOException {
    public static void main(String[] args) throws IOException  {
      	// 创建流对象
		BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
      	// 写出数据
        bw.write("hello");
      	// 写出换行
        bw.newLine();
        bw.write("程序");
        bw.newLine();
        bw.write("员");
        bw.newLine();
		// 释放资源
        bw.close();
    }
}
输出效果:
hello
程序
员

Tips:BufferedReader默认读取的是GBK格式文件,所以如果读的UTF-8文件且文件中有中文的话会乱码。

9.4 练习:文本排序

请将文本信息恢复顺序。

3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
8.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
4.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
2.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
1.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
9.今当远离,临表涕零,不知所言。
6.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
7.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
5.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。

#####案例分析

  1. 逐行读取文本信息。
  2. 解析文本信息到集合中。
  3. 遍历集合,按顺序,写出文本信息。

#####案例实现

public class BufferedTest {
    public static void main(String[] args) throws IOException {
        // 创建map集合,保存文本数据,键为序号,值为文字
        HashMap<String, String> lineMap = new HashMap<>();

        // 创建流对象
        BufferedReader br = new BufferedReader(new FileReader("in.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));

        // 读取数据
        String line  = null;
        while ((line = br.readLine())!=null) {
            // 解析文本
            String[] split = line.split("\\.");
            // 保存到集合
            lineMap.put(split[0],split[1]);
        }
        // 释放资源
        br.close();

        // 遍历map集合
        for (int i = 1; i <= lineMap.size(); i++) {
            String key = String.valueOf(i);
            // 获取map中文本
            String value = lineMap.get(key);
          	// 写出拼接文本
            bw.write(key+"."+value);
          	// 写出换行
            bw.newLine();
        }
		// 释放资源
        bw.close();
    }
}
  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值