5. IO流

简介: 这个类对一个文件(夹)的描述。

5. IO流


5.1  File类


5.1.1 文件对象的构造


这个类对一个文件(夹)的描述。


关于路径分隔符:


路径分隔符是对目录的分隔。表示一层嵌套关系。


在windows系统下,分隔符是:\


在UNIX体系下,分隔符是:/

构造方法

参数

File(String pathName)

使用一个指定的文件路径来实例化一个File对象

File(String parent, String name)

给定一个父目录路径和一个子文件名字,系统会自动的将其拼接在一起

File(File parent, String child)

给定一个父目录和一个子文件的名字,系统自动拼接路径


public class FileDemo {
     public static void main(String[] args) {
            //File构造函数演示
            String pathName = "hello.java";
            File f1 = new File(pathName);
            System.out.println(f1);
            File f2 = new File("/Users/IdeaProjects/JavaSE","hello.java");
            System.out.println(f2);
            //将parent封装成file对象。
            File dir = new File("/Users/IdeaProjects/JavaSE");
            File f3 = new File(dir,"hello.java");
            System.out.println(f3);
        }
}

5.1.2 文件和文件夹的常用方法

常用方

描述

boolean exists()

用来描述指定的路径下到底有没有文件(夹)存在。

boolean isFile()

判断指定路径的内容是不是一个文件

boolean isDirectory()

判断指定路径的内容是不是一个文件夹

boolean mkdir()

在指定的路径创建文件夹,返回值代表创建成功还是失败

boolean mkdirs()

在指定的路径创建文件夹,可以创建多级目录

boolean createNewFile()

在指定的路径创建一个空文件,会有一个IOException

boolean isHidden()

判断一个文件是否是隐藏的


 public static void main(String[] args) throws IOException {
                // 对文件或者文件加进行操作。
                File file = new File("/Users/IdeaProjects/JavaSE/file.txt");
                //获取文件的绝对路径,即全路径
                String absPath = file.getAbsolutePath();
                //File中封装的路径是什么获取到的就是什么。
                String path = file.getPath();
                //获取文件名称
                String filename = file.getName();
                //获取文件大小
                long size = file.length();
                System.out.println("absPath="+absPath);
                System.out.println("path="+path);
                System.out.println("filename="+filename);
                System.out.println("size="+size);
                // 创建文件,如果文件不存在,创建 true 如果文件存在,则不创建 false。 
                // 如果路径错误,IOException。
                boolean file1 = file.createNewFile();
                System.out.println("file1=" + file1);
                //-----------删除文件操作-------注意:不去回收站。慎用------
                boolean flag = file.delete();
                System.out.println("flag="+flag);
                //-----------需要判断文件是否存在------------
                boolean falg1 = file.exists();
                System.out.println("falg1="+falg1);
                //-----------对目录操作 创建,删除,判断------------
                File dir = new File("/Users/IdeaProjects/JavaSE/");
                //mkdir()创建单个目录。//dir.mkdirs();创建多级目录
                boolean flag2 = dir.mkdir();
                System.out.println("flag2="+flag2);
                //删除目录时,如果目录中有内容,无法直接删除。
                boolean flag3 = dir.delete();
                //只有将目录中的内容都删除后,保证该目录为空,这个目录才可以删除。
                System.out.println("flag3=" + flag3);
                //-----------判断文件,目录------------
                File file3 = new File("/Users/IdeaProjects/JavaSE/");
                 // 要判断是否是文件还是目录,必须先判断存在。
                System.out.println(file3.isFile());
                System.out.println(file3.isDirectory());
                //-----------目录遍历------------
                File dir1 = new File("/Users/IdeaProjects");
                //获取的是目录下的当前的文件以及文件夹的名称。
                String[] names = dir.list();
                for(String name : names){
                    System.out.println(name);
                }
                //获取目录下当前文件以及文件对象,只要拿到了文件对象,那么就可以获取其中想要的信息
                File[] files = dir.listFiles();
                for(File file4 : files){
                    System.out.println(file4);
                }
            }

5.1.3 文件过滤器


实现自己的文件过滤器


