IO流

2020-04-16  本文已影响0人  vv_64ce

File

1.File类是一个对象,代表一个文件或一个文件目录(即文件夹)
2.File类声明在java.io包下
3.如何创建File类的实例
4.相对路径:相较于某个路径下,指明的路径
绝对路径:包含盘符在内的文件或文件目录的路径
5.路径分隔符:windows:\ unix: \

        File f1 = new File("hello.txt");//绝对路径  hello.txt
        File f2 = new File("E:\\User\\hell1.txt");//相对路径  E:\User\hell1.txt
        File f = new File("E:"+File.separatorChar+"User1"+File.pathSeparator+"h.txt");//E:\User1;h.txt

        File f3 = new File("E:\\User","file");//E:\User\file
        File f4 = new File(f3,"hello2o2.txt");//E:\User\file\hello2o2.txt

6.File中常用方法

        File f1 = new File("hell1.txt");
        System.out.println(f1.getAbsolutePath());//绝对路径 E:\User\\hell1.txt
        System.out.println(f1.getPath());//路径 hell1.txt
        System.out.println(f1.getName());//hell1.txt
        System.out.println(f1.getParent());//上层文件目录 null
        System.out.println(f1.length());//内容长度
        System.out.println(new Date(f1.lastModified()));//最后一次修改时间,毫秒值 Thu Jan 01 08:00:00 CST 1970

        File f2 = new File("E:\\User\\hell1.txt");
        System.out.println(f2.getAbsolutePath());//绝对路径 E:\User\hell1.txt
        System.out.println(f2.getPath());//路径 E:\User\hell1.txt
        System.out.println(f2.getName());//hell1.txt
        System.out.println(f2.getParent());//父类 E:\User
        System.out.println(f2.length());//内容长度
        System.out.println(f2.lastModified());//最近被修改时间 1586955653716
        File f = new File("E:\\User\\test");//
        //list()获取文件夹下的所有文件名
        String[] list = f.list();
        for(String s : list){
            System.out.println(s);//test1  test2
        }

        File f1 = new File("E:\\User\\test");
        //listFiles()获取文件夹下的所有文件路径名
        File[] files = f1.listFiles();
        for(File file : files){
            System.out.println(file);//E:\User\test\test1 E:\User\test\test2
        }

创建

 /*
        * 创建磁盘中对应的文件或文件目录
        * 1.createNewFile() 创建文件,若文件存在,则不创建,返回false;反之,创建文件并返回true
        * 2.delete()删除文件或文件夹。
        * 3.mkdir()、 mkdirs() 文件夹的创建
        * */
        File f = new File("h.txt");
        try {
            //文件的创建和删除
            System.out.println(f.createNewFile());
            System.out.println(f.delete());
        } catch (IOException e) {
            e.printStackTrace();
        }
        //文件目录的创建,如下文件目录中只存在E:\User
        File f1 = new File("E:\\User\\hell\\test1");
        //1.mkdir()文件上层目录不存在,则不会创建文件;如上由于hell文件目录不存在,则创建文件目录失败
        System.out.println(f1.mkdir());

        File f2 = new File("E:\\User\\hell\\test2");
        //2.mkdirs()文件上层目录不存在,则会创建上层目录,如上hell文件目录不存在,但仍然会创建出该文件目录
        System.out.println(f1.mkdirs());

//删除文件夹时,该文件夹下没有内容时可以删除成功,否则删除失败
注:File类中涉及到文件和文件目录的操作,并未涉及写入或读取文件的内容操作,此操作需要借助IO流实现;File类对象作为参数传递到流的构造器中,指明读取或写入的“终点”

IO流

IO流(程序角度分析流) 流的分类

节点流(即文件流,访问文件的操作)

