I/O流(复习)

File类

File类可以操作文件和目录,它可以新建,删除,重命名文件,但是不能修改文件的内容,它可以使用文件路径来创建

文件过滤:通过File类中的list()方法可以接收一个FilenameFilter参数,通过该参数可以列出符合的文件

关于FilenameFilter,它是一个接口,只有一种方法accept(),所以要想使用这个类必须创建一个类来继承它,所创建的这个类还需要重写accept()方法

import java.io.File;
import java.io.FilenameFilter;
//java程序中的路径指的是java命令执行时所在路径。
public class T4 {
    public static void main(String[] args) throws Exception {
        File f = new File(".");//”.”或”.\”代表当前目录,这个目录也就是jvm启动路径.
        //比如有个项目名为blog,其完整路径为:D:\work\IDE\workspace\blog.那么这个路径就是jvm的启动路径了.
        MyFilter filter = new MyFilter(".java");
        String[] files = f.list(filter);
        for (String a : files) {
            System.out.println(a);
        }
    }
    static class MyFilter implements FilenameFilter {
        private String type;
        public MyFilter(String type) {
            this.type = type;
        }

        public boolean accept(File dir, String name) {//必须重写accept(File file,String path)方法
            return name.endsWith(type);
        }
    }
}

I/O流

java的所有流都是由InputStream(字节输入流),Reader(字符输入流),OutputStream(字节输出流),Writer(字符输入流)派生而来

字符流与字节流的用法几乎一样,只是他们的操作单位不一样,字节流的操作单位是8字节,字符流为16字节

字节流

FileInputStream示例:

import java.io.FileInputStream;

public class FileInputStreamTest {

    public static void main(String[] args)throws Exception{
        //创建字节输入流
        FileInputStream fis=new FileInputStream("name");//输入路径
        byte[] bbuf=new byte[1024];//创建一个数组,每次讲取出来的数据装到这里
        //保存实际读取的字节
        int hasRead=0;
        while((hasRead=fis.read(bbuf))>0){
            System.out.print(new String(bbuf,0,hasRead));//创建一个字符串,这是一个字符串构造器,将一个数组转为字符串
        }
        fis.close();
    }
}

这样所写入的程序会覆盖原文件,原文件的信息会被删除,可以用如下方法来续写文件

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

public class FileOutPutStreamTest2 {
    public static void main(String[] args)throws IOException {
        File file=new File("C:\\Users\\xxx\\Desktop\\a.txt");
        FileOutputStream fos=new FileOutputStream(file,true);//指定为需要续写的文件
        String str="\r\n"+"efg";
        fos.write(str.getBytes());
        fos.close();
    }
}

此处需要注意\r\n:

\r:回车的意思,光标回到本行行首

\n:换行的意思,光标向下移一行

\r\n合起来使用就是换行的意思

将文件输入输出流结合来使用,制作一个文件复制器,代码如下:

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

public class CopyFileTest {
    //利用字节流来复制文件
    public static void main(String[] args) throws IOException{

        File scr=new File("D:\\下载\\a.jpg");
        File dest=new File("C:\\Users\\xxx\\Desktop\\ab.jgp");

        //划分明确输入和输出流
        FileInputStream fis=new FileInputStream(scr);
        FileOutputStream fos=new FileOutputStream(dest);

        //使用输入流的方法读取字节,并输出
        int ch=0;
        while((ch=fis.read())!=-1){
                fos.write(ch);
        }
        //关闭资源
        fis.close();
        fos.close();
    }
}

我们所使用的是字结流,这种复制速度过于缓慢,所以我们可以利用缓冲数组的方式,一次多读进去几个内容

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

public class CopyFIleByBufferTest {

    public static void main(String[] args) throws IOException {
        //继续先创建文件
        File scr=new File("D:\\下载\\a.jpg");
        File dest=new File("C:\\Users\\XXX\\Desktop\\ab.jgp");

        //创建输入输出流
        FileInputStream fis=new FileInputStream(scr);
        FileOutputStream fos=new FileOutputStream(dest);

        int len=0;
        byte[] buf=new byte[1024];
        while((len=fis.read(buf))!=-1){
            fos.write(buf);
        }
        fos.close();
        fis.close();
    }
}

这样效率就提高了

以上所列举的都是字节流,如果我们所面对的中文字符,我们就需要考虑这个

字符流

如果我们继续使用字节流去读取中文文件的话,那我们所读取到的是一些奇怪的字符例如,我们使用文件字节输入流来读取文件中的“哈哈”两个字

所得到的就是这样的符号,这就要我们去通过编码翻译

通过字符流来FileReader来读取文件

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

