Java,IO流操作

File类

表示文件的抽象路径,不代表该路径下一定有该文件.

构造方法

File(String pathname)

pathname是一个文件的抽象路径

File(String parent,String child)

parent是一个路径,child是一个文件名

File(File parent, String child)

实例:

import java.io.File;
public class Test {
    public static void main(String[] args) {
        // File(String pathname)
        File f1 = new File("E:\\test\\a.txt");
        // File(String parent,String child)
        File f2 = new File("E:\\test", "b.txt");
        // File(File parent, String child)
        File f3 = new File("E:\\test");
        File f4 = new File(f3, "c.txt");
        //直接打印是路径
        System.out.println(f1);// E:\test\a.txt
        System.out.println(f2);// E:\test\b.txt
        System.out.println(f4);// E:\test\c.txt
    }
}

常用方法

boolean createNewFile()

  创建当前抽象路径下的文件,如果创建成功则返回true。如果有同名文件则创建失败。该方法自带IOException异常,如果需要创建的文件的目录不存在则创建失败。

boolean mkdir()

  创建当前抽象路径的文件夹,如果创建成功则返回true。当需要创建的文件夹的父目录不存在时则创建失败。如果需要创建的问价已经存在也会创建失败。失败返回false。

boolean mkdirs()

  创建当前抽象路径的文件夹,如果父目录不存在也会创建父目录。创建成功则返回true,如果需要创建的文件夹已经存在了,则创建失败返回false。

实例:


import java.io.File;
import java.io.IOException;
public class Test {
    public static void main(String[] args) throws IOException {
        File f = new File("E:\\test\\aa\\bb");
        System.out.println(f.mkdirs());//true
        File f1 = new File("E:\\test\\aa\\bb\\a.txt");
        System.out.println(f1.createNewFile());//true
    }
}

boolean delete()
  • 删除抽象路径下的文件或文件夹。成功则返回true。
  • 该目录不能为空,多级目录只会删除最后一个项目。例如E:\test\aa\bb\a.txt执行该方法只会删除a.txt其父目录不会被删除。

  • 删除文件夹的时候文件夹必须为空才会被删除。

  • 如果文件或者文件夹正在被访问则无法删除。

import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        File f1 = new File("E:\\test\\aa\\bb\\a.txt");
        System.out.println(f1.delete());//true
        //要想完全删除需要逐级删除
        System.out.println(new File("E:\\test\\aa\\bb").delete());//true
        System.out.println(new File("E:\\test\\aa").delete());//true
        System.out.println(new File("E:\\test").delete());//true
    }
}

注意:
1. 指定盘符的路径是绝对路径,如果不指定盘符是相对路径。
2. 没有指定盘符的情况下创建文件或者文件夹会在当前项目下。
3. mkdirs方法创建文件夹的时候如果指定的路径包含文件,则会以文件的全名称创建文件夹,所以指定该方法的路径时路径不能包含文件

boolean renameTo(File dest)

重命名抽象流泪路径表示的文件。如果两次的路径相同则只是重命名,如果路径不同,则剪切并重命名。

import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        File f = new File("aaa\\bbb\\a.txt");
        // 重命名并剪切到项目根目录文件夹
        System.out.println(f.renameTo(new File("b.txt")));// true
    }

}

判断类功能

boolean isDirectory()

判断是否是文件夹

boolean isFile() 

判断是否是文件

boolean canRead()

是否可读

boolean canWriter()

是否可写

boolean exists()    

是否存在

boolean isHidden()

是否是隐藏文件

获取类功能

String getAbsolutePath()

获取抽象文件的绝对路径

String getPath()

获取相对路径的字符串

String getName()

返回由此抽象路径名表示的文件或目录的名称

long length()

返回由此抽象路径名表示的文件的长度。

long lastModified()

文件最后一次被修改的时间(时间毫秒值)

获取的高级功能

String[] list()

获取当前某个路径下的所有的文件夹以及文件名称的字符串数组

