Java基础–I/O流知识总结

文章目录

  • Java基础--I/O流知识总结
    • 引言
    • Java中IO的结构体系
    • 字节流(InputStream/OutputStream)
      • FileInputStream/FileOutputStream
      • ByteArrayInputStream/ByteArrayOutputStream
      • PipedOutputStream/PipedInputStream
      • BufferedInputStream/BufferedOutputStream
      • DataOutputStream/DataInputStream
      • ObjectInputStream/ObjectOutputStream
      • PushbackInputStream
      • PrintStream
      • SequenceInputStream
    • 字符流(Reader/Writer)
      • FileReader/FileWriter
      • CharArrayReader/CharArrayWriter
      • BufferedReader/BufferedWriter
      • PipedReader/PipedWriter
      • StringReader/StringWriter
      • PushbackReader
      • PrintWriter

引言

I/O(输入/输出)应该算是所有程序都必需的一部分,使用输入机制,允许程序读取外部的数据资源、接收用户输入;使用输出机制,允许程序记录允许状态,并将数据输出到外部设备。Java的IO是通过java.io包下的类和接口来实现的,其下主要包括输入、输出两种IO流,根据流中操作的数据单元的不同又分为字节流(8位的字节)和字符流(16位的字符)。

Java中IO的结构体系

字节流(InputStream/OutputStream)

首先来看一看字节输入流InpuStream,此抽象类是表示字节输入流的所有类的超类,它有如下三个基本方法。

  1. int read():从输入流中读取单个字节,返回所读取的实际数据。
  2. int read(byte[] b):从输入流中最多读取b.length个字节的数据,并将其存储在缓冲区数组b中,返回实际读取的字节数。
  3. int read(byte[] b,int off,int len):将输入流中最多len 个数据字节读入缓冲区数组b中,off为数组 b 中将写入数据的初始偏移量,返回实际读取的字节数。

字节输出流OutputStream,此抽象类是表示字节输出流的所有类的超类,它有如下三个基本方法。

  1. void write(int c):将指定的字节写入此输出流。
  2. void write(byte[] buf):将 b.length个字节从指定的 byte 数组写入此输出流。
  3. void write(byte[] buf,int off,int len):将指定 byte数组中从偏移量off开始的 len个字节写入此输出流。

接下来逐个介绍字节流的各个子类。

FileInputStream/FileOutputStream

这两个类直接继承自InputStreamOutputStream,可实现对文件的读取和数据写入。如下代码即可实现对文件的复制操作。

