美文网首页
Java输入输出流

Java输入输出流

作者: 若兮缘 | 来源:发表于2018-12-31 22:30 被阅读32次

    IO流

    IO流用来处理设备之间的数据传输,传输是通过流的方式
    Java用于操作流的对象都在java.io包中
    流就是指一连串流动的字符,以先进先出的方式发送信息的通道。

    流的方式

    按照流的方向划分:
    输入流:将外部数据源的数据转换成流,程序通过读取流中的数据,完成对数据源读取的访问
    输出流:将流中的数据转换到对应的数据源中,程序通过向流中写入数据,完成对数据源写入

    按照类型划分:
    字节流:以字节为单位(8位),可以访问所有文件
    字符流:以字符为单位(16位Unicode),只能访问文本文件

    输出流

    比如我们经常使用的 System.out.println("cocci"); 就是将字符串输出到控制台中,或者说输出到屏幕中,这里的屏幕就是输出设备,由程序将cocci通过流输出到目的地。

    输出设备除了屏幕,还有打印机、文件等。

    输入流

    比如使用键盘接收数据 Scanner sc = new Scanner(System.in); 这里的System.in就是输入流,程序从数据源这里指键盘去读取数据通过流输入到程序当中。

    输入设备除了键盘,还有扫描仪、文件等。

    File类

    文件和目录路径名的抽象表示形式,表示磁盘上的文件或目录
    文件:可认为是相关记录或放在一起的数据的集合

    构造方法

    示例:以下三种方式等价,各有不同的使用场景

        //Windows中路径分隔可使用/或者\\
        File file1 = new File("d:\\java\\a.txt");
        File file2 = new File("d:\\java","a.txt");
        File file3 = new File(new File("d:\\"),"java\\a.txt");
    
    常用方法
    注意事项
    1. delete()方法在删除目录时如果其内有内容则无法删除,需要先清空目录下的内容,再删除目录本身
    2. isDirectory()isFile()方法在判断是否为文件或者目录时,如果文件或目录不存在则返回false
    3. createNewFile()方法在创建文件时,如果文件所在的目录不存在则创建失败并抛出异常
    4. String[] list()File[] listFiles() 都是返回对象包含的所有的文件和目录,返回类型不同
    文件与目录的相关操作
        public static void main(String[] args) {
            
            /*目录的创建与删除*/
            File file=new File("d:\\test\\java");
            if(file.exists()){
                System.out.println("目录存在,删除目录");
                file.delete(); //只会删除一级目录,即java
            }else{
                boolean b=file.mkdirs();  //创建多级目录
                System.out.println("创建文件目录结果:" + b);
            }
            /*文件的创建与删除*/
            File file2=new File("d:\\test\\a.txt");
            if(file2.exists()){
                System.out.println("文件存在,删除文件");
                file2.delete();
            }else{
                try {
                    file2.createNewFile(); //创建文件
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println("创建文件");
            }
            //重命名,把a.txt重命名为b.txt
            //file2.renameTo(new File("d:\\test\\b.txt"));
            //把b.txt剪切到java目录下并重命名为c.txt
            file2.renameTo(new File("d:\\test\\java\\c.txt"));
        }
    
    获取File对象的所有子文件和目录
    public class TestFile {
    
        public static void main(String[] args) {
            //获取磁盘的所有根目录
           File[] files =File.listRoots();
           for(int i=0;i<files.length;i++){
               System.out.println(files[i].getPath());
               //输出的是  C:\  D:\
           }    
           TestFile tf = new TestFile();
           //打印Silly目录下的所有子目录和文件
           File file=new File("d:\\Silly");
           tf.printFile(file,"");       
        }   
        /**
         * 打印指定目录下的所有子文件和子目录
         * @param file
         * @param str
         */
        public void printFile(File file,String str){
            System.out.println(str + file.getName());
            if(file.isDirectory()){
                File[] files=file.listFiles();
                for(int i=0;i<files.length;i++){
                    //递归调用
                    printFile(files[i], str+"\t");     
                }               
            }       
        }
    }
    

    字节流

    字节输入流

    InputStream,此抽象类是表示字节输入流的所有类的超类,其主要子类如下

    字节输出流

    OutputStream,此抽象类是字节输出流的所有类的超类,其主要子类如下

    过滤器输入输出流

    FileInputStream

    从文件系统中的某个文件中获得输入字节
    用于读取诸如图像数据之类的原始字节流

    构造方法
    主要方法

    read方法不带参数的返回值为读取的单个字节值,带参数的返回值表示读取的字节长度。如果返回值为-1,则表示已经达到文件末尾!

    FileOutputStream
    构造方法
    主要方法
    演示Demo
    public class IOTest {
        
        public static void main(String[] args) {
            OutputStream fos = null;
            InputStream fis = null;
            try {
                /********* 输出流写文件 ***********/
                fos=new FileOutputStream("d:\\silly.txt");
                String str="最好的我们隔了一整个青春";
                byte[] words=str.getBytes(); //把字符串编码成字节序列
                //写入操作
                fos.write(words, 0, words.length);
                System.out.println("写入成功!");
                
                /********* 输入流读文件 ***********/
                fis = new FileInputStream("d:\\silly.txt");
                StringBuilder sb = new StringBuilder();
                byte[] buf = new byte[1024]; //字节数组缓存数据
                int n = 0; //记录读取的字节长度
                //循环读取数据
                while((n = fis.read(buf)) != -1){
                    //这里使用三个参数的构造方法,因为最后一次读取的长度可能达不到buf数组的长度
                    //所以根据实际读取的长度n去构造对象更合理
                    sb.append(new String(buf, 0, n));
                    buf = new byte[1024]; //重新初始化,避免数据重复
                }
                System.out.println(sb.toString());
                
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                try {
                    //释放资源
                    if(fos != null) fos.close();
                    if(fis != null) fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    文件复制
        public static void main(String[] args) {
            //将d盘的图片复制到桌面
             InputStream is = null;  
             OutputStream os = null;
             try {
               //实例化输入输出流对象
                is = new FileInputStream("d:\\girl.jpg");
                os = new FileOutputStream("C:\\Users\\ruoxiyuan\\Desktop\\mm.jpg");
                //定义一个2048字节的缓存
                 byte[] buffer=new byte[2048];
                 int len= 0; //读取的字节长度
                 while((len = is.read(buffer)) != -1){
                     //最后一次读取的长度len不一定能达到buffer数组的长度,也就是空间有可能富余
                     //如果直接使用write(buffer)方法可能导致写入更多的字节,新文件会稍大
                     os.write(buffer, 0, len);
                 }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                try {
                    //释放资源
                    if(is != null) is.close();
                    if(os != null) os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    

    字符流

    字符输入流

    Reader,此抽象类是表示字符输入流的所有类的超类,其主要子类如下

    字符输出流

    Writer,此抽象类是表示字符输出流的所有类的超类,其主要子类如下

    字节字符转换流

    InputStreamReader:是字节流通向字符流的桥梁,它使用指定的 charset 读取字节并将其解码为字符。
    OutputStreamWriter:是字符流通向字节流的桥梁,它使用指定的 charset 将写入其中的字符编码成字节。
    其使用的字符集可以由构造方法指定,或者使用平台默认的字符集。

    FileReader

    用来读取字符文件的便捷类,使用默认字符集进行编码,InputStreamReader的子类

    构造方法
    常用方法
    FileWriter

    用来写入字符文件的便捷类,使用默认字符集进行编码,OutputStreamWriter的子类

    构造方法
    常用方法
    演示Demo
    public class IOTest {
        public static void main(String[] args) {
            try {
                /*****写文件*****/
                FileWriter writer = new FileWriter("d:\\silly.txt");
                String str = "成功的人只会去做他们该做的事情,只会面对他们的困难,不会有抱怨,"
                        + "更不会有羡慕,因为他们心中有目标,理想,动力以及那颗沉淀的心";
                writer.write(str);
                writer.flush(); //刷新缓冲区
                
                /*****读文件*****/
                FileReader reader = new FileReader("d:\\silly.txt");
                char[] buffer = new char[1024];//定义缓冲区
                int len = 0;
                while((len = reader.read(buffer)) != -1){
                    String res = new String(buffer, 0, len);
                    System.out.println(res);
                }
                writer.close();
                reader.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    缓冲流

    使用缓冲流可以提高读写速度,注意缓冲流在调用write方法写入数据时,是写入的缓冲区,如果缓冲区满了自动执行写操作,缓冲区不满则需要执行flush方法强制写入到输出设备,调用close方法也会强制写入

    字节缓冲流

    缓冲输入流BufferedInputStream,缓冲输出BufferedOutputStream
    只是对字节流进行了包装,使用方式和字节流基本一致
    构造方法:
    public BufferedInputStream(InputStream in)
    public BufferedOutputStream(OutputStream out)

    字符缓冲流
    缓冲输入流BufferedReader

    构造方法:public BufferedReader(Reader in)
    特殊方法:String readLine() 读取一个文本行

    缓冲输出流BufferedWriter

    构造方法:public BufferedWriter(Writer out)
    特殊方法:void newLine() 写入一个行分隔符

    演示Demo
    public class IOTest {
        
        public static void main(String[] args) {
            try {
                /*****写文件*****/
                FileWriter writer = new FileWriter("d:\\silly.txt");
                BufferedWriter bw = new BufferedWriter(writer);
                bw.write("书山有路勤为径");
                bw.newLine(); //写入换行符(根据平台写入对应的换行符)
                bw.write("学海无涯苦作舟");
                bw.newLine();
                //windows下使用\r\n也能换行
                bw.write("世间安得两全法" + "\r\n");
                bw.write("不负如来不负卿");
                bw.flush(); //必须刷新缓冲区
                
                /*****读文件*****/
                String record = null; //存储文件的内容
                int count = 0; //记录行数
                FileReader reader = new FileReader("d:\\silly.txt");
                BufferedReader br = new BufferedReader(reader);
                //每次读取一整行数据,返回值为空时说明读取到文件末尾
                while((record = br.readLine()) != null){
                    count++;
                    System.out.println("当前行数"+count+":"+record);
                }
                /**输出结果
                当前行数1:书山有路勤为径
                当前行数2:学海无涯苦作舟
                当前行数3:世间安得两全法
                当前行数4:不负如来不负卿
                */
                bw.close();
                br.close();
                writer.close();
                reader.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    对象序列化与反序列化

    序列化:把Java对象转换为字节序列的过程
    反序列化:把字节序列恢复为Java对象的过程
    只有实现了Serializable接口的类的对象才能被序列化

    序列化用途
    1. 把对象的字节序列永久保存在硬盘上,通常放在一个文件中
    2. 在网络上传送对象的字节序列
    相关类

    对象输入流类:ObjectInPutStream
    对象输出流类:ObjectOutPutStream

    序列化步骤
    1. 创建一个对象输出流:ObjectOutPutStream out = new ObjectOutPutStream(OutPutStream out);
    2. 调用方法对对象进行序列化 out.writeObject(Object obj); 把对象序列化,得到字节序列写入流中
    3. 刷新缓冲并关闭流 out.flush(); out.close();
    反序列化步骤
    1. 创建一个对象输入流:ObjectInPutStream in = new ObjectInPutStream(InPutStream in);
    2. 调用方法 in.readObject(); 读取字符序列,把参数反序列化成对象,返回该对象
    3. 关闭流 in.close();
    演示Demo

    定义一个学生类实现Serializable接口

    public class Student implements Serializable{
        private String name;
        private int age;
        public Student(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        @Override
        public String toString() {
            return "Student [name=" + name + ", age=" + age + "]";
        }
    }
    

    实现对象序列化与反序列化

    public class IOTest {
        
        public void save(Student stu){
            OutputStream os=null;
            try {
                os = new FileOutputStream("d:\\stu.dat");
                ObjectOutputStream oos = new ObjectOutputStream(os);
                oos.writeObject(stu);
                //写入其他类型数据
                oos.writeBoolean(true);
                oos.flush();
                oos.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                if(os!=null){
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        public Student read(){
            InputStream is=null;
            Student stu=null;
            try {
                is = new FileInputStream("d:\\stu.dat");
                ObjectInputStream ois = new ObjectInputStream(is);
                stu = (Student)ois.readObject();
                //注意读取顺序要和写入顺序保持一致
                System.out.println(ois.readBoolean());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }finally{
                if(is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return stu;
        }
        
        public static void main(String[] args) {
            Student stu = new Student("小小", 18);
            IOTest test = new IOTest();
            test.save(stu);
            Student res = test.read();
            System.out.println(res);
            //true
            //Student [name=小小, age=18]
        }
    }
    

    相关文章

      网友评论

          本文标题:Java输入输出流

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