File[] listFiles()

获取当前某个路径下所有的文件夹以及文件的File数组

//判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称
import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        File file = new File("e:\\");// e盘的抽象路径
        File[] fiarr = file.listFiles();// 获取e盘下所有文件的File数组
        if (fiarr != null) {// 非空判断
            // 遍历
            for (File f : fiarr) {
                if (f.isFile()) {// 判断是否是文件
                    if (f.getName().endsWith(".jpg")) {
                        // 返回文件的名称并判断是否为.jpg结尾
                        System.out.println(f.getName());
                    }
                }
            }
        }
    }

}
/*
23.jpg
24.jpg
55.jpg
 */

FilenameFilter

文件名称过滤器接口只包含一个方法

boolean accept(File dir, String name)

 在 listlistFiles 方法的括号中用匿名内部类的方式实现 FilenameFilter 接口然后重写该方法,可以用来过滤文件。返回值为 true 的时候保留该文件到数组中。

  • dir:获取到的文件的目录
  • name:当前获取到的文件的文件名

重写该方法时需要在方法内规定一些过滤文件的规则。

//判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        File file = new File("e:\\");// e盘的抽象路径
        String[] list = file.list(new FilenameFilter() {
            // 匿名内部类重写accept方法
            @Override
            public boolean accept(File dir, String name) {
                // 封装一个File类对象new File(dir, name)用于判断该路径是否属于文件。
                // 获取到的抽象路径需要为一个文件且名称的后缀名为.jpg
                return new File(dir, name).isFile() && name.endsWith(".jpg");
            }
        });
        for (String str : list) {// 遍历
            System.out.println(str);
        }
    }
}
/*
23.jpg
24.jpg
55.jpg
 */

IO流

IO流的分类

按流的方向分
输入流 读取文件
输出流 写入文件
按数据的类型划分
字节流 字节输入流 InputStream 读取字节
字节输出流 OutputStream 写入字节
字符流 字符输入流 Reader 读取字符
字符输出流 Writer 写入字符

开发步骤:

  1. 创建字节输出流对象
  2. 写数据
  3. 关闭资源

 InputStream、OutputStream、Reader、Writer都是抽象类无法实例化
当针对文件进行操作的时候使用他们的子类FileOutputStream、FileInputStream、FileReader、FileWriter。

字节流

FileOutputStream

字节文件输出流,用于将字节数据写入到文件中。

构造方法

FileOutputStream(String name)

参数中指定一个文件的路径,该文件如果不存在会创建该文件,每次执行都会覆盖之前写入的内容。

FileOutputStream(String name, boolean append)

append指定为true的时候为向文件的末尾追加数据。

常用方法

close()    

关闭流资源,关闭后就不能对流进行操作了。每次使用io流之后都要进行关闭

write(int b)

一次写一个字节

write(byte[] b)

一次写一个字节数组。

  • 输入字符串的时候字符串通过getBytes方法转化成字节数组再通过该方法写入到文件中。

  • 可以输入换行符来将输入的内容换行。\r\n


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

一次写一部分字节数组

异常处理

 可以再方法上直接抛出异常,也可以使用try…catch…finally…的方式来处理异常。

  • 一般将输入输出流对象在try之外声明,在try内new;
  • 在catch中抛出异常;
  • 在finally中释放资源。一般释放前需要进行非空判断。
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        // 声明字节输入流对象
        try {
            fos = new FileOutputStream("b.txt");
            // 创建字节输入流对象
            fos.write("hello".getBytes());
            // 将hello字符串转化成字节数组写入

        } catch (IOException e) {
            e.printStackTrace();
            // 抛出异常
        } finally {
            if (fos != null) {// 非空判断
                try {
                    fos.close();// 释放资源
                } catch (IOException e) {
                    e.printStackTrace();
                    // close方法也需要抛出异常
                }
            }
        }
    }
}

此时在当前项目下就会创建b.txt文件并写入hello


FileInputStream

