Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
/zioPublic

ZStream splitting on size#7063

Unanswered
Dennis4b asked this question inQ&A
Discussion options

Hi,

I can't really seem to find how to do the following (in ZIO 2.0), which feels like it should be easy (.. famous last words):

Given for example

val input = ZStream.fromFile(Paths.get("/tmp/largefile.zip").toFile)

with say a size of 68 megabytes, I would like to produce a series ofZStreams of a capped size, say 8 megabytes, which cut the original stream into 8 megabyte pieces, with the last piece being whatever is left over. The initial size is not necessarily known (or relevant), so the result could of course also just be a single sub-stream.

Traversing those (8mb) sub-streams would be done sequentially so that the original stream is also just traversed once from front to back (it could also come from the network and avoiding buffering would be good).

If I use.take(..) it doesn't advance the stream, i.e. if Itake(8mb) twice I get the same initial 8mb of the file instead of consecutive pieces.

Any hints as to which functions would be useful for this, which methods to look at for inspiration, or which approach I could try to take, would be highly appreciated.

[Why? Splitting large files when storing them in SeaweedFS]

You must be logged in to vote

Replies: 2 comments

Comment options

I have something working by usingtoPull on the original stream in order to inject my own splitting logic and returningfromPull basedZStreams, while calculating sizes and re-chunking inbetween:

traitStreamSplitter {defgetNext:ZIO[Any,Throwable,Option[ZStream[Any,Throwable,Byte]]]}objectStreamSplitter {defmake(input:ZStream[Any,Throwable,Byte],splitSize:Int)=for {        pull<- input.toPull        leftover<-Ref.make(Option.empty[Chunk[Byte]])        finished<-Ref.make(false)    }yield {defpuller(readRef:Ref[Int])= {for {                read<- readRef.get                result<- (read== splitSize)match {casetrue=>ZIO.fail(Option.empty[Throwable])case _=>for {                        lf<- leftover.get                        n<- (lfmatch {caseSome(s)=>for {                                _<- leftover.update(_=>None)                            }yield scase _=> pull                        }).either                        res<- nmatch {caseLeft(e)=>for {                                _<- finished.update(_=>true)                                result<-ZIO.fail(e)                            }yield resultcaseRight(r)=> {if (read+ r.size> splitSize) {valmissing= (splitSize- read).toIntvaltoReturn= r.take(missing)valtoRemain= r.drop(missing)for {                                        _<- leftover.update(_=>Some(toRemain))                                        _<- readRef.update(_=> splitSize)                                    }yield toReturn                                }else {for {                                        _<- readRef.update(_=> read+ r.size)                                    }yield r                                }                            }                        }                    }yield res                }            }yield result        }newStreamSplitter {defgetNext= finished.get.map{casetrue=>Nonecasefalse=>Some(ZStream.fromPull(for {                    read<-Ref.make[Int](0)                }yield puller(read)))            }        }    }}

Any style tips or improvement suggestions of course welcome, for example:

  • are theRefs necessary? Could normalvars be used?
  • Is.either an appropriate way to handle thepull result (fail for end-of-stream) or is there some more elegant way with for examplefold
  • So manyfor-comprehensions..
  • Are there convenient/appropriateZIO /ZStream combinators that could be used to simplify this code
  • Etc
You must be logged in to vote
0 replies
Comment options

I think you just want to useZStream.transduce with aZSink that consumes the desired size.

You must be logged in to vote
0 replies
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Category
Q&A
Labels
None yet
2 participants
@Dennis4b@adamgfraser

[8]ページ先頭

©2009-2025 Movatter.jp