第一百七十五节 Java IO教程 - Java通道

Java IO教程 - Java通道

通道是数据源和Java程序之间的开放连接,用于执行I/O操作。

Channel接口在java.nio.channels包中。

通道接口只声明了两个方法:close()和isOpen()。

各种通道

ReadableByteChannel用于使用read()方法将数据从数据源读取到字节缓冲区中。 WritableByteChannel用于使用write()方法将数据从字节缓冲区写入数据宿。

ByteChannel能够分别使用read()和write()方法读取和写入字节数据。

ScatteringByteChannel将数据从数据源读取到多个字节缓冲区中。从已知的文件格式或类似的数据源读取数据是有用的,其中在一些固定长度的报头中提供数据,随后是可变长度的主体。

GatheringByteChannel从多个字节缓冲区中写出数据。

创建通道

要获得一个通道,使用旧的方式使用java.io包中的类使用I/O创建InputStream和OutputStream的对象。

java.nio.channels包中的Channels类是一个实用程序类,它有许多静态方法将流转换为通道,反之亦然。

Channels类还提供了将读写器转换为通道的方法,反之亦然。

例如,如果我们有一个名为myInputStream的输入流对象,我们可以获得一个ReadableByteChannel如下:

复制代码
ReadableByteChannel rbc  = Channels.newChannel(myInputStream);

如果我们有一个名为rbc的ReadableByteChannel,我们可以获得如下的基本InputStream对象:

复制代码
InputStream myInputStream  = Channels.newInputStream(rbc);

FileInputStream和FileOutputStream类有一个称为getChannel()的新方法来返回一个FileChannel对象。

FileChannel用于读取和写入数据到文件。

从FileInputStream获取的FileChannel对象以只读模式打开。

复制代码
FileInputStream fis  = new FileInputStream("test1.txt"); 
FileChannel fcReadOnly  = fis.getChannel(); // A  read-only  channel

从FileOutputStream对象获取的FileChannel对象以只写模式打开。

复制代码
FileOutputStream fos   = new FileOutputStream("test1.txt"); 
FileChannel  fcWriteOnly = fos.getChannel(); // A  write-only  channel

以下代码为不同种类的文件流获取FileChannel对象:

复制代码
// read-only mode
RandomAccessFile  raf1 = new RandomAccessFile("test1.txt", "r"); 
FileChannel  rafReadOnly = raf1.getChannel(); // A  read-only  channel

// read-write mode
RandomAccessFile  raf2 = new RandomAccessFile("test1.txt", "rw"); 
FileChannel rafReadWrite = raf2.getChannel(); // A  read-write channel

读/写文件

FileChannel对象维护位置变量作为缓冲区。

FileChannel的read()和write()方法有两种类型:相对位置读/写和绝对位置读/写。

当我们打开一个FileChannel时,它的位置设置为0,这是文件的开始。

当我们使用相对read()方法从FileChannel读取时,它的位置增加读取的字节数。

从FileChannel读取的绝对位置不会影响其位置。

我们可以使用position()方法获取FileChannel对象的当前位置值。

我们可以使用位置(int newPosition)方法将其位置设置为新位置。

通道也是可自动关闭的。如果我们使用try-with-resources语句来获取一个通道,那么通道将被自动关闭,这样就避免了我们明确地调用通道的close()方法。

以下代码从名为test1.txt的文件中读取文本。

复制代码
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Main {
  public static void main(String[] args) {
    File inputFile = new File("test1.txt");
    if (!inputFile.exists()) {
      System.out.println("The input file " + inputFile.getAbsolutePath()
          + "  does  not  exist.");
      System.out.println("Aborted the   file reading process.");
      return;
    }
    try (FileChannel fileChannel = new FileInputStream(inputFile).getChannel()) {
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while (fileChannel.read(buffer) > 0) {
        buffer.flip();
        while (buffer.hasRemaining()) {
          byte b = buffer.get();
          System.out.print((char) b);
        }
        buffer.clear();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

上面的代码生成以下结果。

例子

以下代码显示如何使用缓冲区和通道写入文件。

复制代码
import java.io.File;
import java.nio.channels.FileChannel;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.io.FileOutputStream;

public class Main {
  public static void main(String[] args) {
    File outputFile = new File("test.txt");

    try (FileChannel fileChannel = new FileOutputStream(outputFile)
        .getChannel()) {
      String text = getText();
      byte[] byteData = text.toString().getBytes("UTF-8");
      ByteBuffer buffer = ByteBuffer.wrap(byteData);
      fileChannel.write(buffer);
    } catch (IOException e1) {
      e1.printStackTrace();
    }
  }

  public static String getText() {
    String lineSeparator = System.getProperty("line.separator");
    StringBuilder sb = new StringBuilder();
    sb.append("test");
    sb.append(lineSeparator);
    sb.append("test");
    sb.append(lineSeparator);

    sb.append("test");
    sb.append(lineSeparator);
    sb.append("test");

    return sb.toString();
  }
}

复制文件的内容

我们可以使用缓冲区和通道来复制文件。

获取源文件和目标文件的FileChannel对象,并对源FileChannel对象调用transferTo()方法或调用目标FileChannel对象上的transferFrom()方法。

以下代码显示如何复制文件。

复制代码
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;

public class Main {
  public static void main(String[] args) throws Exception {

    FileChannel sourceChannel = new FileInputStream("sourceFile").getChannel();
    FileChannel sinkChannel = new FileOutputStream("newFile").getChannel();

    // Copy source file contents to the sink file
    sourceChannel.transferTo(0, sourceChannel.size(), sinkChannel);
  }
}
相关推荐
Daniel 大东1 小时前
BugJson因为json格式问题OOM怎么办
java·安全
Ajiang28247353042 小时前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
幽兰的天空2 小时前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
Theodore_10225 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸6 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象6 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了7 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
----云烟----7 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024067 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
小二·7 小时前
java基础面试题笔记(基础篇)
java·笔记·python