• JAVA IO流的原理介绍和流的分类


    • IO流的原理

    I/O是Input/Output的缩写, I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通讯等。Java程序中,对于数据的输入/输出操作以“流(stream)” 的方式进行。java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。

    输入input:读取外部数据(磁 盘、光盘等存储设备的数据)到 程序(内存)中。

    输出output:将程序(内存) 数据输出到磁盘、光盘等存储设 备中。

    • 流(stream)的分类

    概括

    按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)


    按数据流的流向不同分为:输入流,输出流

    按流的角色的不同分为:节点流,处理流

    节点流:直接从数据源或目的地读写数据

    处理流:不直接连接到数据源或目的地,而是“连接”在已存 在的流(节点流或处理流)之上,通过对数据的处理为程序提 供更为强大的读写功能。

    流的分类图例

    IO流体系

    •  流的基础类

    输入流基础类

    前言

    InputStream 和 Reader 是所有输入流的基类。 

    程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资 源,所以应该显式关闭文件 IO 资源。

    FileInputStream 从文件系统中的某个文件中获得输入字节。FileInputStream 用于读取非文本数据之类的原始字节流。要读取字符流,需要使用 FileReader 

    InputStream

    int read() 从输入流中读取数据的下一个字节。返回 0 到 255 范围内的 int 字节值。如果因 为已经到达流末尾而没有可用的字节,则返回值 -1。

    int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。如果因为已 经到达流末尾而没有可用的字节,则返回值 -1。否则以整数形式返回实际读取 的字节数。

    int read(byte[] b, int off,int len) 将输入流中最多 len 个数据字节读入 byte 数组。尝试读取 len 个字节,但读取 的字节也可能小于该值。以整数形式返回实际读取的字节数。如果因为流位于 文件末尾而没有可用的字节,则返回值 -1。

    public void close() throws IOException 关闭此输入流并释放与该流关联的所有系统资源。

    Reader

    int read() 读取单个字符。作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff)(2个 字节的Unicode码),如果已到达流的末尾,则返回 -1 

    int read(char[] cbuf) 将字符读入数组。如果已到达流的末尾,则返回 -1。否则返回本次读取的字符数。

    int read(char[] cbuf,int off,int len) 将字符读入数组的某一部分。存到数组cbuf中,从off处开始存储,最多读len个字 符。如果已到达流的末尾,则返回 -1。否则返回本次读取的字符数。

    public void close() throws IOException 关闭此输入流并释放与该流关联的所有系统资源。

     输出流基础类

    前言

    outputStream 和 writer 是所有输入流的基类。 

    因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组, 即以 String 对象作为参数 :void write(String str); / void write(String str, int off, int len);

    FileOutputStream 从文件系统中的某个文件中获得输出字节。FileOutputStream 用于写出非文本数据之类的原始字节流。要写出字符流,需要使用 FileWriter

    OutputStream

    void write(int b) 将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。要写 入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。 即写入0~255范围的。

    void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。write(b) 的常规协定是:应该 与调用 write(b, 0, b.length) 的效果完全相同。

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

    public void flush()throws IOException 刷新此输出流并强制写出所有缓冲的输出字节,调用此方法指示应将这些字节立 即写入它们预期的目标。

    public void close() throws IOException 关闭此输出流并释放与该流关联的所有系统资源。

    Writer

    void write(int c) 写入单个字符。要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略。 即 写入0 到 65535 之间的Unicode码。 

    void write(char[] cbuf) 写入字符数组。

    void write(char[] cbuf,int off,int len) 写入字符数组的某一部分。从off开始,写入len个字符

    void write(String str) 写入字符串。

    void write(String str,int off,int len) 写入字符串的某一部分。

    void flush() 刷新该流的缓冲,则立即将它们写入预期目标。

    public void close() throws IOException 关闭此输出流并释放与该流关联的所有系统资源。

    • 节点流(文件流)

    注:以下代码演示均为字符流 (FileReader、FileWriter)的操作,处理字节流文件请更换为字节流(FileInputStream、FileOutputStream)

    读取文件

    步骤

    1. //1.建立一个流对象,将已存在的一个文件加载进流。
    2. FileReader fr = new FileReader(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));
    3. //2.创建一个临时存放数据的数组。
    4. char[] c = new char[1024];
    5. //3.调用流对象的读取方法将流中的数据读入到数组中。
    6. fr.read(c);
    7. //4.关闭流的资源
    8. fr.close();

     代码演示

    读取的时候使用:int read()方法

    1. FileReader fr = null;
    2. try {
    3. //1.建立一个流对象,将已存在的一个文件加载进流。
    4. fr = new FileReader(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));
    5. //2.调用流对象的读取方法将流中的数据读入到数组中。
    6. int len;
    7. while ((len = fr.read()) != -1){
    8. System.out.print((char) len);
    9. }
    10. } catch (IOException e) {
    11. e.printStackTrace();
    12. } finally {
    13. //3.关闭流的资源
    14. try {
    15. if (fr != null)
    16. fr.close();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. }
    20. }

    读取的时候使用:int read(char[] cbuf)方法

    1. FileReader fr = null;
    2. try {
    3. //1.建立一个流对象,将已存在的一个文件加载进流。
    4. fr = new FileReader(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));
    5. //2.创建一个临时存放数据的数组。
    6. char[] cfr = new char[1024];
    7. //3.调用流对象的读取方法将流中的数据读入到数组中。
    8. int len;
    9. while ((len = fr.read(cfr)) != -1){
    10. //方式1:
    11. for (int i = 0; i < len; i++) {
    12. System.out.print(cfr[i]);
    13. }
    14. //方式2:
    15. String str = new String(cfr,0,len);
    16. System.out.print(str);
    17. }
    18. } catch (IOException e) {
    19. e.printStackTrace();
    20. } finally {
    21. //4.关闭流的资源
    22. try {
    23. if (fr != null)
    24. fr.close();
    25. } catch (IOException e) {
    26. e.printStackTrace();
    27. }
    28. }

    写入文件

    步骤

    1. //1.创建流对象,建立数据存放文件
    2. FileWriter fw = new FileWriter(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));
    3. //2.调用流对象的写入方法,将数据写入流
    4. fw.write("写入的数据。。。");
    5. //3.关闭流资源,并将流中的数据清空到文件中。
    6. fw.close();

    代码演示

    1. FileWriter fw = null;
    2. try {
    3. //1.创建流对象,建立数据存放文件
    4. fw = new FileWriter(new File("E:\\JAVA\\java2\\src\\day8\\helloCopy.png"));
    5. //2.调用流对象的写入方法,将数据写入流
    6. fw.write("I am a superman\n");
    7. fw.write("you are a superman too");
    8. } catch (IOException e) {
    9. e.printStackTrace();
    10. } finally {
    11. //3.关闭流资源,并将流中的数据清空到文件中。
    12. if (fw != null){
    13. try {
    14. fw.close();
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. }
    18. }
    19. }

    读入文件和写入文件组合

    1. FileReader srcFile = null;
    2. FileWriter destFile = null;
    3. try {
    4. //1.创建输入输出流的对象,指明读入和写出的文件
    5. srcFile = new FileReader(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));
    6. destFile = new FileWriter(new File("E:\\JAVA\\java2\\src\\day8\\hello1.png"));
    7. //2.数据的读入和写出操作
    8. char[] cbuf = new char[1024];
    9. //记录每次读入到cbuf数组中的字符的个数
    10. int len;
    11. while ((len = srcFile.read(cbuf)) != -1){
    12. //每次写出len个字符
    13. destFile.write(cbuf,0,len);
    14. }
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. } finally {
    18. //3.关闭流资源
    19. /*//方式1:
    20. try {
    21. if (destFile != null)
    22. destFile.close();
    23. } catch (IOException e) {
    24. e.printStackTrace();
    25. }finally {
    26. try {
    27. if (srcFile != null)
    28. srcFile.close();
    29. } catch (IOException e) {
    30. e.printStackTrace();
    31. }
    32. }*/
    33. //方式2:
    34. try {
    35. if (destFile != null)
    36. destFile.close();
    37. } catch (IOException e) {
    38. e.printStackTrace();
    39. }
    40. try {
    41. if (srcFile != null)
    42. srcFile.close();
    43. } catch (IOException e) {
    44. e.printStackTrace();
    45. }
    46. }

    节点流(或文件流):注意点

    1.定义文件路径时,注意:可以用“/”或者“\\”。
    2.在写入一个文件时,如果使用构造器FileOutputStream(file),则目录下有同名文件将被覆盖。
    3.如果使用构造器FileOutputStream(file,true),则目录下的同名文件不会被覆盖,在文件内容末尾追加内容。
    4.在读取文件时,必须保证该文件已存在,否则报异常。
    5.字节流操作字节,比如:.mp3,.avi,.rmvb,mp4,.jpg,.doc,.ppt
    6.字符流操作字符,只能操作普通文本文件。最常见的文本文件:.txt,.java,.c,.cpp 等语言的源代码。尤其注意.doc,excel,ppt这些不是文本文件。

    • 缓冲流

    说明

    1.缓冲流是处理流的一种,内部提供了一个缓冲区,提供流的读取、写入的速度。
    2.为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。
    3.缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
     操作字节数据类型的:BufferedInputStream 和 BufferedOutputStream
     操作字符数据类型的:BufferedReader 和 BufferedWriter
    4.当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次性从文件中读取8192个(8Kb),存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个8192个字节数组。
    5.向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法flush()可以强制将缓冲区的内容全部写入输出流
    6.flush()方法的使用:手动将buffer中内容写入文件
    7.关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流
    8.如果是带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出
    9.当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区 

    缓冲流处理字节类型数据

    1. /**
    2. * @description 使用缓冲流复制字节类型的数据
    3. * @author Alvin
    4. * @param srcFile:需要复制的字节文件地址
    5. * @param destFile:复制到的文件地址
    6. * @date 2022年8月17日15:19:39
    7. * @version
    8. */
    9. private static void copyFileWithBuffered(String srcFile,String destFile) {
    10. BufferedInputStream bis = null;
    11. BufferedOutputStream bos = null;
    12. try {
    13. //1.创建文件和相应的节点流
    14. FileInputStream fis = new FileInputStream(new File(srcFile));
    15. FileOutputStream fos = new FileOutputStream(new File(destFile));
    16. //2.创建缓冲流
    17. bis = new BufferedInputStream(fis);
    18. bos = new BufferedOutputStream(fos);
    19. //3.读取、写入
    20. byte[] bbuf = new byte[1024];
    21. int len;
    22. while ((len = bis.read(bbuf)) != -1){
    23. bos.write(bbuf,0,len);
    24. bos.flush();
    25. }
    26. } catch (IOException e) {
    27. e.printStackTrace();
    28. } finally {
    29. //4.流资源关闭(要求:先关闭外层的流,再关闭内层的流)
    30. try {
    31. if (bos != null)
    32. bos.close();
    33. } catch (IOException e) {
    34. e.printStackTrace();
    35. }
    36. if (bis != null) {
    37. try {
    38. bis.close();
    39. } catch (IOException e) {
    40. e.printStackTrace();
    41. }
    42. }
    43. //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
    44. // fos.close();
    45. // fis.close();
    46. }
    47. }

    缓冲流处理字符类型的数据

    1. /**
    2. * @description 使用缓冲流复制字符类型的数据
    3. * @author Alvin
    4. * @param srcFile:需要复制的字符文件地址
    5. * @param destFile:复制到的文件地址
    6. * @date 2022年8月17日16:05:04
    7. * @version
    8. */
    9. public static void copyCharFileWithBuffered(String srcFile,String destFile){
    10. BufferedReader bd = null;
    11. BufferedWriter bw = null;
    12. try {
    13. //1.创建文件和相应的节点流+缓冲流
    14. bd = new BufferedReader(new FileReader(new File(srcFile)));
    15. bw = new BufferedWriter(new FileWriter(new File(destFile)));
    16. //2.读写操作
    17. /*//方式1:使用char[]数组
    18. char[] cbuf = new char[1024];
    19. int len;
    20. while ((len = bd.read(cbuf)) != -1){
    21. bw.write(cbuf,0,len);
    22. }*/
    23. //方式2:使用String
    24. String data;
    25. while ((data = bd.readLine()) != null){
    26. //方法1:
    27. bw.write(data + "\n");//data中不包含换行符
    28. //方法2:
    29. bw.write(data);
    30. bw.newLine();//提供换行的操作
    31. }
    32. } catch (IOException e) {
    33. e.printStackTrace();
    34. } finally {
    35. //3.关闭流资源
    36. if (bw != null) {
    37. try {
    38. bw.close();
    39. } catch (IOException e) {
    40. e.printStackTrace();
    41. }
    42. }
    43. try {
    44. if (bd != null)
    45. bd.close();
    46. } catch (IOException e) {
    47. e.printStackTrace();
    48. }
    49. }
    50. }
    • 转换流

    说明

    1.转换流:属于字符流。
    2.转换流提供了在字节流和字符流之间的转换
    3.Java API提供了两个转换流:
     InputStreamReader:将InputStream转换为Reader(解码:字节、字节数组  --->字符数组、字符串)
     OutputStreamWriter:将Writer转换为OutputStream(编码:字符数组、字符串 ---> 字节、字节数组)
    4.字节流中的数据都是字符时,转成字符流操作更高效。
    5.很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。 

    代码演示:将utf-8的文件格式转化为gbk文件格式

    1. InputStreamReader isr = null;
    2. OutputStreamWriter osr = null;
    3. try {
    4. FileInputStream fis = new FileInputStream(new File("E:\\JAVA\\java2\\src\\day8\\hello.txt"));
    5. FileOutputStream fos = new FileOutputStream(new File("E:\\JAVA\\java2\\src\\day8\\hello1.txt"));
    6. isr = new InputStreamReader(fis,"utf-8");//该“utf-8“参数指明了字符集,具体使用哪个字符集,取决于文件保存时使用的字符集
    7. osr = new OutputStreamWriter(fos,"GBK");//再次编码的时候,可以指定新的字符集
    8. char[] cbuf = new char[1024];
    9. int len;
    10. while ((len = isr.read(cbuf)) != -1){
    11. osr.write(cbuf,0,len);
    12. }
    13. } catch (IOException e) {
    14. e.printStackTrace();
    15. } finally {
    16. if (osr != null) {
    17. try {
    18. osr.close();
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. }
    22. }
    23. try {
    24. if (isr != null)
    25. isr.close();
    26. } catch (IOException e) {
    27. e.printStackTrace();
    28. }
    29. }
    • 标准输入、输出流

    前言

    System.in和System.out分别代表了系统标准的输入和输出设备
    默认输入设备是:键盘,输出设备是:显示器
    System.in的类型是InputStream
    System.out的类型是PrintStream,其是OutputStream的子类FilterOutputStream 的子类
    重定向:通过System类的setIn,setOut方法对默认设备进行改变。
    public static void setIn(InputStream in)
    public static void setOut(PrintStream out)

    代码演示

    1. /* 从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续
    2. 进行输入操作,直至当输入“e”或者“exit”时,退出程序。*/
    3. public static void main(String[] args) {
    4. BufferedReader br = null;
    5. try {
    6. // 把"标准"输入流(键盘输入)这个字节流包装成字符流,再包装成缓冲流
    7. InputStreamReader isr = new InputStreamReader(System.in);
    8. br = new BufferedReader(isr);
    9. while (true){
    10. System.out.println("请输入字符串:");
    11. String data = br.readLine(); // 读取用户输入的一行数据 --> 阻塞程序
    12. if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)){
    13. System.out.println("程序结束!");
    14. break;
    15. }
    16. String upperCase = data.toUpperCase();
    17. System.out.println(upperCase);
    18. }
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. } finally {
    22. if (br != null) {
    23. try {
    24. br.close();
    25. } catch (IOException e) {
    26. e.printStackTrace();
    27. }
    28. }
    29. }
    30. }

    public static void setIn(InputStream in)

    1. public static void main(String[] args) {
    2. OutputStreamWriter osw = null;
    3. BufferedReader br = null;
    4. try {
    5. //创建新的文件输入流
    6. InputStream ps = new FileInputStream("java2\\\\src\\\\dayExercise\\\\Files\\\\log.txt");
    7. //创建标准输出流
    8. osw = new OutputStreamWriter(System.out);
    9. //将标准输入流替换成新的文件输入流
    10. System.setIn(ps);
    11. br = new BufferedReader(new InputStreamReader(System.in));
    12. char[] cbuf = new char[1024];
    13. //此时读入内存的为新的文件输入流内容,非控制台输入的内容
    14. int i = br.read(cbuf);
    15. //输出在控制台的为文件内容如
    16. osw.write(cbuf,0,i);
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. } finally {
    20. try {
    21. if (br != null)
    22. br.close();
    23. } catch (IOException e) {
    24. e.printStackTrace();
    25. }
    26. try {
    27. if (osw != null)
    28. osw.close();
    29. } catch (IOException e) {
    30. e.printStackTrace();
    31. }
    32. }
    33. }

    public static void setOut(PrintStream out) 

    1. public static void main(String[] args) {
    2. try {
    3. //创建输出流,保存键盘输出的内容
    4. PrintStream ps = new PrintStream("java2\\src\\dayExercise\\Files\\log.txt");
    5. //创建标准程序输出流,用来输出提示语
    6. PrintStream out = System.out;
    7. //键盘录入数据
    8. Scanner scanner = new Scanner(System.in);
    9. String line = "";
    10. System.out.println("请输入:");
    11. while (scanner.hasNextLine()) {
    12. line = scanner.nextLine();
    13. if (line.equalsIgnoreCase("exit")){
    14. System.out.println("程序结束!输入的信息已存储到对应文件中。");
    15. break;
    16. }
    17. //创新指定输出流
    18. System.setOut(ps);
    19. System.out.println(line);
    20. //还原为标准输出流,输入提示语句
    21. System.setOut(out);
    22. System.out.println("输入的信息已存储到对应文件中。请继续输入(输入exit结束程序):");
    23. }
    24. } catch (FileNotFoundException e) {
    25. // TODO: handle exception
    26. e.printStackTrace();
    27. }
    28. }

    •  打印流

    前言

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

    代码演示

    1. //打印流可以使用System.setOut()方法将本来通过[System.out.print()]方法输入在控制台的文件给储存起来
    2. PrintStream ps = null;
    3. try {
    4. FileOutputStream fos = new FileOutputStream(new File("E:\\JAVA\\java2\\src\\day8\\hello1.txt"));
    5. // 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
    6. ps = new PrintStream(fos, true);
    7. if (ps != null) {// 把标准输出流(控制台输出)改成文件存储
    8. System.setOut(ps);
    9. }
    10. //打印ASCII的字符
    11. for (int i = 0; i < 255; i++) {
    12. System.out.print((char) i);
    13. if (i % 50 == 0) {// 每50个数据一行
    14. System.out.println();//换行
    15. }
    16. }
    17. } catch (FileNotFoundException e) {
    18. e.printStackTrace();
    19. } finally {
    20. try {
    21. if (ps != null)
    22. ps.close();
    23. } catch (Exception e) {
    24. e.printStackTrace();
    25. }
    26. }
    • 数据流

    前言

    为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流。
    数据流有两个类:(用于读取和写出基本数据类型、String类的数据)
     DataInputStream 和 DataOutputStream
     分别“套接”在 InputStream 和 OutputStream 子类的流上
    DataInputStream中的方法
        boolean readBoolean()
        byte readByte()
        char readChar()
        float readFloat()
        double readDouble()
        short readShort()
        long readLong()
        int readInt()
        String readUTF()
        void readFully(byte[] b)
    DataOutputStream中的方法
     将上述的方法的read改为相应的write即可。

    代码演示

    内存的基本数据类型的变量或字符串(自定义对象需要下面对象流处理)写出到文件中

    1. //将内存中的字符串、基本数据类型的变量写出到文件中。
    2. DataOutputStream dos = null;
    3. try {
    4. dos = new DataOutputStream(new FileOutputStream("E:\\JAVA\\java2\\src\\day8\\data.dat"));
    5. dos.writeUTF("我是中国人!");
    6. dos.flush();//刷新操作,将内存中的数据写入文件
    7. dos.writeBoolean(true);
    8. dos.flush();
    9. dos.writeLong(12121212L);
    10. dos.flush();
    11. System.out.println("写入成功");
    12. } catch (IOException e) {
    13. e.printStackTrace();
    14. } finally {
    15. try {
    16. if (dos != null)
    17. dos.close();
    18. } catch (IOException e) {
    19. e.printStackTrace();
    20. }
    21. }

     将文件中储存的基本数据类型的变量或字符串(自定义对象需要下面对象流处理)写入到内存中

     注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!

    1. //将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。
    2. //注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!
    3. DataInputStream dis = null;
    4. try {
    5. dis = new DataInputStream(new FileInputStream("E:\\JAVA\\java2\\src\\day8\\data.dat"));
    6. String str = dis.readUTF();
    7. boolean b = dis.readBoolean();
    8. Long l = dis.readLong();
    9. System.out.println(str);
    10. System.out.println(b);
    11. System.out.println(l);
    12. } catch (IOException e) {
    13. e.printStackTrace();
    14. } finally {
    15. try {
    16. if (dis != null)
    17. dis.close();
    18. } catch (IOException e) {
    19. e.printStackTrace();
    20. }
    21. }
    • 对象流

    前言

    1.ObjectInputStream 和 ObjectOutputStream
    2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
    3.ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
    4.序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
       反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
    5.序列化机制:
      5.1对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。  当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
      5.2序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原
      5.3序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是 JavaEE 的基础。因此序列化机制是JavaEE 平台的基础
    6.要想一个java对象是可序列化的,需要满足相应的要求。
      6.1如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一(Serializable、Externalizable  )。否则,会抛出NotSerializableException异常
      6.2凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:private static final long serialVersionUID; serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容。如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议,显式声明。
      6.3简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)
      6.4如果某个类的属性不是基本数据类型或 String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的Field 的类也不能序列化 

     序列化代码演示

    序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去,使用ObjectOutputStream实现

    1. ObjectOutputStream oos = null;
    2. try {
    3. //创建一个 ObjectOutputStream
    4. oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
    5. //调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化对象
    6. oos.writeObject(new String("我爱我得祖国"));
    7. //注意写出一次,操作flush()一次
    8. oos.flush();
    9. oos.writeObject(new Person("张三",23,001));
    10. oos.flush();
    11. oos.writeObject(new Person("李四",24,002,new Account(1000)));
    12. oos.flush();
    13. } catch (IOException e) {
    14. e.printStackTrace();
    15. } finally {
    16. try {
    17. if (oos != null)
    18. oos.close();
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. }
    22. }

    反序列化代码演示

    反序列化:将磁盘文件中的对象还原为内存中的一个java对象,使用ObjectInputStream来实现

    1. ObjectInputStream ois = null;
    2. try {
    3. //创建一个 ObjectInputStream
    4. ois = new ObjectInputStream(new FileInputStream("object.dat"));
    5. //调用 readObject() 方法读取流中的对象
    6. Object o = ois.readObject();
    7. String str = (String) o;
    8. Person p1 = (Person) ois.readObject();
    9. Person p2 = (Person) ois.readObject();
    10. Person p3 = (Person) ois.readObject();
    11. System.out.println(str);
    12. System.out.println(p1);
    13. System.out.println(p2);
    14. System.out.println(p3);
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. } catch (ClassNotFoundException e) {
    18. e.printStackTrace();
    19. } finally {
    20. try {
    21. if (ois != null)
    22. ois.close();
    23. } catch (IOException e) {
    24. e.printStackTrace();
    25. }
    26. }

    谈谈对java.io.Serializable接口的理解

    1.我们知道它用于序列化,是空方法接口
    2.实现了Serializable接口的对象,可将它们转换成一系列字节,并可在以后完全恢复回原来的样子。这一过程亦可通过网络进行。这意味着序列化机制能自动补偿操作系统间的差异。换句话说,可以先在Windows机器上创建一个对象,对其序列化,然后通过网络发给一台Unix机器,然后在那里准确无误地重新“装配”。不必关心数据在不同机器上如何表示,也不必关心字节的顺序或者其他任何细节。
    3.由于大部分作为参数的类如String、Integer等都实现了java.io.Serializable的接口,也可以利用多态的性质,作为参数使接口更灵活。 

    • 随机存取文件流

    前言

    RandomAccessFile的使用
    1. RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
    2. RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
    3. 如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)
    4. RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。RandomAccessFile 类对象可以自由移动记录指针:
     long getFilePointer():获取文件记录指针的当前位置
     void seek(long pos):将文件记录指针定位到 pos 位置
    5. 可以通过相关的操作,实现RandomAccessFile“插入”数据的效果
    构造器
     public RandomAccessFile(File file, String mode)
     public RandomAccessFile(String name, String mode)
    < 创建 RandomAccessFile 类实例需要指定一个 mode 参数,该参数指定 RandomAccessFile 的访问模式:
     r: 以只读方式打开
     rw:打开以便读取和写入
     rwd:打开以便读取和写入;同步文件内容的更新
     rws:打开以便读取和写入;同步文件内容和元数据的更新
    < 如果模式为只读r。则不会创建文件,而是会去读取一个已经存在的文件,如果读取的文件不存在则会出现异常。 如果模式为rw读写。如果文件不存在则会去创建文件,如果存在则不会创建。
    < JDK1.6上面写的每次write数据时,“rw”模式,数据不会立即写到硬盘中;而“rwd”,数据会别立即写入硬盘,如果写数据过程发生异常,“rwd”模式中已被write的数据被保存在硬盘中,而“rw”则全部丢失。

    代码演示

    1. RandomAccessFile raf1 = null;
    2. RandomAccessFile raf2 = null;
    3. try {
    4. //创建读入文件流
    5. raf1 = new RandomAccessFile(new File("E:\\JAVA\\java2\\正能量.png"), "r");
    6. //创建写出文件流
    7. raf2 = new RandomAccessFile(new File("E:\\JAVA\\java2\\正能量1.png"), "rw");
    8. byte[] bbuf = new byte[1024];
    9. int len;
    10. while ((len = raf1.read(bbuf)) != -1){
    11. raf2.write(bbuf,0,len);
    12. }
    13. } catch (IOException e) {
    14. e.printStackTrace();
    15. } finally {
    16. try {
    17. if (raf1 != null)
    18. raf1.close();
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. }
    22. try {
    23. if (raf2 != null)
    24. raf2.close();
    25. } catch (IOException e) {
    26. e.printStackTrace();
    27. }
    28. }

    使用RandomAccessFile实现数据的插入效果

    使用StringBuffer存储插入位置后边的内容:

    1. RandomAccessFile raf = null;
    2. try {
    3. //需求:在hello.txt文件角标为3的位置插入”abc”
    4. raf = new RandomAccessFile("E:\\JAVA\\java2\\src\\day8\\hello.txt","rw");
    5. //将指针调到角标为3的位置
    6. raf.seek(3);
    7. //保存指针3后面的所有数据放到StringBuilder中
    8. StringBuffer StrBuf = new StringBuffer((int) new File("E:\\JAVA\\java2\\src\\day8\\hello.txt").length());
    9. byte[] bbuf = new byte[1024];
    10. int len;
    11. while ((len = raf.read(bbuf)) != -1){
    12. StrBuf.append(new String(bbuf,0,len));
    13. }
    14. //调回指针,写入“abc”
    15. raf.seek(3);
    16. raf.write("abc".getBytes());
    17. //将StringBuilder中的数据写入到文件中
    18. raf.write(StrBuf.toString().getBytes());
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. } finally {
    22. if (raf != null){
    23. try {
    24. raf.close();
    25. } catch (IOException e) {
    26. e.printStackTrace();
    27. }
    28. }
    29. }

     使用ByteArrayOutputStream存储插入位置后边的内容:

    1. @Test
    2. public void test1() throws Exception {
    3. RandomAccessFile raf = new RandomAccessFile("E:\\JAVA\\java2\\src\\day8\\hello.txt","rw");
    4. //将指针调到角标为3的位置
    5. raf.seek(3);
    6. //保存指针3后面的所有数据放到ByteArrayOutputStream对象info中
    7. String info = readStringFromInputStream(raf);
    8. //调回指针,写入“hhhhh”
    9. raf.seek(3);
    10. raf.write("hhhhh".getBytes());
    11. //将info中的数据写入到文件中
    12. raf.write(info.getBytes());
    13. }
    14. /**
    15. * @description 使用ByteArrayOutputStream存储插入位置后边的内容
    16. * @param raf 随机存取流对象
    17. * @return 返回存储数据的ByteArrayOutputStream对象
    18. * @throws IOException
    19. */
    20. private String readStringFromInputStream(RandomAccessFile raf) throws IOException {
    21. ByteArrayOutputStream baos = new ByteArrayOutputStream();
    22. byte[] buffer = new byte[10];
    23. int len;
    24. while ((len = raf.read(buffer)) != -1) {
    25. baos.write(buffer, 0, len);
    26. }
    27. return baos.toString();
    28. }
    • NIO.2中Path、 Paths、Files类的使用

    Java NIO概述

    1. Java NIO (New IO,Non-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。
    2. Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。
    3. 随着 JDK 7 的发布,Java对NIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为 NIO.2。因为 NIO 提供的一些功能,NIO已经成为文件处理中越来越重要的部分。
    4. 早期的Java只提供了一个File类来访问文件系统,但File类的功能比较有限,所提供的方法性能也不高。而且,大多数方法在出错时仅返回失败,并不会提供异常信息。
    5. NIO. 2为了弥补这种不足,引入了Path接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。Path可以看做是java.io.File类的升级版本。也可以表示文件或文件目录,与平台无关
    6. 同时,NIO.2在java.nio.file包下还提供了Files、Paths工具类,Files包含了大量静态的工具方法来操作文件;Paths则包含了两个返回Path的静态工厂方法。
    7. Paths 类提供的静态 get() 方法用来获取 Path 对象(如何实例化Path:使用Paths):
     static Path get(String first, String … more) : 用于将多个字符串串连成路径
     static Path get(URI uri): 返回指定uri对应的Path路径

    Path类 

    Path类的实例化

    1. Path path1 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello1.txt");//相当于:new File(String filepath)
    2. Path path2 = Paths.get("E:\\JAVA\\java2\\src\\day8", "hello1.txt");//相当于new File(String parent,String filename);

    Path中的常用方法

    一下代码演示用到的实例化对象path和path1

    1. Path path = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello1.txt");
    2. Path path1 = Paths.get("hello1.txt");

    Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象 

    1. Path absolutePath = path.toAbsolutePath();
    2. System.out.println(absolutePath);//E:\JAVA\java2\src\day8\hello1.txt
    3. Path absolutePath1 = path1.toAbsolutePath();
    4. System.out.println(absolutePath1);//E:\JAVA\java2\src\day8\hello1.txt

    File toFile(): 将Path转化为File类的对象  《------》Path toPath(): 将Flie转化为Path类的对象

    1. File file = path.toFile();//Path--->File的转换
    2. Path path2 = file.toPath();//File--->Path的转换

    Path resolve(Path p) :合并两个路径,返回合并后的路径对应的Path对象

    1. Path resolve = path.resolve("day9\\hello2.txt");
    2. System.out.println(resolve);//E:\JAVA\java2\src\day8\hello1.txt\day9\hello2.txt
    3. Path resolve1 = path1.resolve("day9\\hello2.txt");
    4. System.out.println(resolve1);// hello1.txt\day9\hello2.txt

    Path getName(int idx) : 返回指定索引位置 idx 的路径名称

    1. Path name = path.getName(2);
    2. System.out.println(name);//src
    3. //Path name1 = path1.getName(2);
    4. //System.out.println(name1);//java.lang.IllegalArgumentException

    int getNameCount() : 返回Path 根目录后面元素的数量

    1. int nameCount = path.getNameCount();
    2. System.out.println(nameCount);//5
    3. int nameCount1 = path1.getNameCount();
    4. System.out.println(nameCount1);//1

    Path getFileName() : 返回与调用 Path 对象关联的文件名

    1. Path fileName = path.getFileName();
    2. System.out.println(fileName);//hello1.txt
    3. Path fileName1 = path1.getFileName();
    4. System.out.println(fileName1);//hello1.txt

    Path getRoot() :返回调用 Path 对象的根路径

    1. Path root = path.getRoot();
    2. System.out.println(root);//E:\
    3. Path root1 = path1.getRoot();
    4. System.out.println(root1);//null

    Path getParent() :返回Path对象包含整个路径,不包含 Path 对象指定的文件路径

    1. Path parent = path.getParent();
    2. System.out.println(parent);//E:\JAVA\java2\src\day8
    3. Path parent1 = path1.getParent();
    4. System.out.println(parent1);//null

    boolean isAbsolute() : 判断是否是绝对路径

    1. boolean absolute = path.isAbsolute();
    2. System.out.println(absolute);//true
    3. boolean absolute1 = path1.isAbsolute();
    4. System.out.println(absolute1);//false

    boolean endsWith(String path) : 判断是否以 path 路径结束

    1. boolean endsWith = path.endsWith("hello1.txt");
    2. System.out.println(endsWith);//true

    boolean startsWith(String path) : 判断是否以 path 路径开始

    1. boolean startsWith = path.startsWith("E:\\JAVA");
    2. System.out.println(startsWith);//true

    String toString() : 返回调用 Path 对象的字符串表示形式

    System.out.println(path.toString());//toString可是省略 //E:\JAVA\java2\src\day8\hello1.txt

    Files类

     java.nio.file.Files 用于操作文件或目录的工具类。

    Files类常用方法

     Path copy(Path src, Path dest, CopyOption … how) : 文件的复制

    1. Path path1 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello1.txt");
    2. Path path2 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");
    3. //要想复制成功,要求path1对应的物理上的文件存在。path2对应的文件没有要求。
    4. Path pathCopy = Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING);

    Path createDirectory(Path path, FileAttribute … attr) : 创建一个目录

    1. Path path3 = Paths.get("E:\\JAVA\\java2\\src\\day8");//该文件磁盘中存在
    2. Path path4 = Paths.get("E:\\JAVA\\java2\\src\\day9");//该文件磁盘中不存在
    3. //要想执行成功,要求path对应的物理上的文件目录不存在。一旦存在,抛出异常。
    4. //Path directory = Files.createDirectory(path3);//java.nio.file.FileAlreadyExistsException
    5. Path directory1 = Files.createDirectory(path4);

    Path createFile(Path path, FileAttribute … arr) : 创建一个文件

    1. Path path5 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello1.txt");//该文件磁盘中存在
    2. Path path6 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello3.txt");//该文件磁盘中不存在
    3. //要想执行成功,要求path对应的物理上的文件不存在。一旦存在,抛出异常。
    4. //Path file = Files.createFile(path5);//java.nio.file.FileAlreadyExistsException
    5. Path file1 = Files.createFile(path6);

    void delete(Path path) : 删除一个文件/目录,如果不存在,执行报错

    1. Path path7 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello3.txt");//该文件磁盘中存在
    2. Path path8 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello4.txt");//该文件磁盘中不存在
    3. //删除一个文件/目录,如果不存在,执行报错
    4. Files.delete(path7);
    5. //Files.delete(path8);//java.nio.file.NoSuchFileException

    void deleteIfExists(Path path) : Path对应的文件/目录如果存在,执行删除.如果不存在,正常执行结束

    1. Path path9 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello3.txt");//该文件磁盘中存在
    2. Path path10 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello4.txt");//该文件磁盘中不存在
    3. //Path对应的文件/目录如果存在,执行删除.如果不存在,正常执行结束
    4. Files.deleteIfExists(path9);
    5. Files.deleteIfExists(path10);//文件不存在时不会报错

    Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置

    1. Path path11 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello1.txt");//该文件磁盘中存在
    2. Path path12 = Paths.get("E:\\JAVA\\java2\\src\\day9\\hello1.txt");//该文件磁盘中不存在
    3. //要想执行成功,src对应的物理上的文件需要存在,dest对应的文件没有要求。
    4. Path move = Files.move(path11, path12, StandardCopyOption.ATOMIC_MOVE);

    long size(Path path) : 返回 path 指定文件的大小

    1. Path path13 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello1.txt");//该文件磁盘中存在
    2. Path path14 = Paths.get("E:\\JAVA\\java2\\src\\day9\\hello1.txt");//该文件磁盘中不存在
    3. long size = Files.size(path13);
    4. System.out.println(size);
    5. //long size1 = Files.size(path14);//java.nio.file.NoSuchFileException

    用于判断的方法

     boolean exists(Path path, LinkOption … opts) : 判断文件是否存在

    1. Path path1 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello1.txt");//该文件磁盘中存在
    2. Path path2 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello3.txt");//该文件磁盘中不存在
    3. boolean exists1 = Files.exists(path1,LinkOption.NOFOLLOW_LINKS);
    4. System.out.println(exists1);//true
    5. boolean exists2 = Files.exists(path2,LinkOption.NOFOLLOW_LINKS);
    6. System.out.println(exists2);//false

    boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在 

    1. Path path11 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");//文件存在
    2. Path path12 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello3.txt");//文件不存在
    3. boolean notExists1 = Files.notExists(path11,LinkOption.NOFOLLOW_LINKS);
    4. System.out.println(notExists1);//false
    5. boolean notExists2 = Files.notExists(path12,LinkOption.NOFOLLOW_LINKS);
    6. System.out.println(notExists2);//true

    boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录

    1. Path path3 = Paths.get("E:\\JAVA\\java2\\src\\day8");//目录
    2. Path path4 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");//文件
    3. boolean directory1 = Files.isDirectory(path3, LinkOption.NOFOLLOW_LINKS);
    4. System.out.println(directory1);//true
    5. boolean directory2 = Files.isDirectory(path4,LinkOption.NOFOLLOW_LINKS);
    6. System.out.println(directory2);//false

    boolean isRegularFile(Path path, LinkOption … opts) : 判断是否是文件

    1. Path path5 = Paths.get("E:\\JAVA\\java2\\src\\day8");//目录
    2. Path path6 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");//文件
    3. boolean regularFile1 = Files.isRegularFile(path5,LinkOption.NOFOLLOW_LINKS);
    4. System.out.println(regularFile1);//false
    5. boolean regularFile2 = Files.isRegularFile(path6,LinkOption.NOFOLLOW_LINKS);
    6. System.out.println(regularFile2);//true

     boolean isHidden(Path path) : 判断是否是隐藏文件

    1. Path path7 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");//文件存在
    2. Path path8 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello3.txt");//文件不存在
    3. //要求此path对应的物理上的文件需要存在。才可判断是否隐藏。否则,抛异常。
    4. boolean hidden = Files.isHidden(path7);
    5. System.out.println(hidden);//false
    6. //boolean hidden1 = Files.isHidden(path8);//java.nio.file.NoSuchFileException

    boolean isReadable(Path path) : 判断文件是否可读

    1. Path path9 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");//文件存在
    2. boolean readable = Files.isReadable(path9);
    3. System.out.println(readable);//true

    boolean isWritable(Path path) : 判断文件是否可写

    1. Path path10 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");//文件存在
    2. boolean writable = Files.isWritable(path10);
    3. System.out.println(writable);//true

    用于操作内容的方法

     SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连 接,how 指定打开方式。

    1. /*StandardOpenOption.READ:表示对应的Channel是可读的。
    2. StandardOpenOption.WRITE:表示对应的Channel是可写的。
    3. StandardOpenOption.CREATE:如果要写出的文件不存在,则创建。如果存在,忽略
    4. StandardOpenOption.CREATE_NEW:如果要写出的文件不存在,则创建。如果存在,抛异常*/
    5. Path path1 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");
    6. SeekableByteChannel Channel = Files.newByteChannel(path1, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

    DirectoryStream newDirectoryStream(Path path) : 打开 path 指定的目录

    1. Path path2 = Paths.get("E:\\JAVA\\java2\\src");
    2. DirectoryStream<Path> paths = Files.newDirectoryStream(path2);
    3. Iterator<Path> iterator = paths.iterator();
    4. while (iterator.hasNext()){
    5. System.out.println(iterator.next());
    6. }

    InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象

    1. Path path3 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");
    2. InputStream inputStream = Files.newInputStream(path3,StandardOpenOption.READ);

    OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象

    1. Path path4 = Paths.get("E:\\JAVA\\java2\\src\\day8\\hello2.txt");
    2. OutputStream outputStream = Files.newOutputStream(path4,StandardOpenOption.WRITE,StandardOpenOption.CREATE);

  • 相关阅读:
    QT当中的【QSetting和.ini配置文件】以及【创建Resources.qrc】
    使用并查集解决的相关问题
    完整大数据集群配置(从配置虚拟机到实操)
    如果你有一次自驾游的机会,你会如何准备?
    使用YAML配置Spring boot的外部属性
    金x软件有限公司安全测试岗位面试
    docker&kubernets篇(九)
    电脑开机蓝屏错误代码c000021a怎么办 电脑蓝屏报错c000021a的解决办法
    827. 最大人工岛
    opencv 图像识别 指纹识别 - python 计算机竞赛
  • 原文地址:https://blog.csdn.net/m0_58052874/article/details/126365723