github.com/cobalt77/jfrog-client-go@v0.14.5/utils/io/multifilereader.go (about) 1 package io 2 3 import ( 4 "io" 5 "os" 6 "sort" 7 ) 8 9 // Create new multi file ReaderAt 10 func NewMultiFileReaderAt(filePaths []string) (*multiFileReaderAt, error) { 11 readerAt := &multiFileReaderAt{} 12 for _, v := range filePaths { 13 f, err := os.Open(v) 14 if err != nil { 15 return nil, err 16 } 17 defer f.Close() 18 stat, err := f.Stat() 19 if err != nil { 20 return nil, err 21 } 22 23 readerAt.filesPaths = append(readerAt.filesPaths, v) 24 readerAt.sizeIndex = append(readerAt.sizeIndex, readerAt.size) 25 readerAt.size += stat.Size() 26 } 27 28 return readerAt, nil 29 } 30 31 type multiFileReaderAt struct { 32 filesPaths []string 33 size int64 34 sizeIndex []int64 35 } 36 37 // Get overall size of all the files. 38 func (multiFileReader *multiFileReaderAt) Size() int64 { 39 return multiFileReader.size 40 } 41 42 // ReadAt implementation for multi files 43 func (multiFileReader *multiFileReaderAt) ReadAt(p []byte, off int64) (n int, err error) { 44 // Search for the correct index to find the correct file offset 45 i := sort.Search(len(multiFileReader.sizeIndex), func(i int) bool { return multiFileReader.sizeIndex[i] > off }) - 1 46 47 readBytes := 0 48 for true { 49 var f *os.File 50 f, err = os.Open(multiFileReader.filesPaths[i]) 51 if err != nil { 52 return 53 } 54 defer f.Close() 55 relativeOff := off + int64(n) - multiFileReader.sizeIndex[i] 56 readBytes, err = f.ReadAt(p[n:], relativeOff) 57 n += readBytes 58 if len(p) == n { 59 // Finished reading enough bytes 60 return 61 } 62 if err != nil && err != io.EOF { 63 // Error 64 return 65 } 66 if i+1 == len(multiFileReader.filesPaths) { 67 // No more files to read from 68 return 69 } 70 // Read from the next file 71 i++ 72 } 73 // not suppose to get here 74 return 75 }