kotlin 如何使用Okio检查一个路径是否在另一个路径内?

chhkpiq4  于 2023-04-07  发布在  Kotlin
关注(0)|答案(2)|浏览(130)

我在Kotlin/Native中使用Okio,我想检查一个路径是否在另一个路径内。
虽然有一个等于/大于/小于运算符,但看起来它只比较长度。
示例:

"/a/b/c/d".toPath().startsWith("/a/b/c".toPath()) // should return true
"/a/b/d/d".toPath().startsWith("/a/b/c".toPath()) // should return false

但是startsWith不存在。
Kotlin/JVM通过Java支持:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/starts-with.html

qni6mghb

qni6mghb1#

您可以.toString()Path s来执行此操作。
你也可以使用relativeTo并检查结果。这不是完全正确的,但下面的内容可能是一个开始:

@Test fun testingInclusion() {
    println("/a/b/c/d".toPath().contains("/a/b/c".toPath()))
    println("/a/b/d/d".toPath().contains("/a/b/c".toPath()))
  }

  private fun Path.contains(other: Path): Boolean {
    return !this.relativeTo(other).toString().contains("..")
  }
wswtfjt7

wswtfjt72#

我创建了这个扩展函数,它实现了startsWith,如问题中所述:

fun Path.startsWith(other: Path) = normalized().run {
    other.normalized().let { normalizedOther ->
        normalizedOther.segments.size <= segments.size &&
                segments
                    .slice(0 until normalizedOther.segments.size)
                    .filterIndexed { index, s -> normalizedOther.segments[index] != s }
                    .isEmpty()
    }
}

它首先检查other路径是否比this路径有更多的段(或组件),这意味着它们不匹配,因为/a/b/c永远不会以/a/b/c/d(甚至/1/2/3/4)开始。
如果other的段计数相同或更少,则继续将this切片为与other一样多的段,以便忽略任何子条目。
然后,通过使用相同的索引访问other的片段,过滤this的不匹配的切片片段。
现在我们有了一个在同一索引上不匹配的段列表。通过检查列表isEmpty(),我们现在有了this是否以other开始的结论(如果你愿意,你可以把它变成中缀)。
通过测试:

import okio.Path.Companion.toPath
import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertTrue

class PathsTests {

    @Test
    fun testStartsWith() {
        listOf(
            "/a/b/c/d" to "/a/b/c",
            "/a/b/c/d" to "/a/b/c/",
            "/A/B/C/D" to "/A/B/C",
            "/a/b/c/d" to "/a/b//c/",
            "/a/b/c/d" to "/a/b/../b/c",
            "/a/b/c/d" to "/a/../a/./b/../b///c",
            "\\a\\b\\c\\d" to "/a/../a/./b/../b///c",
            "/home/user/.config/test" to "/home/user",
            "/var/www/html/app" to "/var/www/html",
            "/home/user" to "/",
            "/" to "/",
            "////////////////////////" to "/",
            "/" to "////////////////////////",
            "/home/user" to "/home/user",
            "/home/user/./" to "/home/user",
            "/home/user" to "/home/user/./",
            "/./var" to "/var",
            "." to ".",
            "./" to ".",
            ".." to "..",
            "../.." to "../..",
            "./.." to "../.",
            "../." to "./..",
            "./../." to ".././.",
            "/." to "/.",
            "./" to ".",
            "/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z" to "/a/b/c",
            "/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a" to "/a/a/a"
        ).forEach { (pathString, otherPathString) ->
            assertTrue(
                pathString.toPath().startsWith(otherPathString.toPath()),
                "$pathString should start with $otherPathString"
            )
        }

        listOf(
            "/a/b/c" to "/a/b/c/d/",
            "/a/b/c/" to "/a/b/c/d",
            "/a/b/d/d" to "/a/b/c",
            "/a/b/d/d" to "/a/b/ce",
            "/a/b/ce" to "/a/b/c",
            "/a/b/c" to "/a/b/ce",
            "/abcd" to "/a/b/c/d",
            "/a/../b/c" to "/a/b/c",
            "/a/b/" to "/a/b//c",
            "/a/b/c/d" to "/a/b/../c",
            "/a/b/c/d" to "/a/./a/../b/./b///c",
            "/a/b/c" to "/c/b/a",
            "/a/a/a/a" to "/a/a/a/a/a",
            "\\a\\b\\d\\d" to "\\a\\b\\c",
            "\\a\\b\\d\\d" to "/a/b/c",
            "/home/user/.config/test" to "/home/user2",
            "/var/www/html/app" to "/var/local/www/html/app",
            "/home/user" to ".",
            "/" to "./",
            "/home/user" to "/home/user2",
            "/home/user/./" to "/home/user2",
            "/home/user2" to "/home/user/./",
            "../var" to "/var",
            "." to "..",
            "./" to "..",
            ".." to ".",
            "/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z" to "/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/z",
            "/a/a/a" to "/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a",
            "/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a" to "/A",
        ).forEach { (pathString, otherPathString) ->
            assertFalse(
                pathString.toPath().startsWith(otherPathString.toPath()),
                "$pathString should not start with $otherPathString"
            )
        }
    }

}

相关问题