欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

I/O流(复习)

程序员文章站 2022-06-13 22:23:36
...

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();
    }
}

这样效率就提高了

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

 

 

字符流

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

 

I/O流(复习)I/O流(复习)

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

通过字符流来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

I/O流(复习)

 

上面我们所看到的字符流中有两个转换流,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流交互的集合,内容以键值对的形式存在)   序列化与反序列化(将一个类序列化后存起来)   打印流

相关标签: I/O流 文件