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



我在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

你可以用.toString()Path来做这个操作。

您也可以使用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("..")
}

我已经创建了这个扩展函数,它实现了问题中所描述的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"
)
}
}
}

相关内容

最新更新