处理流(即嵌套在“已有流”(如节点流)的基础上)如,缓冲流 IO流体系
字符流:对文件进行读取操作
/*
    * 文件的相对路径:
    * idea中main:相对于Project而言,JUnitTest中相对当前moudle;eclipse中相对路径相同
    *
    * */
    public static void main(String[] args) {
        File f = new File("\\Moudle\\hello.txt");//需要添加moudle的路径
        System.out.println(f.getAbsolutePath());//E:\User\vv\Moudle\hello.txt
    }
    @Test
    public void test() throws Exception {
        //1.指明要操作的文件
        File f = new File("hello.txt");
        System.out.println(f.getAbsolutePath()); //E:\User\vv\Moudle\hello.txt
        //2.获得文件的输入流
        FileReader  fr = new FileReader(f);
        int data ;
        while((data = fr.read()) != -1){//判断是否能读取到字符,达到文件末尾时返回-1
            System.out.print((char)data+"\t");//(char)fr.read()将字节码转换成字符
        }
        fr.close();
    }

 //为保证IO流可以正常关闭,应该使用try-catch-finally而不是throws异常
    @Test
    public void test()  {
       
        //1.指明要操作的文件
        File f = new File("hello.txt");
        System.out.println(f.getAbsolutePath()); //E:\User\vv\Moudle\hello.txt
        FileReader  fr = null;
        try {
            //2.获得文件的输入流
            fr = new FileReader(f);
            int data ;
            while((data = fr.read()) != -1){//判断是否能读取到字符,达到文件末尾时返回-1
                System.out.print((char)data+"\t");//(char)fr.read()将字节码转换成字符
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭文件输入流
            if(fr != null)
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

//同时读入的文件若不存在,则java.io.FileNotFoundException:

read()的各种重载方法读取数据


//1.空参read()
      int data ;
      while((data = fr.read()) != -1){//判断是否能读取到字符,达到文件末尾时返回-1
       System.out.print((char)data+"\t");//(char)fr.read()将字节码转换成字符
            }
//2.read(char[] c)
            char[] data = new char[5];//此时的数组大小固定,
            int len ;
            while((len = fr.read(data) )!= -1)
//                //错误写法,每次读取的都是data的固定长度字符,
//                for (int i = 0; i < data.length; i++) {
//                    System.out.print(data[i]);//hello123lo 文件中是hello123;第一次hello,第二次时,将hello替换成123lo
//                }
                //正确写法,每次遍历读取到的长度len
               for (int i = 0; i < len; i++) {
                    System.out.print(data[i]);//hello123
                }

//3.read(char[] c,int offset,int count)
//方式二:
//                //错误写法:原因和上述错误一相同
//                String str = new String(data);
//                System.out.print(str);//hello123lo

                //正确写法
                String str1 = new String(data,0,len);
                System.out.print(str1);//hello123
字符流:对文件进行输出操作
 /*
    * 从内存中写入数据到硬盘文件里
    * 说明:在输出操作中在输出操作中
    * 1.文件不存在时,不会报异常,而是会自动创建该文件
    * 2.文件存在时,new FileWriter(f,true);表示在原有文件后添加数据;
    * new FileWriter(f,false);/new FileWriter(f);表示覆盖原有数据,重新写入
    * */
    @Test
    public void test01() throws IOException {
        //1.指明输出的文件
        File f = new File("Hi.txt");
        //2.创建FileWriter用于文件输出
        FileWriter fw = new FileWriter(f);
        //3.输出内容
        fw.write("hello\n");
        fw.write("world");
        fw.close();

    }
同时进行字符的输入和输出操作
    @Test
    public void test02()  {
        File f1 = new File("Hi.txt");
        File f2 = new File("HiHi.txt");

        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader(f1);
            fw = new FileWriter(f2);

            int data;
            char[] c = new char[5];
            while((data = fr.read()) != -1){//data = fr.read(c)每次read字符的个数为c
                fw.write(c,0,data);
            }

        }catch (IOException e) {
                e.printStackTrace();
            }

        try {
            if(fw != null)
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            if(fr != null)
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
}
读取时文本文件(txt、java、c++)使用字符流处理,对于非文本文件(图片、音频、doc、ppt等)使用字节流处理;复制时,文本文件可以通过字节流处理,但非文本文件不能使用字符流处理
缓冲流:(字节)对文件的读取和写入速度提高
 @Test
    public void test01() {

        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1.指明要操作的文件
            File f1 = new File("2.PNG");
            File f2 = new File("4.PNG");
            //2.获得文件的输入和输出流
            //(1)造节点流
            fis = new FileInputStream(f1);
            fos = new FileOutputStream(f2);
            //(2)造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //3.对文件进行复制
            int b;
            byte[] bytes = new byte[1024];
            while((b = bis.read(bytes)) != -1){//读取的bytes
                bos.write(bytes,0,b);
                bos.flush();//刷新缓冲区
            }
            }catch(java.io.IOException e){
            e.printStackTrace();
        }finally{
            //4.关流(缓冲流close操作中,内部已经对节点流close过,不需要再进行关闭节点流)
            if(bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        }

使用缓冲流(字符)输出数据时,有两种方式:char[] 和String

 @Test
    public void test01(){
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            br = new BufferedReader(new FileReader(new File("1.txt")));
            bw = new BufferedWriter(new FileWriter(new File("2.txt")));
//            //方法一:使用char[]
//            int i;
//            char[] c = new char[1024];
//            while ((i = br.read(c)) != -1){
//                bw.write(c,0,i);
//            }

            //方法二:使用String
            String data;
            while((data = br.readLine()) != null) {//按行读取
                String str = new String(data);
                //换行两种方式
                //一:
                bw.write(str + "\n");
                //二:
                bw.write(str);//将String对象中的数据写入文件,但此方法没有进行换行
                bw.newLine();//进行换行处理
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{

            try {
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

对图片加密操作

    @Test
    public void test01(){
        try {
            FileInputStream fis = new FileInputStream("5.PNG");
            FileOutputStream fos = new FileOutputStream("6.PNG");

            int b ;
            byte[] bytes = new byte[10];
            while ((b = fis.read(bytes)) != -1){
//                //字节数组进行修改
//                //错误:
//                for(byte b1 : bytes){
//                    b1 = (byte)(b ^ 5);//次数是对新的b1变量修改了,但bytes并没有改变
//                }
                //准确
                for (int i = 0; i < b; i++) {//循环的应该是每次获得的长度
                    bytes[i] = (byte)(bytes[i] ^ 5);
                }
                fos.write(bytes,0,b);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }

转换流

1.InputStreamReader:将字节的输入流转换为字符的输入流
OutputStreamWriter:将字符的输出流转换为字节的输出流
2.作用:提供字节流和字符流之间的转换
3.解码:字节、字节数组----》字符数组、字符串
编码:字符数组、字符串----》字节、字节数组
4.字符集
ASCII、ISO8859-1、GB2312、GBK、Unicode、utf-8(每8位传输)
ANSI编码:即平台默认编码;如:英文操作系统ISO-8859-1,中文系GBK


转换流

实现字节流输入流---》字符流输入流

    @Test
    public void test01() throws IOException {
        FileInputStream fis = new FileInputStream("1.txt");
        //字节流---》字符流
        InputStreamReader  isr = new InputStreamReader(fis);//默认使用该工具的字符集
        InputStreamReader  isr1 = new InputStreamReader(fis,"gbk");//自定义字符集

        int i;
        char[] c = new char[10];
        while((i = isr1.read(c)) != -1){
            System.out.println(c);
        }
        isr.close();
    }

实现字节流输入流---》字符流输入流 和 字符输出流-----》字节输出流

    @Test
    public void test02() throws IOException {
        FileInputStream fis = new FileInputStream("1.txt");
        FileOutputStream fos = new FileOutputStream("3.txt");

        InputStreamReader  isr = new InputStreamReader(fis,"utf-8");//使用utf-8获得输入的字符流
        OutputStreamWriter osr = new OutputStreamWriter(fos,"gbk");//使用gbk输出字节流

        int i;
        char[] c = new char[10];
        while((i = isr.read(c)) != -1){
            osr.write(c,0,i);
        }
        osr.close();
        isr.close();
        fos.close();
        fis.close();
    }

获取文本上每个字符出现的次数,并进行相加

    @Test
    public void test01() throws IOException {
        //1.读取的文件
        FileReader fr = new FileReader("1.txt");
        int r;
        char[] c = new char[3];
        //2.将读取文件的字符和每个字符出现的次数存储在HashMap中
        HashMap<Character,Integer> hashMap = new HashMap<>();
        while((r = fr.read(c)) != -1){
            for (int i = 0; i < r; i++) {//循环时应该根据读取到的实际长度判断
                //3.判断该HashMap是否包含该字符,若包含,则放入HashMap中,出现次数+1,;不包含,则放入HashMap中,出现数为1
                if(hashMap.containsKey(c[i])){
                    hashMap.put(c[i],hashMap.get(c[i])+1);
                }else{
                    hashMap.put(c[i],1);
                }
            }
        }
        fr.close();//必须将写入流关闭,否则无法写出数据
        //4.将获取的字符和出现的字符次数重新存入文件中
        FileWriter fw = new FileWriter("char.txt");
        Iterator<Map.Entry<Character, Integer>> iterator = hashMap.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<Character, Integer> next = iterator.next();
            System.out.println(next.getKey() + "......" + next.getValue());

            String str = new String(next.getKey() + "......" + next.getValue());
            fw.write(str);
        }
        fw.close();
    }
标准输入输出流

System.in(默认从键盘输入) System.out(默认从控制台输出)

打印流

PrintStream PrintWriter

数据流:用于读取或写入基本数据类型、String类的变量或字符串

DataInputStream DataOutputStream

对象流ObjectOutputStream、ObjectInputStream

1.作用:用于存储和读取基本数据类型或对象的处理流,主要是可以进行序列化
2.序列化:即将内存中的java对象保存到磁盘中或通过网络传输出去(保存),好处在于可以将任何实现了Serializable接口的对象转化为字节数据,使其在保存和输出时可以被还原
某个对象要实现序列化机制,则必须实现Serializable或Externalizable接口,否则,会抛出NotSerializableException异常
3.反序列化:将磁盘中的文件对象还原为内存中的一个java对象(读取)
ObjectOutputStream、ObjectInputStream不能序列化static和transient修饰的成员变量
4.凡是Serializable接口的类都有一个表示序列化版本标识符的静态变量,用来表明类的不同版本间的兼容性;若没有这个静态变量,则类的实例变量进行修改时,serialVersionUID的值可能发生变化
即对象实现序列化的条件:
(1)需要实现接口
(2)对当前类提供一个全局常量serialVersionUID
(3)出来当前类需要SerialVersionUID接口外,还必须保证其内部所有属性也必须是可序列化的(默认情况下,基本数据类型、String就可序列化)

例题:对象流对字符串进行序列化和反序列操作

    @Test
    public void test01() throws IOException {
        //序列化(OutputStream输出流,没有文件会自动创建)
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("2.dat"));
        oos.writeObject("hhhh好的");
        oos.close();
    }
    @Test
    public void test02() throws IOException, ClassNotFoundException {
        //反序列化(InputStream)
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("1.dat"));
        Object o = ois.readObject();
        String s = (String) o;
        System.out.println(s);
        ois.close();
    }

serialVersionUID作用举例

 @Test
    public void test01() throws IOException {
        //1.对Person对象进行序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person1.txt"));
        //没有对Person序列化时,java.io.NotSerializableException: com.vv.file.test.Person
        oos.writeObject(new Person("xiaoli",14));
        oos.close();
    }
    @Test
    public void test02() throws IOException, ClassNotFoundException {
        //1.对Person对象进行反序列化
        //java.io.InvalidClassException
        //在未对该类赋予序列化常量,并对Person序列化后,又对该类修改,再执行反序列化时,没有找到该类
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person1.txt"));
        Object o = ois.readObject();
        Person p = (Person) o;
        System.out.println(p);
        ois.close();
    }

public class Person implements Serializable{
 public static final long serialVersionUID = 123456789L;
public Account account;//Account类也必须是可序列化的
}
public class Account implements Serializable{
 public static final long serialVersionUID = 456789321L;
}
RandomAccessFile

1.RandomAccessFile直接继承与java.lang.Object类,实现了DataInput和DataOutput
2.既可以作为输入流,也可以作为输出流
3.作为输出流时,写出的文件若不存在,则创建;若存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)

 //获取操作的文件,并指定操作的方式可读和可写
        RandomAccessFile rsf2 = new RandomAccessFile("1.txt","rw");
//        //1."1.txt"中原内容abcdef  写入后ok1def
//        rsf2.write("ok1".getBytes());
////        rsf2.close();
//
//        //2.在指定位置写入
//        rsf2.seek(3);//原内容ok1def  写入后ok1ok1
//        rsf2.write("ok1".getBytes());
////        rsf2.close();

        //3.在指定位置写入,但不会覆盖原有数据  元数据ok1mnp  插入后数据ok1hhhmnp
        StringBuilder sb = new StringBuilder((int) new File("1.txt").length());//指定文件的长度
        int i;
        byte[] b = new byte[2];
        rsf2.seek(3);//保存指针3后的数据到StringBuilder中
        while ((i = rsf2.read(b)) != -1){
            sb.append(new String(b, 0, i));
        }
        rsf2.seek(3);//指定位置插入
        rsf2.write("hhh".getBytes());//指定位置插入的数据
        System.out.println(rsf2.getFilePointer());
        rsf2.write(sb.toString().getBytes());//将插入后的文件中追加刚才保存的数据
        rsf2.close();
java NIO支持面向缓冲区的(IO是面向流的)即基于通道的IO操作

分为量部分:1.针对标准输入输出的NIO 2.针对网络编程的NIO
java.nio.channels.Channel
jdk7出现Path、Paths、Files

上一篇下一篇

猜你喜欢

热点阅读