核心技术(卷二)01、第1章-流与文件

本文深入探讨Java中的输入输出流概念,包括InputStream、OutputStream、Reader和Writer的使用,以及如何利用这些类进行文件的读写操作。同时,介绍了字符集处理、二进制数据读写、随机访问文件及ZIP文档的创建与读取方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

流与文件

  1. 在Java API中,可以从其中读入一个字节序列对象称为输入流,可以向其中写入一个字节序列对象称为输出流抽象类InputStreamOutputStream构成了I/O类层次机构的基础。

    因为面向字节的流不便于处理以Unicode形式存储的信息(Unicode中每个字符都是由多个字节构成的),所以从抽象类ReaderWriter中继承出了一个专门处理Unicode字符的单独的类层次结构。

  2. InputStreamOutputStreamReaderWriter

    • InputStream:

      5893832-ff42135ed25bec3c.png
      InputStream的所有方法

      InputStream有一个abstract int read()抽象方法,该方法读入一个字节并返回这个字节,或者在遇到输入源结尾时返回-1。在设计具体的输入流类时,必须覆盖这个方法以提供实用的功能。InputStream还有两个非抽象的read方法,这两个方法都会调用抽象的read方法。

    • 继承结构:

      5893832-c20c76c795b985bb.png
      InputStream继承结构

      除了在java.io包中有FilterInputStream子类外,其它包中也有,FilterInputStream的所有直接子类有:
      5893832-2dd59aa4eabf12b0.png
      image

    • OutputStream:

      5893832-c3f5cdabb87fb40a.png
      OutputStream的所有方法

      InputStream类似,OutputStream定义了abstract int write()抽象方法,用于向该输出流写出一个字节。

    • 继承结构:

      5893832-e9341e9fb3dea20d.png
      `OutputStream`继承结构

      FilterOutputStream的直接子类:
      5893832-5413f8b2f7c8c6c8.png
      image

    • Reader:

      5893832-018cad9f8747cfda.png
      Reader的所有方法

    • 继承结构:

      5893832-4f036f734fcaf078.png
      image
    • Writer:

      5893832-c1c26fd0ca62c82b.png
      Writer的所有方法

    • 继承结构:


      5893832-c4726b48e48e8644.png
      image

    当完成对流的读写后,都应该调用close方法关闭流。否则系统资源的不到释放,如果使用了缓冲区,对于缓冲区最后一个包的读写也有影响。

    4个抽象类都实现了Closeable接口,该接口扩展了java.lang.AutoCloseable接口,所以4个抽象类都可以使用try-with-resource语句。

  3. 以文本方式输出

    我们可以使用PrintWriter输出文本,BufferedReader读入文本。

    try(PrintWriter printWriter = new PrintWriter("test2.txt");
        BufferedReader bufferedReader = new BufferedReader(new FileReader("test2.txt"))){
            printWriter.println("this is ");
            printWriter.println("文本输出");
            printWriter.flush();
            while (bufferedReader.ready())
            log.info(bufferedReader.readLine());
        }catch (Exception e){
            e.printStackTrace();
        }
    
  4. 字符集

    在JavaSE 1.4中引入的Charset类统一提供了对字符集的转换。

    它有一下几个主要方法:

     //返回一个指定字符集类型对象
     static Charset  forName(String charsetName);
     //返回该字符集的所有别名
     Set<String> aliases();
     //获取当前支持的所有字符集
     public static SortedMap<String,Charset> availableCharsets();
     //将字符序列编码为指定编码的字节序列
     ByteBuffer  encode(CharBuffer cb);
     //将字符串编码为指定编码的字节序列
     ByteBuffer  encode(String str);
     //将指定的字节序列解码,唯一的解码方法
     CharBuffer  decode(ByteBuffer bb)
    

    解码指定字节序列时,需要有字节缓冲区,使用ByteBufferwrap方法将一个字节数组转换为一个字节缓冲区。

     static ByteBuffer   wrap(byte[] array, int offset, int length);
     static ByteBuffer   wrap(byte[] array);
     //返回这个缓冲区所管理的字节数组
     byte[]  array();
    

    java.nio.CharBuffer

     //返回这个字符缓冲区管理的字符数组
     char[]  array();
     //返回给定索引出的码元
     char    charAt(int index);
     //返回由这个缓冲区管理的码元所构成的字符串
     String  toString();
    

    一个完整的编码解码过程:

    
     Charset charSet = Charset.forName("utf-8");
     String text = "this is a 文本";
     //编码
     ByteBuffer byteBuffer = charSet.encode(text);
     byte[] encodeResult = byteBuffer.array();
     //解码
     //解码时,需要将字节缓冲区
     byteBuffer = ByteBuffer.wrap(encodeResult);
     CharBuffer charBuffer = charset.decode(byteBuffer);
     String decodeResult = charBuffer.toString();
    
  5. 读写二进制数据

    DataOutput接口的方法来实现以二进制的形式写Java的基本类型数据。

    5893832-3dd08b30544c0d67.png
    DataOutput定义的方法

    writeInt总是将一个整数写出为4个字节长度的二进制数量值,WriteDouble总是将一个double值写出为8字节的二进制文件。这样产生的结果就是:总是对于给定类型的每一个值,所需的空间都是相同的。并且将其读回也比解析更快。
    DataOutputStream实现了DataOutput接口

    DataInput接口定义了读入二进制数据的方法:

    5893832-c76c72fa73ab16b0.png
    DataInput定义的方法

    DataInputStream实现了该接口。

  6. 随机读写文件

    RandomAccessFile类提供的方法可以帮助我们随机读写文件内容。

    这个类的构造器的第二个参数用于指定访问模式,r/rw(只读/读写)

     RandomAccessFile in = new RandomAccessFile("data.dat","r");//只读
     RandomAccessFile out = new RandomAccessFile("data.dat","rw");//可读写
    

    RandomAccessFile实现了DataInputDataOutput两个接口,所以这类可以用来读写二进制数据。另外他还有关于文件指针方法:

     //获取文件指针的位置,指针从0开始,最大为文件所包含的字节总数
     long    getFilePointer();
     //将指针置于文件指定的位置
     void    seek(long pos);
    

    因为DataOutput写出的每个类型数据长度固定,在加上随机访问的特性,使用RandomAccessFile类来帮助我们将信息存储为二进制文件是一个很好的选择。

  7. ZIP文档

    ZIP文档一压缩格式存储了一个或多个文件,每个ZIP文档都有一个,包含诸如每个文件名字和所使用的 压缩方法等信息。

    在Java中,使用ZipOutputStream来读入ZIP文档:

    
     //创建文件输出流
     FileOutputStream fileOutputStream = new FileOutputStream("zipfile.zip");
     ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
    
     //创建压缩文件项
     ZipEntry zipEntry = new ZipEntry("text.txt");
     ZipEntry zipEntry1 = new ZipEntry("text2.txt");
    
     //写入第一个文件项
     zipOutputStream.putNextEntry(zipEntry);
     //向文件项中写入内容
     String context = "压缩文件text1的内容111";
     zipOutputStream.write(Util.encode(context,"utf-8"));
     //非必须调用
     //zipOutputStream.closeEntry();
     //写入下一个文件项,必须调用这个方法,不然无法写入第二个文件项中
     zipOutputStream.putNextEntry(zipEntry1);
     context = "压缩文件text2的内容222";
     zipOutputStream.write(Util.encode(context,"utf-8"));
    
     //关闭流
     zipOutputStream.close();
     fileOutputStream.close();
    
    

    使用ZipInputStream读入Zip文档:

    //创建输入流
     FileInputStream fileInputStream = new FileInputStream(("zipfile.zip"));
     ZipInputStream zipInputStream = new ZipInputStream(fileInputStream);
     ZipEntry zipEntry;
     while((zipEntry = zipInputStream.getNextEntry())!= null){
         //检查文件项信息
        Util.getLogger().info("file name : " + zipEntry.getName());
        //读文件内容
        byte[] content = new byte[100];
        zipInputStream.read(content);
        Util.getLogger().info(Util.decode(content,"utf-8"));
        //非必须调用
        //zipInputStream.closeEntry();
    
     }
    
  8. Path接口

    An object that may be used to locate a file in a file system. It will typically represent a system dependent file path.

    Path表示的是一个目录名序列,其后还还可以跟着一个文件名。

     /**
      * 通过Pahts类的get方法来得到一个Path的实例
      * Paths.get方法可以接受多个字符串,并将它们用默认的文件系统路径分隔符链接起来。
      * 类Unix文件系统是'/',windows是'\'
      */
     Path path = Paths.get("/home","lrz");
    

    Path有许多操作文件路径的方法:API

  9. Files

    This class consists exclusively of static methods that operate on files, directories, or other types of files.

    Files类包含专门用于操作文件、目录或其他类型文件的静态方法。这些方法使普通文件操作变得简单。

    9.1 读写文件

     static byte[]   readAllBytes(Path path);
     static List<String> readAllLines(Path path);
    
     static Path write(Path path, byte[] bytes, OpenOption... options);
     static Path write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options);
     static Path write(Path path, Iterable<? extends CharSequence> lines, OpenOption... options);
    

    实现OpenOption接口的StandardOpenOption

    5893832-b2712eec758f602b.png
    StandardOpenOption枚举常量解释

    Files类提供的文件读写方法适合中等长度的文本文件,如果是大型文件,或者是二进制文件,还是应该使用流或者读入/读出器

     static InputStream  newInputStream(Path path, OpenOption... options)
     //Opens a file, returning an input stream to read from the file.
     static OutputStream newOutputStream(Path path, OpenOption... options)
     //Opens or creates a file, returning an output stream that may be used to write bytes to the file.
    
     static BufferedReader   newBufferedReader(Path path)
     //Opens a file for reading, returning a BufferedReader to read text from the file in an efficient manner.
     static BufferedReader   newBufferedReader(Path path, Charset cs)
     //Opens a file for reading, returning a BufferedReader that may be used to read text from the file in an efficient manner.
     static BufferedWriter   newBufferedWriter(Path path, Charset cs, OpenOption... options)
     //Opens or creates a file for writing, returning a BufferedWriter that may be used to write text to the file in an efficient manner.
     static BufferedWriter   newBufferedWriter(Path path, OpenOption... options)
     //Opens or creates a file for writing, returning a BufferedWriter to write text to the file in an efficient manner.
    

    9.2 复制、移动、删除文件

     static long copy(InputStream in, Path target, CopyOption... options)
     //Copies all bytes from an input stream to a file.
     static long copy(Path source, OutputStream out)
     //Copies all bytes from a file to an output stream.
     static Path copy(Path source, Path target, CopyOption... options)
     //Copy a file to a target file.
    
     static Path move(Path source, Path target, CopyOption... options)
     //Move or rename a file to a target file.
    
     static void delete(Path path)
     //Deletes a file.
     static boolean  deleteIfExists(Path path)
     //Deletes a file if it exists.
    

    实现CopyOption接口的StandardCopyOption

    5893832-064c831500c1ac7a.png
    StandardCopyOption枚举常量解释

    9.3 创建文件和目录

     static Path createDirectories(Path dir, FileAttribute<?>... attrs)
     //Creates a directory by creating all nonexistent parent directories first.
     static Path createDirectory(Path dir, FileAttribute<?>... attrs)
     //Creates a new directory.
     static Path createFile(Path path, FileAttribute<?>... attrs)
     //Creates a new and empty file, failing if the file already exists.
     static Path createLink(Path link, Path existing) //硬链接
     //Creates a new link (directory entry) for an existing file (optional operation).
     static Path createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs)//符号链接
     //Creates a symbolic link to a target (optional operation).
     static Path createTempDirectory(Path dir, String prefix, FileAttribute<?>... attrs)
     //Creates a new directory in the specified directory, using the given prefix to generate its name.
     static Path createTempDirectory(String prefix, FileAttribute<?>... attrs)
     //Creates a new directory in the default temporary-file directory, using the given prefix to generate its name.
     static Path createTempFile(Path dir, String prefix, String suffix, FileAttribute<?>... attrs)
     //Creates a new empty file in the specified directory, using the given prefix and suffix strings to generate its name.
     static Path createTempFile(String prefix, String suffix, FileAttribute<?>... attrs)
     //Creates an empty file in the default temporary-file directory, using the given prefix and suffix to generate its name.
    

    9.4 获取文件信息

     static boolean  exists(Path path, LinkOption... options)
     //Tests whether a file exists.
     static boolean  isDirectory(Path path, LinkOption... options)
     //Tests whether a file is a directory.
     static boolean  isExecutable(Path path)
     //Tests whether a file is executable.
     static boolean  isHidden(Path path)
     //Tells whether or not a file is considered hidden.
     static boolean  isReadable(Path path)
     //Tests whether a file is readable.
     static boolean  isRegularFile(Path path, LinkOption... options)
     //Tests whether a file is a regular file with opaque content.
     static boolean  isSameFile(Path path, Path path2)
     //Tests if two paths locate the same file.
     static boolean  isSymbolicLink(Path path)
     //Tests whether a file is a symbolic link.
     static boolean  isWritable(Path path)
     //Tests whether a file is writable.
     static <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options)
     //Reads a file's attributes as a bulk operation.
     static Map<String,Object>   readAttributes(Path path, String attributes, LinkOption... options)
     //Reads a set of file attributes as a bulk operation.
     static long size(Path path)
     //Returns the size of a file (in bytes).
    

    BasicFileAttributes接口:

    5893832-dfedb1010835af11.png
    BasicFileAttributes

    LinkOption
    5893832-e72248ef939349f9.png
    LinkOption枚举常量解释

    9.5 迭代目录中的文件

    如果要获取一个目录中所有文件:

     static DirectoryStream<Path>    newDirectoryStream(Path dir)
     //Opens a directory, returning a DirectoryStream to iterate over all entries in the directory.
     static DirectoryStream<Path>    newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter)
     //Opens a directory, returning a DirectoryStream to iterate over the entries in the directory.
     static DirectoryStream<Path>    newDirectoryStream(Path dir, String glob)
     //Opens a directory, returning a DirectoryStream to iterate over the entries in the directory.
    

    如果想要访问某个目录的所有子孙成员:

     tatic Path  walkFileTree(Path start, FileVisitor<? super Path> visitor)
     //Walks a file tree.
     static Path walkFileTree(Path start, Set<FileVisitOption> options, int maxDepth, FileVisitor<? super Path> visitor)
     //Walks a file tree.
    
    5893832-7699419adc300591.png
    FileVisitor接口定义的方法:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值