public class FileDemo{
  public static void main(String[] args) {
    //获取扩展名为.java所有文件
    //创建File对象
    File file = new File("/Users/IdeaProjects");
    //获取指定目录下的文件夹
    File[] files = file.listFiles(new FileFileterByDir());
    //遍历获取到的所有符合条件的文件
    for (File f : files) {
      System.out.println(f);
    }
  }
}
自定义类继承FileFilter过滤器接口
//文件过滤器
class FileFileterByDir implements FileFilter{
  public boolean accept(File pathname) {
    return pathname.isDirectory();
  }
}


5.2 流的分类


分类:


方向:输入流和输出流


数据单元:字节流和字符流


InputStream: 字节输入流的超类


OutputStream: 字节输出流的超类


Reader: 字符输入流


Writer: 字符输出流


无论是使用什么流,在使用结束之后,一定要记得关闭这个流。


5.3 字节流


InputStream:


int read(byte[] arr):


参数:从流中读取数据,需要使用到一个字节数组。read方法会将读取到的数据填充到这个字节数组中。所以,读取完成后,我们直接从这个字节数组中取数据即可。


返回值:每次读取数据后,返回这一次读取到了多少个字节的数据。如果这个方法返回值为-1,说明本次没有读取到任何数据,读取完成。


 class FileInputStreamDemo {
     public static void main(String[] args) throws Exception {// 先声明
         InputStream is = null;
         try {
             // 实例化一个流
             is = new FileInputStream(new File("/Users/IdeaProjects/JavaSE/src/kaikeba/com/ArraysDemo.java"));
             // InputStream: 字节输入流,数据是以字节为单位
             // 从管道中读取数据:
             // 实例化一个数组,用来存储每次读取到的数据
             byte[] contents = new byte[100];
             // 用来记录每次读取到了多少数据
             int length = 0;
             // 循环读取,将每次读取到的数据长度给length赋值,并判断是否为-1
             while ((length = is.read(contents)) != -1) {
                 // 通过一个字节数组实例化一个字符串
                 String str = new String(contents, 0, length);
                 System.out.print(str);
             }
         } catch (FileNotFoundException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } finally {
             // 判断是否为空,因为如果最开始实例化的时候,文件不存在,则is实例化失败,依然为null
             // 此时,如果is是null,那么再去关闭的时候,就会出现NullPointerException
             if (is != null) {
                 try {
                     is.close();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
     }
 }

outputStream:操作的数据都是字节,定义了输出字节流的基本共性功能方法。


OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件。


FileOutputStream类,即文件输出流,是用于将数据写入 File的输出流。


public class FileOutputStreamDemo2 {
    public static void main(String[] args) throws Exception {
        File file = new File("myfile.txt");
        FileOutputStream fos = new FileOutputStream(file, true);
        String str = "\r\n"+"kaikeba.com";
        fos.write(str.getBytes());
        fos.close();
    }
}

5.4 字符流


Reader:字符输入流


Writer:字符输出流


写操作


  public static void main(String[] args) throws IOException {
    //1.创建FileWriter的对象并关联对应的文件
    //注意点:
    //一:如果只写文件的名字,不写具体路径,默认路径是当前的工程
    //二:对于关联的文件,如果之前不存在,程序会自动创建一个,如果存在,会将原来的内容覆盖
    //三:可以自己指定路径,但是必须保证路径是真实存在的,否则报异常---FileNotFountException(系统找不到指定的路径。)
    FileWriter fileWriter = new FileWriter("fileWrite.txt");
    //调用写入方法
    //注意点四:在执行write方法时,数据被临时放到了流对象的内部数组中,这个数组是一个字节数组,会默认去查编码表
    fileWriter.write("晨晨");
    //刷新---将临时数组中的数据放入磁盘
    //fileWriter.flush();
    //4.关闭流--两个功能:a:关闭流  b:刷新
    //第五个注意点:流对象使用完后必须关闭
    fileWriter.close();
    //第六个注意点:当流对象关闭之后,不能再进行操作,否则会报异常:Stream closed
    //fileWriter.write("haha");
  }

读操作


  public static void main(String[] args) throws IOException {
    //1.创建文件读入流
    FileReader fileReader = new FileReader("/Users/IdeaProjects/JavaSE/src/kaikeba/com/ArraysDemo.java");
    //开始读操作
    /*
     * read():一个字符一个字符的读,每次读出一个字符
     */
    //a:将当前的字符读出    b:将当前的指针后移一位
    int  value;
    while ((value = fileReader.read()) != -1) {
      System.out.println((char)value);
    }
    fileReader.close();
  }
  public static void main(String[] args) throws IOException {
    //1.创建文件读入流
    FileReader fileReader = new FileReader("/Users/liyunxia/IdeaProjects/JavaSE/src/kaikeba/com/ArraysDemo.java");
    //开始读操作
    /*
     * read(数组):一次可以读出多个字符   ,数组的作用:每次会将读出的字符临时放到这个数组中
     */
    /* 数组是临时存放数据的地方,我们会将读到的字符放到临时数组中,数组的大小决定了我们一次可以读到的字符个数.
     * 一般这个数组的大小<=1kB
     * 返回值代表本次读到的真实的字符个数,如果返回值是-1代表读完了.
     */
    char[] cbuf = new char[2];
    int num ;
    while ((num = fileReader.read(cbuf)) != -1) {
      //System.out.println(new String(cbuf)+"    num:"+num);
      System.out.println(new String(cbuf,0,num)+"    num:"+num);
    }
    fileReader.close();
  }


5.5 转换流


InputStreamReader、OutputStreamWriter


字节=》字符=》字节


转换流:保留了字符流对文本进行操作时候的便利性,保留了字节流的安全性。产生的一种新的流,主要用来做关于文本文件的处理。还可以解决:关于采用了不同字符集的文本之间的处理问题。可以使用指定的字符集来读取一个文本,也可以使用指定的字符集来写一个文本。


OutputStreamWriter


public class InputStreamReaderDemo {
  public static void writeCN() throws Exception {
    //创建与文件关联的字节输出流对象
    FileOutputStream fos = new FileOutputStream("OutputStreamWriter.txt");
    //创建可以把字符转成字节的转换流对象,并指定编码
    OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
    //调用转换流,把文字写出去,其实是写到转换流的缓冲区中
    osw.write("你好");//写入缓冲区。
    osw.close();
  }
}


InputStreamReader


public class InputStreamReaderDemo {
  public static void main(String[] args) throws IOException {
    //演示字节转字符流的转换流
    readCN();
  }
  public static void readCN() throws IOException{
    //创建读取文件的字节流对象
    InputStream in = new FileInputStream("/Users/IdeaProjects/JavaSE/src/kaikeba/com/ArraysDemo.java");
    //创建转换流对象 
    //InputStreamReader isr = new InputStreamReader(in);用本地默认码表读取,可能发生解码的错误
        InputStreamReader isr = new InputStreamReader(in,"utf-8");
    //使用转换流去读字节流中的字节
    int ch = 0;
    while((ch = isr.read())!=-1){
      System.out.println((char)ch);
    }
    //关闭流
    isr.close();
  }
}

5.6 缓冲流


Java提供一套缓冲流,可提高IO流的读写速度;


缓冲流,根据流的分类分类字节缓冲流与字符缓冲流。


BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter


BufferInputStream、BufferedOutputStream:


public class BufferedStreamDemo {
   public static void main(String[] args) throws IOException {
        //写数据到文件的方法
        write();
        read();
    }
    private static void write() throws IOException {
        //创建基本的字节输出流
        FileOutputStream fileOut = new FileOutputStream("bufferedStream.txt");
        //使用高效的流,把基本的流进行封装,实现速度的提升
        BufferedOutputStream out = new BufferedOutputStream(fileOut);
        //2,写数据
        out.write("hello".getBytes());
        //3,关闭流
        fileOut.close
        out.close();
    }
    private static void read() throws IOException {
        //1,创建缓冲流对象
        FileInputStream fileIn = new FileInputStream("bufferedStream.txt");
        //把基本的流包装成高效的流
        BufferedInputStream in = new BufferedInputStream(fileIn);
        //2,读数据
        int ch = -1;
        while ( (ch = in.read()) != -1 ) {
            //打印
            System.out.print((char)ch);
        }
        //3,关闭
        in.close();
    }
}


BufferedReader、BufferedWriter


public class BufferedWriterReaderDemo {
  public static void main(String[] args) throws IOException {
    write();
    read();
  }
    private static void write() throws IOException {
    //创建流
    //基本字符输出流
    FileWriter fileOut = new FileWriter("file.txt");
    //把基本的流进行包装
    BufferedWriter out = new BufferedWriter(fileOut);
    //2,写数据
    for (int i=0; i<5; i++) {
      out.write("hello");
      out.newLine();
    }
    //3,关闭流
    out.close();
    }
    private static void read() 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();
    }
}


5.7 序列化和反序列化流


用于从流中读取对象的操作流 ObjectInputStream   称为反序列化流


用于向流中写入对象的操作流 ObjectOutputStream  称为序列化流


特点:用于操作对象。可以将对象写入到文件中,也可以从文件中读取对象


import java.io.*;
class Person implements Serializable {
    private String name;
    private int age;
    public Person() {
        super();
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
 class ObjectStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        writeObj();//对象的序列化。
        readObj();//对象的反序列化。
    }
    public static void writeObj() throws IOException {
        //1,明确存储对象的文件。
        FileOutputStream fos = new FileOutputStream("object.txt");
        //2,给操作文件对象加入写入对象功能。
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        //3,调用了写入对象的方法。
        oos.writeObject(new Person("wangcai",20));
        //关闭资源。
        oos.close();
    }
    public static void readObj() throws IOException, ClassNotFoundException {
        //1,定义流对象关联存储了对象文件。
        FileInputStream fis = new FileInputStream("object.txt");
        //2,建立用于读取对象的功能对象。
        ObjectInputStream ois = new ObjectInputStream(fis);
        Person obj = (Person)ois.readObject();
        System.out.println(obj.toString());
    }
}

注意:


一个对象要能被序列化,对象所属的类必须实现Serializable接口。否则会发生NotSerializableException异常。


当反序列化对象时,如果对象所属的class文件在序列化之后进行的修改,那么进行反序列化也会发生异常InvalidClassException。发生这个异常的原因如下:该类的序列版本号与从流中读取的类描述符的版本号不匹配/该类包含未知数据类型/该类没有可访问的无参数构造方法.


Serializable标记接口,给需要序列化的类,提供了一个序列版本号:serialVersionUID,该版本号的目的在于验证序列化的对象和对应类是否版本匹配。


静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。


当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会琲序列化了。


5.8 标准输入输出流


System类,定义了一系列有用的属性和方法


System.in、System.out


PrintStream


System.in


结束控制台输入方案:


  • 在Windows环境下,需要输入Ctrl+Z;在Linux/Unix/MAC环境下,需要输入Ctrl+D;
  • 使用结束条件;


  public static void main(String[] args) throws IOException {
        //创建输入流对象
        InputStream is = System.in;
        //创建输出流对象
        FileWriter fw = new FileWriter("file.txt");
        //读取数据
        byte[] bys = new byte[1024];
        int len;
        while((len = is.read(bys))!=-1)
        {
            fw.write(new String(bys, 0, len));
            fw.flush();
        }
        fw.close();
        is.close();
    }


System.out


  public static void main(String[] args) throws IOException {
        //创建输入输出流对象
        BufferedReader br=new BufferedReader(new FileReader("file.txt"));
        OutputStream os=System.out;
        String line;//用于存储读取到的数据
        while((line=br.readLine())!=null) {
                   os.write(line.getBytes());
                   os.write("\r\n".getBytes());
                  }
             //释放资源
            os.close();
            br.close();
    }

由于标准输出流是一个字节输出流,所以只能输出字节或者字节数组,但是我们读到的数据则是字符串,如果想进行输出,还需要转换成字节数组,非常麻烦。我们要想通过标准输出流输出字符串,把标准输出流转换成一种字符输出流即可。可以使用转换流OutputStreamWriter。


 public static void main(String[] args) throws IOException {
        //创建输入输出流对象
        BufferedReader br=new BufferedReader(new FileReader("file.txt"));
        Writer w=new OutputStreamWriter(System.out);//多态,父类引用指向子类对象
        //进行数据读写
        String line;
        while((line=br.readLine())!=null) {
                   w.write(line);
                   w.write("\r\n");
                }
            //释放资源
             w.close();
             br.close();
          }

还可以结合高效缓冲流使用:


 public static void main(String[] args) throws IOException {
         //创建输入输出流对象
         BufferedReader br=new BufferedReader(new FileReader("file.txt"));
         BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
         //进行数据读写
         String line;
         while((line=br.readLine())!=null) {
                  bw.write(line);
                  bw.newLine();
               }
         //释放资源
          bw.close();
          br.close();
          }

5.9 打印流


打印流是输出信息最方便的类,注意包含字节打印流:PrintStream和字符打印流:PrintWriter


通过定义的构造方法可以发现,有一个构造方法可以直接接收OutputStream类的实例,与OutputStream相比起来,PrintStream可以更方便的输出数据,相当于把OutputStream类重新包装了一下,使之输出更方便。


JAVA对PrintStream功能进行了扩充,增加了格式化输出功能。直接使用Print即可。但是输出的时候需要指定输出的数据类型


  1. 提供了一系列重载的print()和println()方法,用于多种数据类型的输出。
  2. PrintStream和PrintWriter的输出不会抛出IOException异常。
  3. PrintStream和PrintWriter有自动flush功能。
  4. PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。 在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。
  5. System.out返回的是PrintStream的实例。


PrintStream


 

    public static void main(String[] args) throws IOException {
        //创建流,绑定输出的目的地
        PrintStream ps=new PrintStream("a.txt");
        //使用write方法写数据,保持内容不变
        ps.write(97);
        ps.println();
        //使用print方法,会根据平台编码,进行转码工作
        ps.println(97);//97->a
        ps.println("HelloWorld");//HelloWorld
       //释放资源
        ps.close();
    }

PrintWriter


 public static void main(String[] args) throws IOException {
        //创建流
        //PrintWriter out = new PrintWriter(new FileWriter("printFile.txt"));
        PrintWriter out = new PrintWriter("a.txt");
        //2,写数据
        for (int i=0; i<5; i++) {
            out.println("helloWorld");
        }
        //3,关闭流
        out.close();
    }

5.10 Properties类


Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。


特点:


  1. Hashtable的子类,map集合中的方法都可以用。
  2. 该集合没有泛型。键值都是字符串。
  3. 它是一个可以持久化的属性集。
  4. 唯一一个能与IO流交互的集合
  5. 有和流技术相结合的方法。
    load(InputStream)  把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中
    load(Reader)
    store(OutputStream,commonts)把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息
    store(Writer,comments);
  6. 常用方法


  • public Object setProperty(String key, String value)调用 Hashtable 的方法 put。
  • public Set stringPropertyNames()返回此属性列表中的键集,
  • public String getProperty(String key)用指定的键在此属性列表中搜索属性


//Properties的使用
public class PropertiesDemo01 {
  public static void main(String[] args) {
    //创建集合对象
    Properties prop = new Properties();
    //添加元素到集合
    //prop.put(key, value);
    prop.setProperty("小丽", "大学生");
    prop.setProperty("小美", "研究生");
    prop.setProperty("小芳", "博士生");
    //遍历集合
    Set<String> keys = prop.stringPropertyNames();
    for (String key : keys) {
      //通过键 找值
      String value = prop.getProperty(key);
      System.out.println(key+"==" +value);
    }
  }
}

使用Properties集合,完成把集合内容存储到IO流所对应文件中的操作

public class PropertiesDemo02 {
  public static void main(String[] args) throws IOException {
    //1,创建Properties集合
    Properties prop = new Properties();
    //2,添加元素到集合
    prop.setProperty("小丽", "大学生");
    prop.setProperty("小美", "研究生");
    prop.setProperty("小芳", "博士生");
    //3,创建流
    FileWriter out = new FileWriter("prop.properties");
    //4,把集合中的数据存储到流所对应的文件中
    prop.store(out, "save data");
    //5,关闭流
    out.close();
  }
}



需求:从属性集文件prop.properties 中取出数据,保存到集合中

public class PropertiesDemo03 {
  public static void main(String[] args) throws IOException {
    //1,创建集合
    Properties prop = new Properties();
    //2,创建流对象
    FileReader in = new FileReader("prop.properties");
    //3,把流所对应文件中的数据 读取到集合中
    prop.load(in);
    //4,关闭流
    in.close();
    //5,显示集合中的数据
    System.out.println(prop);
  }
}


5.11  NIO和NIO.2


NIO(New IO):


从 JDK 1.4 开始引入的一个用来替代传统IO的API。NIO与传统的IO具有相同的作用,但是使用的方式是不一样的。NIO是面向缓冲区(Buffe)的、基于通道(Channel)。


从 JDK 1.7 开始加入了一些新的元素。被称作 NIO.2


NIO 和 IO 有什么区别:


  • IO是面向流(Stream)的,NIO是面向缓冲区(Buffer)的。
  • IO是阻塞型的,NIO是非阻塞型的。


缓冲区Buffer:是一个用来存储基本数据类型的容器。


按照其存储的数据类型不同,缓冲区有着不同的分类:(没有boolean)


ByteBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer、CharBuffer


以上,这些缓冲区有着相同的方法来进行获取和数据的管理。因为所有以上的缓冲区都是继承自Buffer类的。


常用属性和方法:


1,获取缓冲区:不是通过new的方式,而是通过静态方法 allocate(int capacity) 来获取缓冲区。


2,属性:


  • capacity: 容量。表示缓冲区最多可以存储多少数据。一旦设置后,将不能改变。
  • limit: 界限。表示缓冲区可以操作的数据数量。(实际上存储了多少数据)。
  • position: 位置。缓冲区中正在进行操作的数据的位置。
  • mark: 使用mark()方法标记的位置。
  • mark <= position <= limit <= capacity


3,常用方法:


put():将数据放入缓冲区


get():从缓冲区中获取数据


flip():切换成读模式


rewind():重新读取(position重置为0)


clear():清空缓冲区。将缓冲区中limit和position重置为allocate之后的状态。


clear方法只是重置了一下标记,缓冲区中的数据还在。


mark():在指定的position做一个标记


public class FileDemo{
    public static void main(String[] args) throws IOException {
        // 设置输入源 & 输出目的 = 文件
        String infile = "a.txt";
        String outfile = "b.txt";
        // 1. 获取数据源 和 目标传输地的输入输出流(此处以数据源 = 文件为例)
        FileInputStream fin = new FileInputStream(infile);
        FileOutputStream fout = new FileOutputStream(outfile);
        // 2. 获取数据源的输入输出通道
        FileChannel fcin = fin.getChannel();
        FileChannel fcout = fout.getChannel();
        // 3. 创建缓冲区对象
        ByteBuffer buff = ByteBuffer.allocate(1024);
        while (true) {
            // 4. 从通道读取数据 & 写入到缓冲区
            // 注:若 以读取到该通道数据的末尾,则返回-1
            int r = fcin.read(buff);
            if (r == -1) {
                break;
            }
            // 5. 传出数据准备:调用flip()方法
            buff.flip();
            // 6. 从 Buffer 中读取数据 & 传出数据到通道
            fcout.write(buff);
            // 7. 重置缓冲区
            buff.clear();
        }
    }
}


目录
相关文章
|
27天前
|
C语言 iOS开发 C++
10. C++IO流
10. C++IO流
15 0
|
6月前
|
存储 编译器 C语言
IO流(C++)
IO流(C++)
36 3
|
安全 C语言 C++
【C++】—— C++的IO流
【C++】—— C++的IO流
|
8月前
IO流
IO流
28 0
io流
inputStream和Reader是所有输入流的基类
|
4月前
|
算法 C语言 C++
C++的IO流
C++的IO流
25 0
|
5月前
|
安全 C语言 C++
|
8月前
|
C++
C++IO流(1)
C++IO流(1)
|
8月前
|
iOS开发
C++IO流(2)
C++IO流(2)
|
10月前
|
存储
IO流理解
个人学习理解
31 0