字节文件输入流,用于程序读取文件中的数据。

开发步骤

  1. 创建字节文件输入流对象
  2. 读数据
  3. 释放资源

常用方法

int read()

一次读取一个字节,如果读取不到返回-1

int read(byte[] b)

一次读取一个字节数组 (读取实际的字节数),返回值为读取到的字节的长度,如果读取不到返回-1。

import java.io.FileInputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        FileInputStream fis=new FileInputStream("b.txt");
        int by=0;
        while ((by=fis.read())!=-1) {
            //read读取的是ASCII码表转化的字节,所以输出时候需要强制转化
            System.out.print((char)by);
            //因为中文的编码一个中文是两个字节所以该方法无法正常解析中文
        }
        fis.close();
    }
}
/*
hello0
hello1
hello2
hello3
hello4
hello5
????
 */

复制文件

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        // 将b.txt复制到a.txt
        // 文件读取流对象
        FileInputStream fis = new FileInputStream("b.txt");
        // 文件写入流对象
        FileOutputStream fos = new FileOutputStream("a.txt");
        // 读取的同时写入
        int by = 0;
        while ((by = fis.read()) != -1) {
            fos.write(by);
        }
        // 分别关闭输入和输出流
        fis.close();
        fos.close();
    }
}

因为复制操作没有进行强制转化所以中文没有出现乱码的情况

一次读取一个字节数组

 比起一次读取一个字节来复制文件要快的多,相当于构建了一个缓冲区。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        // 创建文件字节输入流对象
        FileInputStream fis = new FileInputStream("a.txt");
        // 创建文件字节输出流对象
        FileOutputStream fos = new FileOutputStream("b.txt");
        // 创建一个字节数组,初始化长度,最好为1024的倍数
        byte[] arr = new byte[1024];
        // 定义长度变量
        int len = 0;
        // 一次读取一个字节数组
        while ((len = fis.read(arr)) != -1) {
            fos.write(arr, 0, len);
        }
        fis.close();
        fos.close();

    }
}

GBK 编码中一个中文为两个字节,多为负数如:

import java.util.Arrays;
public class Test {
    public static void main(String[] args){
        String s = "你好";
        // 转化成字节数组遍历
        System.out.println(Arrays.toString(s.getBytes()));
        // [-60, -29, -70, -61]
        String s2 = "abcd";
        System.out.println(Arrays.toString(s2.getBytes()));
        // [97, 98, 99, 100]

    }
}

BufferedInputStream

字节缓冲输入流,套在某个InputStream外面提供一个缓冲区,可以提高里面的InputStream的性能,无法独立使用。

构造方法

BufferedInputStream(InputStream in)

以默认缓冲区大小构造缓冲输入流对象,参数中需要传入一个InputStream 对象。

BufferedInputStream(InputStream in,int size)

指定缓冲区大小构造缓冲输入流对象,一般情况下默认的已经足够使用了。

常用方法

int read()

  和FileInputStream中的read方法相比,BufferedInputStream中的该方法一次会尽可能多的读取数据以减少io的访问次数。
  BufferedInputStream中自带8192字节的缓冲区,读取文件中先将缓冲区读满,然后从缓冲区读取数据,这样一来每次读取都是从内存中读取,比FileInputStream每次从硬盘中读取速度要快得多。

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

  如果 size <= 0,会出现IllegalArgumentException异常。

BufferedOutputStream

字节缓冲输出流

构造方法

BufferedOutputStream(OutputStream out)

用默认的缓冲区大小,来构造一个字节缓冲输出流对象。通常默认大小就够用了。

BufferedOutputStream(OutputStream out,int size)

指定缓冲区大小构造缓冲输出流对象,如果 size <= 0会发生IllegalArgumentException异常。

常用方法

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

同样相比FileOutputStream中的方法更高效。

