简体   繁体   English

在Linux上的Scala中锁定和写入文件的最佳方法

[英]The optimal way to lock and write to a file in Scala on Linux

I'm having a hard time finding the correct way to do any advanced file-system operations on Linux using Scala. 我很难找到使用Scala在Linux上进行任何高级文件系统操作的正确方法。

The one which I really can't figure out if best described by the following pseudo-code: 如果用下面的伪代码最好地描述,那我真的不知道:

with fd = open(path, append | create):
    with flock(fd, exclusive_lock):
        fd.write(string)

Basically open a file in append mode (create it if it's non existent), get an exclusive lock to it and write to it (with the implicit unlock and close afterwards). 基本上以追加模式打开文件(如果不存在则创建文件),对其进行排他锁并写入(使用隐式解锁,然后关闭)。

Is there an easy, clean and efficient way of doing this if I know my program will be ran on linux only ? 如果我知道我的程序只能在linux上运行,是否有一种简单,干净且有效的方法来执行此操作? (preferably without glancing offer the exceptions that should be handled). (最好不带眼地提供应处理的异常)。

Edit: 编辑:

The answer I got is, as far as I've seen and tested is correct. 据我所见和测试,我得到的答案是正确的。 However it's quite verbose, so I'm marking it as ok but I'm leaving this snippet of code here, which is the one I ended up using (Not sure if it's correct, but as far as I see it does everything that I need): 但是它很冗长,因此我将其标记为可以,但是我在这里留下了这段代码,这是我最终使用的代码段(不确定是否正确,但是据我所知需要):

  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() }

You can use FileChannel.lock and FileLock to get what you wanted: 您可以使用FileChannel.lockFileLock获得所需的内容:

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
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM