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  }