flush()

  刷新缓冲区的流,强制将当前缓冲区中的数据写入文件中,并清空缓冲区。因为BufferedOutputStream需要先写满缓冲区然后再向文件中写数据,如果数据已经写完但是缓冲区没满系统就会一直等待缓冲区写满,此时就可以使用flush方法强制清空缓冲区并写入文件。
在BufferedOutputStream的close方法中已经包含了flush方法一般只需关闭流就可以了,不需要手动刷新。

字节缓冲流实现复制文件

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        // 字节缓冲输入流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
        // 字节缓冲输出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));
        // 一次读取一个字节数组
        byte[] arr = new byte[1024];
        int len = 0;
        while ((len = bis.read(arr)) != -1) {
            bos.write(arr, 0, len);
        }
        // 关闭流
        bis.close();
        bos.close();
    }
}

此时实现将a.txt中的内容复制到b.txt中。

字符流

为解决中文乱码的问题而产生的流操作,一次操作一个字符。

编码和解码

编码和解码的格式必须一致不然就会乱码

编码

字符串转为字节数组

getBytes() 

使用默认编码格式(GBK)

getBytes(Charset charset) 

指定一种编码格式

解码

字节数组转为字符串,String的构造方法

String(byte[] bytes) 

使用平台默认编码集(gbk)

String(byte[] bytes,Charset charset)

用指定的编码格式来解码

FileReader

  字符读取流,一般仅用于纯文本文件

常用方法

int read(char[] chs)

读取一个字符数组

int read()

读取单个字符

FileWriter

  字符写入流,一般仅用于纯文本文件

常用方法

write(int c)//写单个字符 
write(char[] cbuf)//写字符数组
write(char[] cbuf, int off,  int len)//写字符数组的一部分
write(String str)//写字符串
write(String str,int off, int len)//写字符串的一部分

字符流的write方法可以直接写入字符串,字节流不可以

flush()

刷新流,将缓冲区中的内容写入文件并清空缓冲区。

close();

关闭前必须刷新。区别于BufferedOutputStream的close方法,BufferedOutputStream的close方法中自带了flush方法

  用字符流复制文件

将项目下a.txt中的内容复制到b.txt中

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException  {
        //字符读取流
        FileReader fr=new FileReader("a.txt");
        //字符写入流
        FileWriter fw=new FileWriter("b.txt");
        char[]arr=new char[1024];
        int len=0;
        while ((len=fr.read(arr))!=-1) {
            fw.write(arr, 0, len);
        }
        //释放资源
        fr.close();
        fw.close();
    }
}

InputStreamReader

字符转换输入流,套在字节输入流的外面,一次读取一个或多个字节然后通过编码转化成字符。可以指定编码格式。FileReader是他的子类

InputStreamReader(InputStream in) 

构造一个字符转换输入流使用默认编码

InputStreamReader(InputStream in,Charset cs) 

构造一个字符转换输入流,指定编码

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {
    public static void main(String[] args) throws IOException  {
        InputStreamReader isr=new InputStreamReader(new FileInputStream("a.txt"),"gbk");
        char[]arr=new char[1024];
        int len=0;
        while((len=isr.read(arr))!=-1) {
            System.out.print(new String(arr, 0, len));//你好
            isr.close();
        }
    }
}

OutputStreamWriter

字符转换输出流,套在字节输出流的外面,可以指定编码格式。FileWriter是他的子类。

OutputStreamWriter(OutputStream out)

使用默认的编码格式构造一个字符转换输出流对象

OutputStreamWriter(OutputStream out, Charset cs)

使用指定编码格式构造一个字符转换输出流对象

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class Test {
    public static void main(String[] args) throws IOException  {
        OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("b.txt"), "gbk");
        osw.write("你好");
        osw.close();
    }
}

效果:
b.txt


BufferedReader

字符缓冲读取流,自带缓冲区,套在字符流的外面提高字符流的效率,也可以指定缓冲区大小,不过通常默认大小已经足够大了。

常用方法

readLine()

BufferedReader特有方法,一次读取一行,但是读不到换行符,只能读可见的部分。

BufferedWriter