package cn.lincain.io;import java.io.FileInputStream;
import java.io.FileOutputStream;public class FileStreamTest {public static void main(String[] args) {try (// 创建一个字节输入流FileInputStream fis = new FileInputStream("FileStreamTest .java");// 创建一个字节输出流FileOutputStream fos = new FileOutputStream("copy.txt")){int hasRead = 0;// 从ByteStreamTest.java文件读取数据到流中while ((hasRead = fis.read()) != -1) {// 将数据写入到指定的文件中fos.write(hasRead);}} catch (Exception e) {e.printStackTrace();}}
}

我们将输入流比作是一个水管,里面装的水就是文件的数据,read()write(int c)方法相当于每次从中取一滴水,数据量不大的时候,效率还可以,但是当数据量非常大时,读取的效率就很低。
下面我们采用int read(byte[] b)void write(byte[] b,int off,int len)方法来示范文件复制的效果。

package cn.lincain.io;import java.io.FileInputStream;
import java.io.FileOutputStream;public class FileStreamTest {public static void main(String[] args) {try (// 创建一个字节输入流FileInputStream fis = new FileInputStream("FileStreamTest .java");// 创建一个字节输出流FileOutputStream fos = new FileOutputStream("copy.txt")) {long start = System.currentTimeMillis();byte[] buff = new byte[12];int hasRead = 0;// 从ByteStreamTest.java文件读取数据到流中while ((hasRead = fis.read(buff)) > 0) {// 将数据写入到指定的文件中fos.write(buff, 0, hasRead);}long end = System.currentTimeMillis();System.out.println("文件复制总共花了:" + (end - start) + "ms");} catch (Exception e) {e.printStackTrace();}}
}

同样的案例,当我们采用数组作为read()write()的参数时,该数组就相当如一个“水桶”,每次将水桶的水接满了或者水管的水接完了才输出,这样就极大的提高了读取效率,其中第一个程序复制文件消耗了21ms,而第二个程序则只消耗了1ms,由此可见二者的差距。
后面对其他字节流流我们都采取就用缓冲效果的方法进行示范。

ByteArrayInputStream/ByteArrayOutputStream

以上两个字节流从字面意思可知,就是字节数组与字节输入输出流之间的各种转换。
ByteArrayInputStream的构造方法就包含一个字节数组作为它本身的内部缓冲区,该缓冲区包含从流中读取的字节。
ByteArrayOutputStream实现了一个输出流,其中的数据被写入一个 byte 数组,缓冲区会随着数据的不断写入而自动增长,可使用 toByteArray() 和 toString() 获取数据。
举个例子如下:

package cn.lincain.io;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;public class ByteStreamDemo {public static void main(String[] args) {// 创建内存中的字节数组byte[] btyeArray = { 1, 2, 3 };try (// 创建字节输入流ByteArrayInputStream bis = new ByteArrayInputStream(btyeArray);// 创建字节输出流ByteArrayOutputStream bos = new ByteArrayOutputStream()){byte[] bff = new byte[3];// 从字节流中读取字节到指定数组中bis.read(bff);System.out.println(bff[0]+","+bff[1]+","+bff[2]);// 向字节输出流中写入字节bos.write(bff);// 从输出流中获取字节数组byte[] bArrayFromBos = bos.toByteArray();System.out.println(bArrayFromBos[0] + "," + bArrayFromBos[1] + "," + bArrayFromBos[2]);} catch (Exception e) {e.printStackTrace();}}
}

需要注意的是:在ByteArrayInputStream里面直接使用外部字节数组的引用,也就是说,即使得到字节流对象后,当改变外部数组时,通过流读取的字节也会改变。

PipedOutputStream/PipedInputStream

PipedOutputStreamPipedInputStream分别是管道输出流和管道输入流。
它们的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedOutputStreamPipedInputStream配套使用。
使用管道通信时,大致的流程是:我们在线程A中向PipedOutputStream中写入数据,这些数据会自动的发送到与PipedOutputStream对应的PipedInputStream中,进而存储在PipedInputStream的缓冲中;此时,线程B通过读取PipedInputStream中的数据。就可以实现,线程A和线程B的通信。

package cn.lincain.io1;import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class PipedStreamTest {public static void main(String[] args) {try (final PipedOutputStream pos = new PipedOutputStream();final PipedInputStream pis = new PipedInputStream(pos)) {ExecutorService es = Executors.newFixedThreadPool(2);es.execute(new Runnable() {@Overridepublic void run() {try {byte[] bArr = new byte[] { 1, 2, 3 };pos.write(bArr);pos.close();} catch (IOException e) {e.printStackTrace();}}});es.execute(new Runnable() {@Overridepublic void run() {byte[] bArr = new byte[3];try {// 会导致线程阻塞pis.read(bArr, 0, 3);pis.close();} catch (IOException e) {e.printStackTrace();}System.out.println(bArr[0] + "," + bArr[1] + "," + bArr[2]);}});} catch (Exception e) {e.printStackTrace();}}
}

BufferedInputStream/BufferedOutputStream

BufferedInputStreamBufferedOutputStream 分别是缓冲输入流和缓存输出流,他们分别继承自FilterInputStreamFilterOutputStream,主要功能是一次读取/写入一大块字节到缓冲区,避免每次频繁访问外部媒介,提高性能。
其中BufferedInputStream的作用是缓冲输入以及支持 mark()reset ()方法的能力。
BufferedOutputStream的作用是为另一个输出流提供“缓冲功能”。
下面的案例演示了采用缓冲流进行文件的复制。

package cn.lincain.io;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;public class BufferedStreamTest {public static void main(String[] args) {try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("ByteStreamTest.java"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.txt"))) {int hasRead = 0;while ((hasRead = bis.read()) != -1) {bos.write(hasRead);}} catch (Exception e) {e.printStackTrace();}}
}

该程序和上面的FileStreamTest .java的代码大致相同,但是该案例的效率显然更高,只用了不到1ms的时间。

DataOutputStream/DataInputStream

DataInputStream允许应用程序读取在与机器无关方式从底层输入流基本Java数据类型,应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。
DataOutputStream允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。

package cn.lincain.io;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;public class DataStreamTest {public static void main(String[] args) {try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("target.txt"));DataInputStream dis = new DataInputStream(new FileInputStream("target.txt"))){dos.writeBoolean(false);dos.writeChar('夜');dos.write(18);dos.writeUTF("权利的游戏");System.out.println(dis.readBoolean());System.out.println(dis.readChar());System.out.println(dis.read());System.out.println(dis.readUTF());} catch (Exception e) {e.printStackTrace();}}
}

如果要想使用数据输出流,则肯定要由用户自己制定数据的保存格式,必须按指定好的格式保存数据,才可以使用数据输入流将数据读取进来。

ObjectInputStream/ObjectOutputStream

ObjectOutputStream用于将指定的对象写入到文件的过程,就是将对象序列化的过程。ObjectInputStream则是将储存在文件的对象读取出来,就是将对象反序列化的过程。
一个对象如果要实现序列化和反序列化,则需要该对象实现Serializable或者Externalizable接口。

class Person implements Serializable{private String name;private int 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;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}
}
package cn.lincain.io;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;public class ObjectStreamTest {public static void main(String[] args) {Person person = new Person();person.setAge(28);person.setName("Lincain");writeObject(person);readObject();}// 将对象写入指定的文件public static void writeObject(Object object) {try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"))){oos.writeObject(object);} catch (Exception e) {e.printStackTrace();}}// 将文件中将对象读取出来public static void readObject() {try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"))){Person person = (Person)ois.readObject();System.out.println(person);} catch (Exception e) {e.printStackTrace();}}
}

运行上面程序,在磁盘上产生了object.txt文件,说明对象已将序列化到本地文件,如下图:

需要注意的是,反序列化过程读取的仅仅是Java对象的数据,而不是Java类,因此反序列化恢复Java对象时,必须提供该对象的class文件,否则会引起ClassNotFoundException异常。另外反序列化也无须通过构造器来初始化对象。
关于序列化的知识可参考:https://www.cnblogs.com/fnz0/p/5410856.html

PushbackInputStream

退回:其实就是将从流读取的数据再推回到流中。实现原理也很简单,通过一个缓冲数组来存放退回的数据,每次操作时先从缓冲数组开始,然后再操作流对象。

package cn.lincain.io;import java.io.ByteArrayInputStream;
import java.io.PushbackInputStream;public class PushBackInputStreamTest {public static void main(String[] args) {String str = "abcdefghijk";try (//  //创建字节推回流,缓冲区大小为 7ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());PushbackInputStream pis = new PushbackInputStream(bis,7)){byte[] hasRead = new byte[7];// 从流中将7个字节读入数组pis.read(hasRead);System.out.println(new String(hasRead)); //abcdefg// 从数组的第一个位置开始,推回 4 个字节到流中pis.unread(hasRead,0,4);// 重新从流中将字节读取数组pis.read(hasRead);System.out.println(new String(hasRead)); // abcdhij} catch (Exception e) {e.printStackTrace();}}
}
  1. 创建字节推回流,同时创建了大小为7的缓冲区数组;要从字节输入流读取字节到 hasRead 数组;
  2. 从流中读取 7 个字节到hasRead数组;
  3. 现在要从hasRead的 0 下标(第一个位置)开始,推回 4 个字节到流中去(实质是推回到缓冲数组中去);
  4. 再次进行读取操作,首先从缓冲区开始读取,再对流进行操作。

PrintStream

PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式,使其它输出流能方便的通过print()println()printf()等输出各种格式的数据。

package cn.lincain.io;import java.io.FileOutputStream;
import java.io.PrintStream;public class PrintStreamTest {public static void main(String[] args) {try (// 创建打印流,并允许在文件末端追加PrintStream ps = new PrintStream(new FileOutputStream("a.txt", true))) {// 将字符串“Hello,字节流!”+回车符,写入到输出流中ps.println("Hello,字节流!");// 97对应ASCII码的是'A',也就是说此处写入的是字符'A'ps.write(97);// 将字符串"97"写入输出流中,等价于ps.write(String.valueOf(97))ps.print(97);// 将'B'追加到输出流中,和ps.print('B')效果相同ps.append('B');// Java的格式化输出 String str = "CDE";int num = 5;ps.printf("%s is %d\n", str, num);} catch (Exception e) {e.printStackTrace();}}
}

关于PrintStreamDataOutputStream的区别,可阅读:https://www.cnblogs.com/skywang12345/p/io_16.html

SequenceInputStream

SequenceInputStream表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

package cn.lincain.io;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;public class SequenceInputStreamTest {public static void main(String[] args) throws IOException {enumMerge();}// 通过public SequenceInputStream(Enumeration<? extends InputStream> e)创建SequenceInputStreampublic static void enumMerge() throws IOException {List<FileInputStream> arrayList = new ArrayList<>();FileInputStream is1 = new FileInputStream("1.txt");FileInputStream is2 = new FileInputStream("2.txt");FileInputStream is3 = new FileInputStream("3.txt");arrayList.add(is1);arrayList.add(is2);arrayList.add(is3);Enumeration<FileInputStream> enumeration = Collections.enumeration(arrayList);BufferedInputStream bis = new BufferedInputStream(new SequenceInputStream(enumeration));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("4.txt"));int hasRead = 0;while ((hasRead = bis.read()) != -1) {bos.write(hasRead);}bis.close();bos.close();}
}

字符流(Reader/Writer)

字节流和字符流的操作方式几乎一样,只是他们操作的数据单元不同,体现在方法上时,就是方法的参数有所差别。
首先字符输入流Reader,它的三个方法分别是:

  1. int read():从输入流中读取单个字符,返回所读取的世界数据。
  2. int read(char[] c):从输入流中最多读取b.length个字符的数据,并将其存储在缓冲区数组c中,返回实际读取的字符数。
  3. int read(char[] c,int off,int len):将输入流中最多len 个数据字符读入缓冲区数组c中,off为数组 c 中将写入数据的初始偏移量,返回实际读取的字符数。

字符输出流Writer,因为它可以直接操作字符,可以用字符串代替字符数组,所以它有如下五个基本方法。

  1. void write(int c):将指定的字符写入此输出流。
  2. void write(char[] c):将 b.length个字符从指定的c数组写入此输出流。
  3. void write(char[] c,int off,int len):将字符数组中从偏移量off开始的 len个字节写入此输出流。
  4. void write(String str):将str中包含的字符输出到指定的输出流中。
  5. void write(String str, int off,int len):将stroff位置开始,长度为len的字符输出到指定输出流中。

FileReader/FileWriter

通过FileReader/FileWriter我们可以实现对文本文件的读取、写入,从而实现文本文件的复制。

package cn.lincain.io;import java.io.FileReader;
import java.io.FileWriter;public class FileCopyTest {public static void main(String[] args) {try (FileReader fr = new FileReader("FileCopyTest.java");FileWriter fw = new FileWriter("copy.txt")){char[] cbuf = new char[32];int hasRead = 0;while ((hasRead = fr.read(cbuf)) != -1) {fw.write(cbuf, 0, hasRead);}} catch (Exception e) {e.printStackTrace();}}
}

CharArrayReader/CharArrayWriter

CharArrayReader/CharArrayWriter就是字符数组与字符输入输出流之间的各种转换。和ByteArrayInputStream/ByteArrayOutputStream类似,它们都有一个内部缓冲区,区别是前者操作字符,后置操作字节。

package cn.lincain.io;import java.io.CharArrayReader;
import java.io.CharArrayWriter;public class CharArrayTest {public static void main(String[] args) {char[] charArray = "无边落木萧萧下,不尽长江滚滚来!!!".toCharArray();try (CharArrayReader cr = new CharArrayReader(charArray); CharArrayWriter cw = new CharArrayWriter()) {int hasRead = 0;char[] buff = new char[1024];while ((hasRead = cr.read(buff)) != -1) {cw.write(buff, 0, hasRead);}// 将输入数据转换为字符串。System.out.println(cw.toString());} catch (Exception e) {e.printStackTrace();}}
}

同样需要注意的是,在CharArrayReader里面直接使用外部字符数组的引用,也就是说,即使得到字符流对象后,当改变外部数组时,通过流读取的字符也会改变。

BufferedReader/BufferedWriter

和缓冲字节流相似的,缓冲字符流可以用来装饰其他字符流,为其提供字符缓冲区,避免频繁的和外界交互,从而提高效率。被装饰的字符流可以有更多的行为,比如readLine()newLine()方法等。
下来我们还是通过文件复制的案例,对其效果进行演示。

package cn.lincain.io;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;public class BufferedCopyTest {public static void main(String[] args) {try (// 创建字符缓冲输入流BufferedReader br = new BufferedReader(new FileReader("BufferedCopyTest.java"));// 创建字符缓冲输出流BufferedWriter bw = new BufferedWriter(new FileWriter("copy.txt"))){String line = null;// 调用readLine()方法,每次读取一行while ((line = br.readLine()) != null) {// 将字符串写入到输出流中bw.write(line);// 向输出流写入一个换行符bw.newLine();}} catch (Exception e) {e.printStackTrace();}}
}

PipedReader/PipedWriter

通过阅读源码可知,PipedReader/PipedWriter分别将对方作为自己的成员变量,可知二者需要配套使用。通过二者建立联系,构建一个字符流通道,PipedWriter向管道写入数据,PipedReader从管道中读取数据,从而实现线程的通信。
如下示例:

package cn.lincain.io;import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class PipedTest {public static void main(String[] args) throws IOException {final PipedWriter pw = new PipedWriter();final PipedReader pr = new PipedReader(pw);ExecutorService eService = Executors.newFixedThreadPool(2);eService.execute(new Runnable() {@Overridepublic void run() {try {pw.write("线程交互!!!");} catch (IOException e) {e.printStackTrace();}}});eService.execute(new Runnable() {@Overridepublic void run() {char[] cbuf = new char[32];try {// 会导致线程阻塞pr.read(cbuf);pr.close();} catch (IOException e) {e.printStackTrace();}System.out.println(cbuf);}});}
}

需要注意的是:一定要同一个JVM中的两个线程,且读写都会阻塞线程。

StringReader/StringWriter

这两个类和前面介绍的CharArrayReader/CharArrayWriter很相似,只是后者操作的数据类型为字符数组,而这里操作的是字符串,二者的方法也大致相同,下面通过案例来说明。

package cn.lincain.io;import java.io.StringReader;
import java.io.StringWriter;public class StringBufferTest {public static void main(String[] args) {String str = "字符串缓冲流";try (StringReader sr = new StringReader(str);StringWriter sw = new StringWriter()){   // 从输入流中读取数据int hasRead = 0;char[] cbuf = new char[32];while ((hasRead = sr.read(cbuf)) != -1) {System.out.println(new String(cbuf, 0, hasRead));}// 向输出流中写入数据sw.write(str);System.out.println(sw.toString());} catch (Exception e) {e.printStackTrace();}}
}

PushbackReader

PushbackReaderPushbackInputStream的操作方式基本一样,这里就不在再详细的介绍,通过案例对其进行说明。

package cn.lincain.io;import java.io.FileReader;
import java.io.IOException;
import java.io.PushbackReader;public class PushbackReaderTest {public static void main(String[] args) throws IOException {PushbackReader pbr = new PushbackReader(new FileReader("PushbackReaderTest.java"),30);char[] cbuf = new char[24];pbr.read(cbuf);System.out.println(new String(cbuf)); // package cn.lincain.io3;// 如果pbr中的缓冲区的大小小于回退数组的大小,则抛出异常pbr.unread(cbuf);pbr.read(cbuf);System.out.println(new String(cbuf)); // package cn.lincain.io3;pbr.close();}
}

PrintWriter

PrintWriterPrintStream的操作基本一致,只是前者多了两个方法:void write(String s)void write(String s,int off,int len)
但通过源码可知,PrintStream也有这两个方法,只是用private修饰,方法内容不一样,但是最终都指向了Writer类的void write(String str, int off, int len)方法。

package cn.lincain.io;import java.io.PrintWriter;public class PrintWriterTest {public static void main(String[] args) {try (PrintWriter pw = new PrintWriter(System.out)){// 97对应ASCII码的是'A',也就是说此处写入的是字符'A'pw.write(97);// 将字符串"97"写入输出流中,等价于ps.write(String.valueOf(97))pw.print(97);// 将'B'追加到输出流中,和ps.print('B')效果相同pw.append('B');// Java的格式化输出 String str = "CDE";int num = 5;pw.printf("%s is %d\n", str, num);} catch (Exception e) {e.printStackTrace();}}
}

Java基础--I/O流知识总结相关推荐

  1. 【Java基础】· IO流习题详解

    写在前面 Hello大家好, 我是[麟-小白],一位软件工程专业的学生,喜好计算机知识.希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!谢谢大家!!! ...

  2. Java基础学习—— IO流

    Java基础学习-- IO流 1 文件 1.1 文件的创建 1.2 文件常用的方法 2 IO流 2.1 FileInputStream 2.2 FileOutputStream 2.3 文件的拷贝 2 ...

  3. java基础学习_IO流03_字符流、IO流小结、案例_day21总结

    java基础学习_IO流03_字符流.IO流小结.案例_day21总结 ================================================================ ...

  4. 【java基础】IO流是啥?有啥用?(上)

    今天我们说说java代码中对文件的操作,比如新建删除文件,读取文件内容等. File类 File类用于操作文件和目录,可对文件或目录进行新建,删除和重命名等操作.但是如果要访问文件内容本身,就需要用到 ...

  5. Java基础之IO流操作

    第14章 File类与IO流 主要内容 File类 字节流 字符流 文件流 缓冲流 转换流 数据流 对象流 打印流 Scanner与System与IO流 教学目标 使用File类对象表示文件或目录 能 ...

  6. java基础 I/O流

    目录 第一章I/O概述 1.1什么是I/o 1.2I/o的分类 1.3 IO的流向说明图解 1.4顶级父类 第二章字节流 2.1一切皆为字节 2.2字节输出流OutputStream 2.3 File ...

  7. Java基础学习-IO流

    package IObasics; import java.io.FileWriter; import java.io.IOException;/*IO流* 通过数据流.序列化和文件系统提供系统输入和 ...

  8. Java基础进阶IO流概述

    1.IO流,什么是IO? I : Input O : Output 通过IO可以完成硬盘文件的读和写. 2.IO流的分类? 有多种分类方式: 一种方式是按照流的方向进行分类: 以内存作为参照物 往内存 ...

  9. 一篇文章教你学会Java基础I/O流

    文章目录 一.初始IO流 1.什么是流 2.IO流的分类 二.字节输入输出流 1.字节输入流(InputStream) 2.字节输出流(OutputStream) 3.文件拷贝 三.处理流和转换流 写 ...

最新文章

  1. aes前台加密后台解密
  2. sqlserver2008 R2中查找未使用过的索引
  3. php中post提交参数_PHP中Http协议post请求参数
  4. 数据中心外包面临法律考验
  5. 区块链BaaS云服务(24)秘猿科技CITA
  6. lg g7 android9,随着Android 11的临近 LG G7 ThinQ在其最后一家美国运营商处获得了Android 9更新...
  7. python综合练习1-- 用户登录
  8. 如何检查并unregister本地注册的Chrome service worker
  9. halcon找矩形顶点的一种方法
  10. Ant 构建文件的一种写法
  11. matlab 有公式 变量,matlab两个变量拟合公式x=0.40.450.50.550? 爱问知识人
  12. 电气图纸制图规范及电气图纸的识读方法大全
  13. 微信表白代码,单身汪们还不快收藏!
  14. 如何评价《守望先锋》架构设计?
  15. VBS学习笔记(4): WScript //d //x MyScript.vbs,调试无法启动
  16. IE8 SysFader:IEXPLORE.EXE应用程序错误解决办法
  17. Photoshop标尺单位介绍以及录制动作标尺单位选择的重要性
  18. 网络流专题班例题和练习
  19. OpenCV——Harris、Shi Tomas、自定义、亚像素角点检测
  20. 【微信小游戏】游戏性能检测

热门文章

  1. 限界上下文(BC)是什么
  2. win10使用python的strftime有错误_win10系统提示werfault.exe应用程序错误如何解决
  3. A005-软件结构-从前后台到调度器
  4. 常见思维模型汇总(一)
  5. [CF1603D]Artistic Partition
  6. 纽扣电池命名(常规表述)
  7. 发款php蜘蛛统计插件只要有mysql就可用
  8. 中国书法名词解释大全
  9. 宝真酒业:借助用友U8cloud数智化转型,小集团也能“小而美”
  10. 红帽linux怎么截图,Linux上使用Ksnip截图