swave comes with built-in support for stream-based file IO.
You enable built-in support for stream-based file IO with this single import:
This gives you the following three additional methods on the
Spout companion object, which create Spout instances for reading arbitrarily large files from the file system in a stream-based fashion (signatures slightly simplified):
Spout.fromFileName[T: Bytes](fileName: String): Spout[T] Spout.fromFile[T: Bytes](file: File): Spout[T] Spout.fromPath[T: Bytes](path: Path): Spout[T]
The import also gives you the following three additional methods on the
Drain companion object, which create Drain instances for writing arbitrarily large files to the file system in a stream-based fashion (signatures slightly simplified):
Drain.toFileName[T: Bytes](fileName: String): Drain[T, Future[Long]] Drain.toFile[T: Bytes](file: File): Drain[T, Future[Long]] Drain.toPath[T: Bytes](path: Path): Drain[T, Future[Long]]
Apart from one thing these signatures are probably quite self-explanatory. Still, you might want to take a look at the ScalaDoc of the
SpoutFromFiles trait and the ScalaDoc of the
DrainToFiles trait for more details. Probably also interesting are the sources of the
SpoutFromFiles trait and the sources of the
The one thing that deserves more explanation here is the type parameter with the
Bytes context bound.
As you can see all of the methods shown above take a type parameter
T, which (if not explicitly specified) will be inferred from the (single) context bound instance of the type class
Bytes[T] that is in scope at the call site.
The purpose of this type parameter is to allow swave to abstract over the concrete data type that represents a chunk of raw bytes, which all lower-level IO operations typically work with. swave’s approach here is not to duplicate the excellent work that other projects have invested in this area, but leave the decision of which type to use to the user.
Currently swave pre-defines three
Bytes[T] implementations, for these types:
akka.util.ByteString(as part of the swave-akka-compat module)
scodec.bits.ByteVector(as part of the swave-scodec-compat module)
Array[Byte](as part of the
swave intentionally doesn’t pick any of these as a “preferred default”, so you’ll have to make a conscious choice as to what you’d like to use. If you have no clear preference we’d recommend you rely on scodec.bits.ByteVector as it appears to be the most flexible implementation with the broadest API offering.
If you rely on the
byteArrayBytes implementation (which has the advantage of not requiring any module dependency in addition to
swave-core) be aware that swave treats instances of
Array[Byte] as immutable, even though they this is not and cannot be enforced. So, if you violate this convension in your own code by mutating byte array instances in place you should be sure to know what you are doing.