字符缓冲写入流,自带缓冲区,套在字符流的外面提高字符流的效率

常用方法

newLine()

BufferedWriter特有的方法,写入一个行的分隔符号相当于 \r\n

flush()

关闭流之前要先刷新,如果通过循环写入行的话每行都要刷新。

用字符缓冲流复制文件

将a.txt的内容复制到b.txt

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
        String line = null;
        while ((line = br.readLine()) != null) {// 一次复制一行
            bw.write(line);
            bw.newLine();// 换行
            bw.flush();// 每行都刷新
        }
        bw.close();
        br.close();
    }
}

综合运用实例

从一个包含人名的文件中随机获取一个人
b.txt

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

public class Test {
    public static void main(String[] args) throws IOException  {
        //使用BufferedReader读取文件
        BufferedReader br=new BufferedReader(new FileReader("b.txt"));
        //存入集合中
        ArrayList<String> list=new ArrayList<String>(5);
        //一次读一行
        String line=null;
        while((line=br.readLine())!=null) {
            //添加到集合
            list.add(line);
        }
        br.close();
        //创建随机对象
        Random r=new Random();
        //通过脚标获取需要的人
        String name=list.get(r.nextInt(list.size()));
        //输出选中的人
        System.out.println(name);
    }
}

常用的一些流

数据流

DataInputStream

数据输入流,可以从文件内读取基本类型,需要套在一个输入流的外面使用。

DataInputStream(InputStream in) 

DataOutputStream

 数据输出流,直接向文件内写入基本类型,需要套在一个输出流外面使用,写入的数据大部分看不懂,需要用DataInputStream读取。

DataOutputStream(OutputStream out) 

实例:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException   {
        DataOutputStream dos=new DataOutputStream(new FileOutputStream("b.txt"));
        dos.writeInt(10); 
        dos.writeShort(100);
        dos.writeByte(120);
        dos.writeDouble(13.34);
        dos.writeFloat(12.56F);
        dos.writeBoolean(true);
        dos.writeChar('a');
        dos.close();//释放资源
        //此时b.txt中内容dx@*�z酖瓵H趺,无法阅读,需要通过DataInputStream
        DataInputStream dis=new DataInputStream(new FileInputStream("b.txt"));
        System.out.println(dis.readInt());//10
        System.out.println(dis.readShort());//100
        System.out.println(dis.readByte());//120
        System.out.println(dis.readDouble());//13.34
        System.out.println(dis.readFloat());//12.56
        System.out.println(dis.readBoolean());//true
        System.out.println(dis.readChar());//a
        dis.close();
    }
}

内存操作流

适用于临时存储数据,存在内存中。

byteArrayInputStream

  内存操作输入流

ByteArrayInputStream(byte[] buf) 

将字符数组转化成内存操作输入流对象

byteArrayOutputStream

  内存操作输出流

ByteArrayOutputStream() 

创建一个新的字节数组输出流。 缓冲区容量最初为32字节,也支持指定容量。

方法

write()

只能写入字节或字节数组,写入到内存中。

close()

内存流不需要执行该方法

toByteArray()

将存入内存中的数组转化成字节数组返回

实例:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (int i = 0; i < 5; i++) {
            baos.write(("hello" + i).getBytes());
            baos.write("\r\n".getBytes());
        }
        // 不需要释放资源
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        int b = 0;
        while ((b = bais.read()) != -1) {
            System.out.print((char) b);
        }
    }
}
/*
hello0
hello1
hello2
hello3
hello4
 */

打印流

PrintWriter

字符打印流,属于输出流,只能写数据,不能读。

构造方法

PrintWriter(File file) 
PrintWriter(String fileName) 

如果一个类中的构造方法里面有File对象或者String类型数据说明这个类可以对文本文件直接操作
例如:

FileInputStream
FileOutputStream
FileWriter
FileReader
PrintWriter

都是可以直接操作文本文件的。

