Java通道是一种用于在两个不同的线程之间传输数据的机制,它可以让一个线程将数据写入通道,而另一个线程可以从通道中读取数据。它是Java NIO库中的一部分,它允许非阻塞式I/O操作。
Java通道有两种形式:字节通道和文件通道。字节通道用于传输字节流,而文件通道用于传输文件流。
Java NIO库中的Channel接口是所有通道的基本接口,它定义了所有通道都必须实现的方法。这些方法包括open()、close()、read()、write()、position()和truncate()。
Java NIO库还包含一些其他的接口,如ReadableByteChannel和WritableByteChannel,这些接口扩展了Channel接口并提供了额外的功能。例如,ReadableByteChannel具有read()方法,该方法用于从字节流中读取数据;而WritableByteChannel具有write()方法,该方法用于将数据写入字节流中。
public interface Channel { public void open(); public void close(); public int read(ByteBuffer dst); public int write(ByteBuffer src); public long position(); public void truncate(long size); }
通道是数据源和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); } }
Java IO教程 - Java控制台控制台类的目的是使Java程序和控制台之间的交互更容易。Console类是java.io包中的一个实用程序类,用于...
Java IO教程 - Java文件输出流创建输出流要写入文件,我们需要创建一个FileOutputStream类的对象,它将表示输出流。// Create af...
Java IO教程 - Java符号链接符号链接包含对另一个文件或目录的引用。符号链接引用的文件称为符号链接的目标文件。符号链接上的操...