public class FileReaderDemo {
    //利用字符流来读取文件
    public static void main(String[] args) throws IOException {
        FileReader fr=new FileReader("C:name");
        int ch=0;
        while((ch=fr.read())!=-1){
            System.out.print(ch);//输出对应的值
            System.out.print((char)ch);//输出字符本身
        }
    }
}

通过字符流FileWirter来写文件

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

public class FileWriterDemo {
    public static void main(String[] args) throws IOException {
        FileWriter fw=new FileWriter("C:\\Users\\xxx\\Desktop\\a.txt");
        fw.write("嘿嘿");//这些文字都写入了缓存区,需要边写边刷新
        fw.flush();
        fw.close();
    }
}

此处要特别注意在写完需要刷新flush()

此处使用了flush()和close()

flush()是刷新流,刷新后流还可以继续使用

close()是直接关闭流,close()自带刷新

最后还是利用字符输入输出流来练习文件的复制

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

public class CopyTextFileTest {
    public static void main(String[] args) throws IOException {
        FileReader fr=new FileReader("D:\\下载\\a.jpg");
        FileWriter fw=new FileWriter("C:\\Users\\王敏航\\Desktop\\ab.jpg");

        char[] buf=new char[1024];
        int len=0;
        while((len=fr.read(buf))!=-1){
            fw.write(buf,0,len);
        }
        fr.close();
        fw.close();
    }
}

总结:在输入流方面,字节都是可以使用单个的int型数来接收的,字节输入流使用byte[]数组,而字符输入流则使用char[]

输出流方面,要特别注意字符输出流每次write完都要flush

上面我们所看到的字符流中有两个转换流,FileWriter和FileReader都是两个转换流的子类,FileWriter和FileReader使用的是默认编码表

转换流

转换流就是字符流与字节流之间的桥梁

OutputStreamWriter类,它是字符流转向字节流的桥梁,它的作用是指定特定的编码方式,再使用字节流以指定的编码方式写出去

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

public class writeCN {

    public static void main(String[] args) throws IOException {
        FileOutputStream fos=new FileOutputStream("name");
        //创建可以把字符转为字节的转换流对象
        OutputStreamWriter osw=new OutputStreamWriter(fos,"utf-8");
        osw.write("abc");//调用转换流,写入缓存,注:这里是写入缓存,所以要刷新
        osw.close();
    }
}

注:使用该转换流写入后需要刷新

InputStreamReader:是字节流通向字符流的桥梁,字节流读取的数据通过它进行指定的编码,展示出来

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

public class InputStreamreaderDemo {


    public static void main(String[] args) {
        //创建字节流
        FileOutputStream is=new FileInputStream("");
        //创建转换流
        InputStreamReader isr=new InputStreamReader(is,"utf-8");
        int ch=0;
        while((ch=isr.read())!=-1){
            System.out.print((char)ch);
        }
        isr.close();

    }
}

总结:

字节--->字符 : 看不懂的--->看的懂的 需要读 输入流 InputStreamReader

字符--->字节 : 看的懂的--->看不懂的 需要写 输出流 OutputStreamWriter

缓冲流

在之前的操作中,如果需要的数据多了,就会影响速度,所以就要用到缓冲流,缓冲流也分为字节缓冲流和字符缓冲流

l 字节缓冲输出流 BufferedOutputStream

l 字节缓冲输入流 BufferedInputStream

l 字符缓冲输入流 BufferedReader

l 字符缓冲输出流 BufferedWriter

使用缓冲流都是对基础的字符字节流进行封装

直接上代码来看

字节缓冲输入流BufferedOutputStream

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

public class BufferedOutputDemo {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos=new FileOutputStream("name");//创建基础的字节输出流
        BufferedOutputStream bos=new BufferedOutputStream(fos);//对字节输出流进行封装

        bos.write("asd".getBytes());
        bos.close();
    }
}

字节缓冲输入流BufferedInputStream

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

public class BufferedInputStreamDemo {
    public static void main(String[] args) throws IOException {
        //创建基础字节输入流
        FileInputStream fis=new FileInputStream("name");
        //进行封装
        BufferedInputStream bis=new BufferedInputStream(fis);

        int ch=-1;
        while((ch=fis.read())!=-1){
                System.out.print((char)ch);
        }
        fis.close();
    }
}

字符缓冲输出流BufferedWriter

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

public class BufferedWriterDemo {
    public static void main(String[] args) throws IOException {
        FileWriter fw=new FileWriter("name");
        BufferedWriter bw=new BufferedWriter(fw);
        for(int i=0;i<5;i++){
            bw.write("ad");
            bw.newLine();//换行
        }
        bw.close();
    }
}

字符缓冲输入流BufferedReader