PrintWriter(OutputStream out, boolean autoFlush) 
PrintWriter(Writer out, boolean autoFlush) 

第二个参数为true时表示对象可以自动刷新。

方法

print(XXX)
println(XXX)

向文件中打印,参数可以是任意类型

write(xxx) 

向文件中写入,参数可以是一个字符,字符串,字符数组。

实例1:

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class Test {
    public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter(new FileWriter("b.txt"), true);//启动自动刷新
        pw.println("java");
        pw.println("hello");
        pw.println("word");
        pw.close();

    }
}

向b.txt中打印内容:
b.txt

实例2:

将a.txt中的内容复制到b.txt用PrintWriter改进之前的方法

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class Test {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        PrintWriter pw = new PrintWriter(new FileWriter("b.txt"), true);// 自动刷新
        String line = null;// 一次读一行
        while ((line = br.readLine()) != null) {
            pw.println(line);// 打印一行并换行
        }
        // 释放资源
        br.close();
        pw.close();

    }
}

printStream

字节打印流,System.out返回的就是这个流对象

标准的输入输出流

InputStream in <- System.in 
PrintStream out <- Syste.out 

标准的输入流

System.in 

返回值是:InputStream 输入流对象

除了Scanner可以实现键盘录入外还可以通过BufferedReader

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {
    public static void main(String[] args) throws IOException {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        System.out.println("输入内容:");
        String line = br.readLine();
        System.out.println("输入的内容是:"+line);

    }
}
/*
输入内容:
hello
输入的内容是:hello
 */

包装者设计模式:
BufferedReader里面包装字符转换输入流InputStreamReader,InputStreamReader再包装System.in。

标准的输出流

Syste.out 

返回值是PrintStream 输出流对象

PrintStream

方法

println(XXX)
println() 
print(XXX) 

在控制台打印输出

实例:

使用BufferedWriter 去包装System.out

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class Test {
    public static void main(String[] args) throws IOException {

        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        bw.write("hello");
        bw.newLine();
        bw.write("word");
        bw.newLine();
        bw.write("java");
        bw.newLine();
        bw.flush();
        bw.close();
    }
}
/*
hello
word
java
 */

合并流

SequenceInputStream

构造方法

SequenceInputStream(InputStream s1, InputStream s2)

将两个流合并为一个流进行操作。

实例:

将a.txt和b.txt合并写入到c.txt中

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        FileInputStream f1 = new FileInputStream("a.txt");
        FileInputStream f2 = new FileInputStream("b.txt");
        // 创建合并流
        SequenceInputStream sis = new SequenceInputStream(f1, f2);
        // 写入c.txt 使用字节缓冲输入流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c.txt"));
        byte[] by = new byte[1024];
        int len = 0;
        while ((len = sis.read(by)) != -1) {
            bos.write(by, 0, len);
            bos.flush();// 如果是写图片文件时候要刷新
        }
        sis.close();
        bos.close();

    }
}

最后创建的c.txt实际是a.txt写完紧接着写b.txt


SequenceInputStream(Enumeration<? extends InputStream> e) 

另一种构造方法,利用Vector集合中elements()方法返回Enumeration接口对象,来提供多个流合并的操作。

实例2:

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

public class Test {
    public static void main(String[] args) throws IOException {
        // 将a.txt\b.txt\c.txt合并到d.txt
        FileInputStream f1 = new FileInputStream("a.txt");
        FileInputStream f2 = new FileInputStream("b.txt");
        FileInputStream f3 = new FileInputStream("c.txt");
        // 定义Vector集合
        Vector<FileInputStream> v = new Vector<FileInputStream>();
        // 添加到集合中
        v.add(f1);
        v.add(f2);
        v.add(f3);
        // 特有方法
        Enumeration<FileInputStream> enu = v.elements();
        // 创建合并流对象
        SequenceInputStream sis = new SequenceInputStream(enu);
        // 字节缓冲输出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d.txt"));
        byte[] by = new byte[1024];
        int len = 0;
        while ((len = sis.read(by)) != -1) {
            bos.write(by, 0, len);
            bos.flush();

        }
        sis.close();
        bos.close();
    }
}

