首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Supplier<Sequence<String>>不能重复一次。

Supplier<Sequence<String>>不能重复一次。
EN

Stack Overflow用户
提问于 2019-08-17 09:59:57
回答 2查看 801关注 0票数 3

我希望在Kotlin脚本中使用接收HTTP请求。

我只需要请求中的两行,所以我尝试将整个请求作为字符串行来获得,迭代它,并获得与这两行的regex匹配的行。

我用FileInputStream测试了一个文本文件,而不是从客户端发送的实际InputStream。我只能迭代一次,所以不能得到第二行。我收到以下结果。

获取/hello.html HTTP/1.1 线程"main“java.util.NoSuchElementException中的异常: Sequence不包含与谓词匹配的元素。在RequestParam$filterLines$1.invoke(RequestParam.kt:29) at RequestParam$filterLines$1.invoke(RequestParam.kt:6) at RequestParam.(RequestParam.kt:19) at RequestParamKt.main(RequestParam.kt:26)

官方的Kotlin引用说,由asSequence()实例化的序列不能重复一次以上。所以我使用了供应商界面,但这不起作用。

我以前也试过同样的方法而且成功了。我现在正在重写代码,因为以前的版本有点混乱。以前的版本是这里

下面是我正在苦苦挣扎的当前版本。

代码语言:javascript
复制
import java.io.FileInputStream
import java.io.InputStream
import java.util.function.Supplier
import kotlin.streams.asSequence

class RequestParam(private val inputStream: InputStream) {
    val path: String
    val host: String

    init {
        //I'd like to receive request from client as multiple lines of String.
        //I generated Supplier since instance made by asSequence() cannot be iterated more than once https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/index.html
        val linesSupplier: Supplier<Sequence<String>> = Supplier { inputStream.bufferedReader().lines().asSequence() }

        //I only need lines starting with "GET" or "Host:"
        val regex = { x: String -> { y: String -> y.matches(Regex(x)) } }
        val regexGet = regex("GET.*")
        val regexHost = regex("Host:.*")

        //Iterate supplier and get the first line that matches each regex
        val filterLines = { x: Sequence<String>, y: (String) -> Boolean -> x.first(y) }
        path = filterLines(linesSupplier.get(), regexGet)
        println(path) //works fine
        host = filterLines(linesSupplier.get(), regexHost)
        println(host) // no good
    }
}

fun main(args: Array<String>) {
    //Test with some file
    val inputStream = FileInputStream("C:\\path\\to\\my\\test.txt")
    val requestParam = RequestParam(inputStream)
}

以及我在测试中使用的文本文件

代码语言:javascript
复制
GET /hello.html HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.barfoo.com
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

为什么我不能迭代linesSupplier不止一次?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-08-17 11:08:56

表示延迟计算的集合的序列类型。顶层函数用于实例化序列,扩展函数用于序列。

对于没有suplier的解决方案:正如文档所述,sequence试图惰性地计算由inputStream‘line’方法返回的流中的值。因此,对于第一个调用,它将读取流,第二个调用尝试执行相同的操作,这将失败,因为您不能读取该流两次。您可以使用toList而不是asSequence来解决这个问题。列表将只读一次,并将其保存在内存中。如果你不局限于记忆,它将解决你的问题。

代码语言:javascript
复制
val linesSupplier: List<String> = inputStream.bufferedReader().lines().toList()

编辑:对于供应商的解决方案:您应该能够通过将文件流的创建移动到供应商来使其工作。在您的代码段中,供应商会失败,因为您使用的是已经使用的相同的流。

代码语言:javascript
复制
val linesSupplier: Supplier<Sequence<String>> = Supplier { FileInputStream("C:\\test.txt").bufferedReader().lines().asSequence() }
票数 2
EN

Stack Overflow用户

发布于 2019-08-17 10:43:26

因为在第一次调用linesSupplier.get()时,您消耗了inputStream,而在第二次调用时,它会引发异常。与其使用供应商,不如定义一个正常的Sequence并使用它:

代码语言:javascript
复制
val lines: Sequence<String> =  inputStream.bufferedReader().lines().asSequence()

//...

path = filterLines(lines, regexGet)

//...

host = filterLines(lines, regexHost)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57535225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档