• File类和IO流


    我是南城余!阿里云开发者平台专家博士证书获得者!

    欢迎关注我的博客!一同成长!

    一名从事运维开发的worker,记录分享学习。

    专注于AI,运维开发,windows Linux 系统领域的分享!

    本章节对应知识库

    File类和IO流 (yuque.com) 


    尚硅谷_宋红康_IO流.pptx

    小tips(科普):

    为什么创建文件对象时,文件即使不存在物理磁盘,也不会报错

    因为仅在Java层面创建了一个Java对象,并未对此进行读写操作,不然则会进行报错

    在Java中,当使用File类来代表一个文件时,如果该文件在文件系统中不存在,创建File对象并不会立即触发文件系统的访问,因此不会引发任何异常。

    File类代表了文件系统中的路径名,它可以作为文件或目录的抽象表示。当你创建一个File对象时,它只是在Java程序中创建了一个对象,并没有要求这个文件一定要存在。

    只有当你在对文件进行读取、写入或者执行其他与文件系统相关的操作时,才会真正触发对文件的访问。比如调用File对象的`exists()`方法或者创建文件输入输出流进行读写操作,才会触发文件系统的访问。

    当你调用File对象的某些方法时,如`delete()`、`createNewFile()`等,才会导致对文件系统的操作,如果文件确实不存在或者无法创建,则会抛出相应的异常。

    因此,创建File对象并不会立即检查文件是否存在,所以不会在创建File对象时就报错。而是在进行实际的文件操作时,才会根据文件系统的状态来决定是否出现异常。

    为啥Windows的文件层次关系用\表示,而Linux用/

    这涉及到历史和设计上的考虑。

    起初,这种区别是源于不同操作系统的发展历史。在早期的操作系统中,这种文件层次结构的表示方式并不统一。后来,Unix系统引入了正斜杠(`/`)作为目录分隔符,这在当时可以被看作是一项创新。而在DOS和Windows中,则使用了反斜杠(`\`)来表示目录分隔符。

    这种差异在很大程度上也反映了不同系统设计者的个人喜好和初衷。虽然在很多方面这两种表示方式都能够很好地满足文件系统的需要,但是由于历史原因,这种区别就一直延续至今。

    此外,正斜杠和反斜杠在计算机中都有特殊的含义,正斜杠在Unix/Linux系统中用于表示命令行参数的选项,因此在路径表示时避免了歧义;而反斜杠在Windows中被用来表示转义序列,如`\n`表示换行等。

    总的来说,这种区别在很大程度上是由操作系统设计者和历史发展决定的,尽管在一些跨平台的软件中会进行统一处理,但是在文件系统层面,这种差异基本上已经深入人心,难以改变。


    File类

    》File类位于java.io包下,本章涉及的相关流也都声明在此包下

    》File类的一个对象,对应与操作系统下的一个文件或文件目录下

    》File类声明了新建、删除、获取名称、重命名等方法,并没有涉及到文件内容的读写操作。要想实现文件内容的读写,需要使用io流

    》File类的对象,通常是作为io流操作的端点出现的

    》代码层面,将File类的对象作为参数传递到IO流相关类的构造器中。

    IO流

    IO流的分类

    》流向的不同:输入流、输出流

    》处理单位的不同:字节流、字符流

    》流的角色不同:节点流、处理流

    基础IO流的框架

    抽象基类 4个节点流(也称文件流) 4个缓冲流

    InputStream FileInputStream BufferedInputStream

    OutputStream FileOutputStream BufferOutStream

    Reader FileReader BufferReader

    Writer FileWriter BufferWriter

    FileWriter\FileReader的使用

    执行步骤

    》创建读取或写出的File类的对象

    》创建输入输出流

    》具体的读入或写出的过程

    读入:read(char[] cbuffer)

    写入:write(String str) / write(char[] cbuffer,0,len)

    》关闭流资源,避免内存泄漏

    注意点

    》因为涉及流资源的关闭操作,所以出现异常的话,需要try-catch-finally的方式来处理异常

    》对于输入流来讲,要求File类的对象对应的物理磁盘的文件必须存在。否则,会报FileNotFoundException

    对于输出流来讲,File类的对象对应的物理磁盘文件可以不存在

    》如果此文件不存在,则在输出的过程中,会自动创建此对象,并写出数据到此文件中

    》如果此文件存在,使用FileWriter(File file)或FileWriter(File file,false):

    输出数据过程中,会新建同名的文件对现有文件进行覆盖

    FileWriter(File file,true):输出数据过程中,会在现有文件的末尾追加 写出内容

    1. public class FWWrite {
    2. //注意:应该使用try-catch-finally处理异常。这里出于方便阅读代码,使用了throws的方式
    3. @Test
    4. public void test01()throws IOException {
    5. // 使用文件名称创建流对象
    6. FileWriter fw = new FileWriter(new File("fw.txt"));
    7. // 写出数据
    8. fw.write(97); // 写出第1个字符
    9. fw.write('b'); // 写出第2个字符
    10. fw.write('C'); // 写出第3个字符
    11. fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字。
    12. //关闭资源
    13. fw.close();
    14. }
    15. //注意:应该使用try-catch-finally处理异常。这里出于方便阅读代码,使用了throws的方式
    16. @Test
    17. public void test02()throws IOException {
    18. // 使用文件名称创建流对象
    19. FileWriter fw = new FileWriter(new File("fw.txt"));
    20. // 字符串转换为字节数组
    21. char[] chars = "尚硅谷".toCharArray();
    22. // 写出字符数组
    23. fw.write(chars); // 尚硅谷
    24. // 写出从索引1开始,2个字符。
    25. fw.write(chars,1,2); // 硅谷
    26. // 关闭资源
    27. fw.close();
    28. }
    29. //注意:应该使用try-catch-finally处理异常。这里出于方便阅读代码,使用了throws的方式
    30. @Test
    31. public void test03()throws IOException {
    32. // 使用文件名称创建流对象
    33. FileWriter fw = new FileWriter("fw.txt");
    34. // 字符串
    35. String msg = "尚硅谷";
    36. // 写出字符数组
    37. fw.write(msg); //尚硅谷
    38. // 写出从索引1开始,2个字符。
    39. fw.write(msg,1,2); // 硅谷
    40. // 关闭资源
    41. fw.close();
    42. }
    43. @Test
    44. public void test04(){
    45. FileWriter fw = null;
    46. try {
    47. //1. 创建File的对象
    48. File file = new File("personinfo.txt");
    49. //2. 创建FileWriter的对象,将File对象作为参数传递到FileWriter的构造器中
    50. //如果输出的文件已存在,则会对现有的文件进行覆盖
    51. fw = new FileWriter(file);
    52. // fw = new FileWriter(file,false);
    53. //如果输出的文件已存在,则会在现有的文件末尾写入数据
    54. // fw = new FileWriter(file,true);
    55. //3. 调用相关的方法,实现数据的写出操作
    56. //write(String str) / write(char[] cbuf)
    57. fw.write("I love you,");
    58. fw.write("you love him.");
    59. fw.write("so sad".toCharArray());
    60. } catch (IOException e) {
    61. e.printStackTrace();
    62. } finally {
    63. //4. 关闭资源,避免内存泄漏
    64. try {
    65. if (fw != null)
    66. fw.close();
    67. } catch (IOException e) {
    68. throw new RuntimeException(e);
    69. }
    70. }
    71. }
    72. }
    FileInputStream\FileOutStream的使用

    执行步骤

    》创建读取或写出的File类的对象

    》创建输入输出流

    》具体的读入或写出的过程

    读入:read(byte[] buffer)

    写入:write(byte[] buffer,0,len)

    》关闭流资源,避免内存泄漏

    注意点

    》对于字符流,只能用来操作文本文件,不能用来处理非文本文件

    》对于字节流,通常用来处理非文本文件。但是,如果涉及到文本的复制,也可以使用字节流

    说明:

    文本文件:.txt、.java、.c、.ccp等

    非文本文件:.doc、.xls、.jpg、mp3等

    缓冲流

    作用:文件比较大时,提升文件读写效率。

    转换流

    字符编码:字符、字符串、字符数组——》字节、字节数组(看的懂——》看不懂)

    字符解码:字节、字节数组——》字符、字符串、字符数组(看不懂——》看的懂)

    程序在读取文本文件时,不希望乱码,需要考虑

    解码时使用的字符集必须与当初编码使用的字符集相同

    作用:实现字节与字符间的转换

    API:

    InputStreamReader:将一个输入型的字节流转换为输入型的字符流

    OutputStreamWriter: 将一个输出型的字符流转换为输出型的字节流

    常见字符集

    在存储文件中的字符集

    在内存中的字符集

    一个字符(char)占用2个字节。在内存中使用的字符集称为Unicode字符集。

    数据流(已废弃)

    已废弃,已被对象流覆盖

    DataOutputStream:可以将内存中的基本数据类型的变量、String类型的变量写出到具体的文件中

    DataInputStream:将文件中保存的数据还原为内存中的基本数据类型的变量、String类型的变量

    对象流

    API

    ObjectInputStream

    ObjectOutputStream

    作用

    可以读写基本数据类型的变量,引用数据类型的变量

    对象的序列化机制

    对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而把这种二进制流持久地保存在磁盘上。

    或通过网络将这种二进制流传输到另一个网络节点。

    //当其它程序获取了这种二进制流,就可以恢复成原来地Java对象

    如下两个流的使用:

    序列化过程:使用ObjectOutputStream流实现。将内存中的Java对象保存在文件中或通过网络传输出去

    反序列化过程:使用ObjectInputstream流实现,将文件中的数据或网络还原为内存中的Java对象

    自定义类实现序列化机制

    》自定义类需要实现接口,Serializable

    》要求自定义类声明一个全局变量:static final long serizalVersionUID = 4223422L

    用来唯一的标识当前类

    》要求自定义类的各个属性也必须是可序列化的

    对于基本数据类型的属性,默认就是为可序列化的

    》对于引用数据类型的属性,要实现Serilalizable接口

    注意点:

    》如果不声明全局变量serivalVersionUID,系统会自动针对当前类分配一个UID

    但是如果修改此类中的变量,方法,构造器等,或导致UID变化,进而导致反序列化时,出现 InvalidClassException异常

    》类中的属性如果声明为transient或static,则不会实现序列化。

  • 相关阅读:
    遥感指数数据库
    正点原子嵌入式linux驱动开发——Linux按键输入
    C++11详解
    TsinghuaDatabaseGroup - AIDB
    【Linux刷题练习】
    人人都可用的Newbing部署项目
    前端开发:$nextTick()的使用及原理
    uni-app:通过三目运算动态增加样式效果(class)
    异常的分类、产生、传递和处理(JAVA基础十)
    spdk(一)----为什么要使用spdk?
  • 原文地址:https://blog.csdn.net/m0_63031112/article/details/134455376