效果:

这里写图片描述

序列化对象流

序列化ObjectOutputStream

将对象按照流的方式存储到文本文件中或者再网络中传输,对象转化为流数据。

Serializable接口

需要被序列化的自定义类需要实现该接口,该接口只用作标记,接口中没有构造方法、方法和字段。

  • 实现该接口的类被称作标记类,在序列化中会产生序列化版本id。
  • 实现该接口后可以点击类名称上的黄色警告线添加一个固定id值,否则每次修改该类都会变动id值。
  • id值与流中的id不匹配,例如,通过ObjectOutputStream将对象写入文本之后又修改了类然后再用ObjectInputStream读取就会发生InvalidClassException异常。

transient关键字

  自定义类中被transient关键字修饰的属性不参与序列化

方法

writeObject(Object obj)

将自定义类的对象序列化写入ObjectOutputStream流


反序列化ObjectInputStream

将文本文件中的流对象或者网络传输中的流对象还原成对象,流数据转化为对象。

方法

readObject()

从ObjectInputStream中读取一个对象

实例:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Student implements Serializable{
    //序列化的类必须实现Serializable接口,只是用作标记,Serializable中没有方法,没有字段
    private static final long serialVersionUID = -3251042750794115146L;
    //产生一个随机固定的id,点类上的黄色警告线就会生成
    //自定义类
    private String name;
    transient int age;//被transient修饰的属性不参与序列化
    public Student() {
        super();
    }
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    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 "Student [name=" + name + ", age=" + age + "]";
    }

}
public class Test {
    public static void main(String[] args) throws Exception {
        //序列化ObjectOutputStream,对象转流
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("a.txt"));
        Student s=new Student("张三", 21);
        oos.writeObject(s);
        //此时a.txt中内容看不懂,乱码只能用 ObjectInputStream反序列化去读取
        oos.close();

        //反序列化ObjectInputStream
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("a.txt"));
        Object obj = ois.readObject();
        System.out.println(obj);//Student [name=张三, age=0]
        //年龄被transient修饰不参与序列化
        ois.close();

    }
}

属性集合类

Properties

  继承自Hashtable的双列集合,集合中的每一对键值对的类型都为String, 可保存在流中或从流中加载。

构造方法

Properties()

创建一个没有默认值的空属性列表。 Properties集合没有泛型结构,因为所有参数都是String类型的。

方法

虽然继承自Hashtable可以使用Hashtable中的put方法添加元素,但是因为put方法允许添加不属于String类型的数据,所以应该使用该类特有的方法来添加元素。

setProperty(String key, String value)

添加键值对,并且强制要求都为String类型

stringPropertyNames()

获取所有的键的集合

getProperty(String key)

用指定的键寻找对应的值

store(Writer writer,String comments)

将属性集合类添加到流中,writer是一个输出流对象,comments是对集合中的键值对的说明。

load(Reader reader)

从文本文件中加载键值对到属性集合类中,reader是一个输入流对象,文本文件中的键值对是以  键=值的格式存储的。

实例:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;

public class Test {
    public static void main(String[] args) throws IOException {
        Properties p=new Properties();
        //添加元素
        p.setProperty("张三", "21");
        p.setProperty("李四", "22");
        p.setProperty("王五", "20");
        //保存到流中
        p.store(new FileWriter("a.txt"), "name,age");

        //读取a.txt中的键值对
        Properties p2=new Properties();
        p2.load(new FileReader("a.txt"));
        //遍历p2
        Set<String> kset = p2.stringPropertyNames();
        for (String k : kset) {
            String v = p2.getProperty(k);
            System.out.println("姓名:"+k+"\t年龄:"+v);
        }
    }
}

a.txt中的内容

a.txt


猜你喜欢

转载自blog.csdn.net/liuchonghua/article/details/80439824