github.com/suiyunonghen/DxCommonLib@v0.5.3/FileStream.go (about)

     1  package DxCommonLib
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  )
     7  
     8  type (
     9  	FileCodeMode uint8 //文件格式
    10  
    11  	FileOpenMode int //文件打开方式
    12  )
    13  
    14  const (
    15  	File_Code_Unknown FileCodeMode = iota
    16  	File_Code_Utf8
    17  	File_Code_Utf16BE
    18  	File_Code_Utf16LE
    19  	File_Code_GBK
    20  )
    21  
    22  const (
    23  	FMCreate        FileOpenMode = FileOpenMode(os.O_CREATE | os.O_WRONLY | os.O_TRUNC)
    24  	FMOpenRead      FileOpenMode = FileOpenMode(os.O_RDONLY)
    25  	FMOpenWrite     FileOpenMode = FileOpenMode(os.O_WRONLY) // | os.O_APPEND)
    26  	FMOpenReadWrite FileOpenMode = FileOpenMode(os.O_RDWR)   // | os.O_APPEND)
    27  
    28  )
    29  
    30  type GFileStream struct {
    31  	fCache       []byte
    32  	fcacheSize   uint
    33  	fbufferStart int //缓存在文件中开始的位置
    34  	fbufferEnd   int //缓存的结束位置
    35  	fbufferRW    int
    36  	fmodified    bool
    37  	file         *os.File
    38  }
    39  
    40  func (stream *GFileStream) Close() {
    41  	stream.FlushBuffer()
    42  	stream.file.Close()
    43  }
    44  
    45  func (stream *GFileStream) FlushBuffer() error {
    46  	if stream.fmodified {
    47  		_, err := stream.file.Write(stream.fCache[:stream.fbufferRW])
    48  		if err != nil {
    49  			return err
    50  		}
    51  		stream.fbufferStart = int(stream.FilePosition())
    52  		stream.fbufferRW = 0
    53  		bfend, _ := stream.file.Read(stream.fCache)
    54  		stream.fbufferEnd = bfend + stream.fbufferStart
    55  		stream.fmodified = false
    56  	}
    57  	return nil
    58  }
    59  
    60  func (stream *GFileStream) Seek(offset int64, whence int) (int64, error) {
    61  	fpostion := stream.FilePosition()
    62  	if fpostion == offset {
    63  		return fpostion, nil
    64  	}
    65  	ret, err := stream.file.Seek(offset, whence)
    66  	if err == nil { //重新计算位置和缓存区域
    67  		stream.fbufferStart = int(stream.FilePosition())
    68  		stream.fbufferRW = 0
    69  		bfend, _ := stream.file.Read(stream.fCache)
    70  		stream.fbufferEnd = bfend + stream.fbufferStart
    71  	}
    72  	return ret, err
    73  }
    74  
    75  func (stream *GFileStream) Read(buffer []byte) (n int, err error) {
    76  	stream.FlushBuffer()
    77  	bflen := len(buffer)
    78  	if bflen == 0 {
    79  		return 0, nil
    80  	}
    81  	if stream.fbufferStart < 0 { //未处理,重新设定位置读取
    82  		if uint(bflen) >= stream.fcacheSize {
    83  			return stream.file.Read(buffer)
    84  		} else {
    85  			stream.fbufferStart = int(stream.FilePosition())
    86  			bfend, _ := stream.file.Read(stream.fCache)
    87  			stream.fbufferEnd = bfend
    88  		}
    89  	}
    90  	hasleave := stream.fbufferEnd - stream.fbufferStart - stream.fbufferRW
    91  	if hasleave >= bflen {
    92  		rln := copy(buffer, stream.fCache[stream.fbufferRW:stream.fbufferRW+bflen])
    93  		stream.fbufferRW += rln
    94  		return rln, nil
    95  	}
    96  	copy(buffer, stream.fCache[stream.fbufferRW:])
    97  	if uint(stream.fbufferEnd-stream.fbufferStart) < stream.fcacheSize {
    98  		return int(hasleave), nil
    99  	}
   100  	bflen -= hasleave
   101  	if uint(bflen) >= stream.fcacheSize {
   102  		rln, err := stream.file.Read(buffer[hasleave:])
   103  		if err != nil {
   104  			return rln + int(hasleave), err
   105  		}
   106  		stream.fbufferStart = int(stream.FilePosition())
   107  		stream.fbufferRW = 0
   108  		bfend, err := stream.file.Read(stream.fCache)
   109  		stream.fbufferEnd = bfend + stream.fbufferStart
   110  		return rln + int(hasleave), err
   111  	} else {
   112  		stream.fbufferStart = stream.fbufferEnd
   113  		stream.fbufferRW = 0
   114  		bfend, err := stream.file.Read(stream.fCache)
   115  		if err != nil {
   116  			return bfend, err
   117  		}
   118  		stream.fbufferEnd = bfend + stream.fbufferStart
   119  		hasread := int(hasleave)
   120  		rl, err := stream.Read(buffer[hasread:])
   121  		if err != nil {
   122  			return hasread, err
   123  		}
   124  		hasread += rl
   125  		return hasread, err
   126  	}
   127  }
   128  
   129  func (stream *GFileStream) Position() int {
   130  	if stream.fbufferStart < 0 {
   131  		return int(stream.FilePosition())
   132  	} else {
   133  		return stream.fbufferStart + stream.fbufferRW
   134  	}
   135  }
   136  
   137  func (stream *GFileStream) SetPosition(ps int) error {
   138  	if ps < 0 {
   139  		return nil
   140  	}
   141  	if stream.fbufferStart < 0 {
   142  		_, err := stream.file.Seek(int64(ps), io.SeekStart)
   143  		return err
   144  	} else if ps < stream.fbufferStart || ps >= stream.fbufferEnd {
   145  		_, err := stream.file.Seek(int64(ps), io.SeekStart)
   146  		if err != nil {
   147  			return err
   148  		}
   149  		stream.fbufferStart = ps
   150  		stream.fbufferRW = 0
   151  		bfend, _ := stream.file.Read(stream.fCache)
   152  		stream.fbufferEnd = bfend + stream.fbufferStart
   153  	} else {
   154  		stream.fbufferRW = ps - stream.fbufferStart
   155  	}
   156  	return nil
   157  }
   158  
   159  func (stream *GFileStream) FilePosition() int64 {
   160  	pos, _ := stream.file.Seek(0, io.SeekCurrent)
   161  	return pos
   162  }
   163  
   164  func (stream *GFileStream) Write(data []byte) (int, error) {
   165  	datalen := len(data)
   166  	if datalen == 0 {
   167  		return 0, nil
   168  	}
   169  	if !stream.fmodified { //如果之前一直是读取的,先将文件指针移动到Position位置,然后写入到缓存中去
   170  		stream.file.Seek(int64(stream.Position()), io.SeekStart)
   171  	}
   172  	stream.fbufferStart = -1
   173  	if stream.fbufferRW == 0 { //直接一步写入
   174  		if uint(datalen) >= stream.fcacheSize {
   175  			return stream.file.Write(data)
   176  		}
   177  		wln := copy(stream.fCache[:datalen], data)
   178  		stream.fbufferRW = wln
   179  		stream.fmodified = true
   180  		return wln, nil
   181  	}
   182  	wln := 0
   183  	canCachelen := int(stream.fcacheSize) - stream.fbufferRW
   184  	if datalen <= canCachelen {
   185  		wln = copy(stream.fCache[stream.fbufferRW:stream.fbufferRW+datalen], data)
   186  		stream.fbufferRW += wln
   187  		stream.fmodified = true
   188  		data = nil
   189  	} else {
   190  		wln = copy(stream.fCache[stream.fbufferRW:], data[:canCachelen])
   191  		stream.fbufferRW += wln
   192  		stream.fmodified = true
   193  		data = data[canCachelen:]
   194  	}
   195  	if stream.fbufferRW == int(stream.fcacheSize) {
   196  		_, err := stream.file.Write(stream.fCache)
   197  		if err != nil {
   198  			return wln, err
   199  		}
   200  		stream.fbufferRW = 0
   201  	}
   202  	if data != nil {
   203  		wln2, err := stream.Write(data)
   204  		return wln + wln2, err
   205  	}
   206  	return wln, nil
   207  }
   208  
   209  //ReadFrom interface
   210  func (stream *GFileStream) ReadFrom(r io.Reader) (n int64, err error) {
   211  	var m [4096]byte
   212  	realLen := int64(0)
   213  	for {
   214  		rlen, err := r.Read(m[:])
   215  		if rlen > 0 {
   216  			stream.Write(m[:rlen])
   217  		}
   218  		realLen += int64(rlen)
   219  		if rlen < 4096 {
   220  			stream.FlushBuffer()
   221  			return realLen, nil
   222  		}
   223  		if err != nil {
   224  			stream.FlushBuffer()
   225  			return realLen, err
   226  		}
   227  	}
   228  }
   229  
   230  //WriteTo interface
   231  func (stream *GFileStream) WriteTo(w io.Writer) (n int64, err error) {
   232  	stream.SetPosition(0)
   233  	var m [4096]byte
   234  	realLen := int64(0)
   235  	for {
   236  		rlen, err := stream.Read(m[:])
   237  		if rlen > 0 {
   238  			w.Write(m[:rlen])
   239  		}
   240  		realLen += int64(rlen)
   241  		if rlen < 4096 {
   242  			return realLen, nil
   243  		}
   244  		if err != nil {
   245  			return realLen, err
   246  		}
   247  	}
   248  }
   249  
   250  //ReadAt ReaderAt interface
   251  func (stream *GFileStream) ReadAt(p []byte, off int64) (n int, err error) {
   252  	stream.SetPosition(int(off))
   253  	return stream.Read(p)
   254  }
   255  
   256  //WriteAt WriterAt  interface
   257  func (stream *GFileStream) WriteAt(p []byte, off int64) (n int, err error) {
   258  	stream.SetPosition(int(off))
   259  	return stream.Write(p)
   260  }
   261  
   262  //ReadByte ByteReader
   263  func (stream *GFileStream) ReadByte() (byte, error) {
   264  	var b [1]byte
   265  	_, err := stream.Read(b[:])
   266  	return b[0], err
   267  }
   268  
   269  func (stream *GFileStream) UnreadByte() error {
   270  	return stream.SetPosition(stream.Position() - 1)
   271  }
   272  
   273  func (stream *GFileStream) WriteByte(c byte) error {
   274  	_, err := stream.Write([]byte{c})
   275  	return err
   276  }
   277  
   278  func (stream *GFileStream) Size() int64 {
   279  	pos, _ := stream.file.Seek(0, io.SeekCurrent)
   280  	endpos, _ := stream.file.Seek(0, io.SeekEnd)
   281  	stream.file.Seek(pos, io.SeekStart)
   282  	return endpos
   283  }
   284  
   285  func NewFileStream(fileName string, openMode FileOpenMode, bufferSize int) (*GFileStream, error) {
   286  	file, err := os.OpenFile(fileName, int(openMode), 0660)
   287  	if err != nil {
   288  		return nil, err
   289  	}
   290  	stream := &GFileStream{}
   291  	stream.file = file
   292  	if bufferSize <= 0 {
   293  		bufferSize = 32768
   294  	}
   295  	stream.fcacheSize = uint(bufferSize)
   296  	stream.fCache = make([]byte, bufferSize)
   297  	stream.fbufferStart = -1 //未读取到缓存
   298  	return stream, nil
   299  }