IO流

作者: vv_64ce | 来源:发表于2020-04-16 21:52 被阅读0次

    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

    相关文章

      网友评论

          本文标题:IO流

          本文链接:https://www.haomeiwen.com/subject/mhmhvhtx.html