public class BufferedReaderDemo {
    public static void main(String[] args) throws IOException {
        //1,创建流
        BufferedReader in = new BufferedReader(new FileReader("file.txt"));
        //2,读数据
        //一次一个字符
        //一次一个字符数组
        //一次读取文本中一行的字符串内容
        String line = null;
        while( (line = in.readLine()) != null ){
            System.out.println(line);
        }
        //3,关闭流
        in.close();
    }
}

如果使用字符流会更加高效,下面使用字符流来完成复制功能

import java.io.*;

public class CopyFileDemo {

    public static void main(String[] args) throws IOException {
        //1,指定数据源, 是数据源中读数据,采用输入流
        BufferedReader in = new BufferedReader(new FileReader("file.txt"));
        //2,指定目的地,是把数据写入目的地,采用输出流
        BufferedWriter out = new BufferedWriter(new FileWriter("copyFile.txt"));
        //3,读数据
        String line = null;
        while ( (line = in.readLine()) != null ) {
            //4,写数据
            out.write(line);
            //写入换行符号
            out.newLine();
        }
        //5,关闭流
        out.close();
        in.close();
    }
}

Properties集合

它是唯一一个能和IO流交互的集合,是一个持久集合,它的值以键值的形式存储,下面通过个栗子来了解这个集合

import java.util.Properties;
import java.util.Set;

public class PropertiesDemo {

    public static void main(String[] args) {
        //创建集合对象
        Properties prop=new Properties();
        //添加元素到集合中
        prop.setProperty("王","haha");//调用 Hashtable 的方法 put
        prop.setProperty("sad","asda");
        prop.setProperty("sads","2we");
        //遍历集合
        Set<String> keys=prop.stringPropertyNames();//返回此序列中的键集
        for(String key:keys){
            String val=prop.getProperty(key);//通过键得到值得
            System.out.print(key+" "+val);//输出
        }
    }
}

我们可以使用IO流将这个集合存到文件中,这里的核心方法是store()

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

public class PropertiesDemo2 {

    public static void main(String[] args) throws IOException {
        Properties prop=new Properties();
        prop.setProperty("a","b");
        prop.setProperty("c","d");
        prop.setProperty("e","f");

        FileWriter out=new FileWriter("prop.properties");//文件名
        prop.store(out,"save data");
        out.close();
    }
}

也可以利用输入流将它读取,这里的核心方法是load()

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo3 {

    public static void main(String[] args) throws IOException {
        //创建集合
        Properties prop=new Properties();
        //创建流对象
        FileInputStream fis=new FileInputStream("prop.properties");
        prop.load(fis);
        System.out.print(prop);
    }
}

 

序列化和反序列化

序列化就是向流中写入对象

反序列化就是从流中读取对象

序列化ObjectOutputStream,首先,已经存在一个已知的类person,而且这个被序列化的类还必须实现Serializable接口

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException {
        //明确存储对象的文件
        FileOutputStream fos=new FileOutputStream("D:\\下载\\obj.object");
        //对其进行封装
        ObjectOutputStream oos=new ObjectOutputStream(fos);
        oos.writeObject(new Person("wang",19));
        oos.close();
    }
}

反序列化ObjectInputStream,刚刚已经序列化了一个对象,现在我们来反序列化,读取刚才所序列化的内容

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

public class ObjectStreamDemo2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fis=new FileInputStream("D:\\下载\\obj.object");
        ObjectInputStream ois=new ObjectInputStream(fis);
        Person obj=(Person) ois.readObject();
        System.out.print(obj.toString());
    }
}

当一个对象被序列化,必须实现Serializable接口,这个借口给需要序列化的类提供了一个序列版本号。

如果不想序列化类中的某一变量,可以使用transient来修饰这个变量

打印流

打印流能方便的打印各种数据

字节打印流:PrintStream

字符打印流:PrintWriter

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

public class PrintWriterDemo {

    public static void main(String[] args)throws IOException {
        //创建流
        PrintWriter pw=new PrintWriter("p.txt");
        //直接打印
        for(int i=0;i<5;i++){
            pw.println("abc");
        }
        pw.close();
    }
}

public PrintWriter(OutputStream out, boolean autoFlush)

public PrintWriter(Writer out, boolean autoFlush)

可以开启自动刷新

总结一下:了解了File类,字节流和字符流(最基础的流),以及转换流和他们的子类(可以设置字符流,字节流的输入输出编码方式)   缓冲流(属于封装流,可以提升效率)      Properties集合(唯一一个可以和IO流交互的集合,内容以键值对的形式存在)   序列化与反序列化(将一个类序列化后存起来)   打印流

猜你喜欢

转载自blog.csdn.net/waectr/article/details/81224669