I/Oの相互運用性
Ktorは、基本的なI/Oプリミティブを提供するマルチプラットフォームKotlinライブラリであるkotlinx-ioをベースに構築された、ノンブロッキングで非同期なI/Oをサポートしています。これにより、HTTPリクエストとレスポンスのボディをストリーミングしたり、ファイルを読み書きしたり、データをメモリにすべてロードすることなくインクリメンタルに処理したりすることができます。
異なるI/Oモデルを使用する外部ライブラリやプラットフォームを扱う場合は、一連のアダプターを使用して以下と相互運用できます。
RawSourceやRawSinkなどのkotlinx-ioの型OutputStreamなどのJava I/O型
このページでは、KtorのI/Oプリミティブ(ByteReadChannel、ByteWriteChannel)とこれらの外部の型との間で変換を行う方法について説明します。
ByteReadChannelからRawSourceへの変換
ByteReadChannelをRawSourceに変換するには、.asSource()拡張関数を使用します。
client.prepareGet("https://httpbin.org/bytes/1024").execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.body()
val source: RawSource = channel.asSource()
val buffered = source.buffered()
val firstByte = buffered.readByte()
println("Read first byte from RawSource: $firstByte")
}ByteWriteChannelからRawSinkへの変換
中断(suspending)ByteWriteChannelをRawSinkに変換するには、.asSink()拡張関数を使用します。
get("/sink") {
call.respondBytesWriter {
val sink: RawSink = this.asSink()
sink.buffered().use { buffered ->
buffered.writeString("Hello from kotlinx-io Sink!")
}
}
}このアダプターによって生成されたRawSinkは、データのフラッシュ時に内部でrunBlockingを使用するため、フラッシュ操作が呼び出し元のスレッドをブロックする可能性があります。
RawSinkからByteWriteChannelへの変換
RawSinkを中断ByteWriteChannelとしてラップするには、.asByteWriteChannel()拡張関数を使用します。
get("/raw-sink") {
val buffer = Buffer()
val channel = buffer.asByteWriteChannel()
channel.writeByte(42)
channel.writeFully("Hello via RawSink".toByteArray())
channel.flushAndClose()
call.respondBytes(buffer.readByteArray())
}これにより、中断関数からシンクへの非同期書き込みが可能になります。返されるチャネルはバッファリングされます。すべてのデータが書き込まれたことを確実にするには、.flush()または.flushAndClose()を使用してください。
OutputStreamからByteWriteChannelへの変換
JavaのOutputStreamをByteWriteChannelに変換するには、.asByteWriteChannel()拡張関数を使用します。
get("/output-stream") {
val out = ByteArrayOutputStream()
val channel = out.asByteWriteChannel()
channel.writeFully("Hello from OutputStream-backed channel!".toByteArray())
channel.flushAndClose()
call.respondBytes(out.toByteArray())
}ByteWriteChannelでのすべての操作はバッファリングされます。基盤となるOutputStreamは、ByteWriteChannelで.flush()が呼び出されたときにのみデータを受け取ります。
