Linux 在 Scala 中锁定和写入文件的最佳方式
The optimal way to lock and write to a file in Scala on Linux
我很难找到使用 Scala 在 Linux 上执行任何高级文件系统操作的正确方法。
我真的想不通下面的伪代码是否能最好地描述这个:
with fd = open(path, append | create):
with flock(fd, exclusive_lock):
fd.write(string)
基本上以追加模式打开一个文件(如果它不存在则创建它),获得一个独占锁并写入它(使用隐式解锁然后关闭)。
如果我知道我的程序将 运行 仅在 linux 上运行,是否有一种简单、干净且高效的方法来执行此操作? (最好不看一眼就提供应该处理的异常)。
编辑:
据我所见和测试,我得到的答案是正确的。然而,它非常冗长,所以我将其标记为 ok,但我将这段代码留在这里,这是我最终使用的代码(不确定它是否正确,但据我所知,它完成了我所做的一切需要):
val fc = FileChannel.open(Paths.get(file_path), StandardOpenOption.CREATE, StandardOpenOption.APPEND)
try {
fc.lock()
fc.write(ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8)))
} finally { fc.close() }
您可以使用 FileChannel.lock and FileLock 来获得您想要的:
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
import java.nio.charset.StandardCharsets
import java.nio.file.{Path, Paths, StandardOpenOption}
import scala.util.{Failure, Success, Try}
object ExclusiveFsWrite {
def main(args: Array[String]): Unit = {
val path = Paths.get("/tmp/file")
val buffer = ByteBuffer.wrap("Some text data here".getBytes(StandardCharsets.UTF_8))
val fc = getExclusiveFileChannel(path)
try {
fc.write(buffer)
}
finally {
// channel close will also release a lock
fc.close()
}
()
}
private def getExclusiveFileChannel(path: Path): FileChannel = {
// Append if exist or create new file (if does not exist)
val fc = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.APPEND,
StandardOpenOption.CREATE)
if (fc.size > 0) {
// set position to the end
fc.position(fc.size - 1)
}
// get an exclusive lock
Try(fc.lock()) match {
case Success(lock) =>
println("Is shared lock: " + lock.isShared)
fc
case Failure(ex) =>
Try(fc.close())
throw ex
}
}
}
我很难找到使用 Scala 在 Linux 上执行任何高级文件系统操作的正确方法。
我真的想不通下面的伪代码是否能最好地描述这个:
with fd = open(path, append | create):
with flock(fd, exclusive_lock):
fd.write(string)
基本上以追加模式打开一个文件(如果它不存在则创建它),获得一个独占锁并写入它(使用隐式解锁然后关闭)。
如果我知道我的程序将 运行 仅在 linux 上运行,是否有一种简单、干净且高效的方法来执行此操作? (最好不看一眼就提供应该处理的异常)。
编辑:
据我所见和测试,我得到的答案是正确的。然而,它非常冗长,所以我将其标记为 ok,但我将这段代码留在这里,这是我最终使用的代码(不确定它是否正确,但据我所知,它完成了我所做的一切需要):
val fc = FileChannel.open(Paths.get(file_path), StandardOpenOption.CREATE, StandardOpenOption.APPEND)
try {
fc.lock()
fc.write(ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8)))
} finally { fc.close() }
您可以使用 FileChannel.lock and FileLock 来获得您想要的:
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
import java.nio.charset.StandardCharsets
import java.nio.file.{Path, Paths, StandardOpenOption}
import scala.util.{Failure, Success, Try}
object ExclusiveFsWrite {
def main(args: Array[String]): Unit = {
val path = Paths.get("/tmp/file")
val buffer = ByteBuffer.wrap("Some text data here".getBytes(StandardCharsets.UTF_8))
val fc = getExclusiveFileChannel(path)
try {
fc.write(buffer)
}
finally {
// channel close will also release a lock
fc.close()
}
()
}
private def getExclusiveFileChannel(path: Path): FileChannel = {
// Append if exist or create new file (if does not exist)
val fc = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.APPEND,
StandardOpenOption.CREATE)
if (fc.size > 0) {
// set position to the end
fc.position(fc.size - 1)
}
// get an exclusive lock
Try(fc.lock()) match {
case Success(lock) =>
println("Is shared lock: " + lock.isShared)
fc
case Failure(ex) =>
Try(fc.close())
throw ex
}
}
}