在Golang中创建自定义作家和读者

时间:2018-08-23 06:26:07

标签: go

我是golang的新手(争吵一周左右)。在这一点上,我将库从PHP移植到Golang,因为我觉得我应该将其转移到一种效率更高的语言上,尤其是在进行低级工作时。

在PHP中,手动序列化是通过首先打开文件句柄来完成的。

public function __construct($filename, $mode='r+b')
{
    some checking and stuff...

    $this->_fileHandle = @fopen($filename, $mode);

}

public function seek($offset, $whence=SEEK_SET)
{
    return fseek($this->_fileHandle, $offset, $whence);
}

public function readInt()
{
    $str = $this->_fread(4);

    return  ord($str[0]) << 24 |
            ord($str[1]) << 16 |
            ord($str[2]) << 8  |
            ord($str[3]);
}

public function readLong()
{ ....... }

public function writeInt($value)
{
    settype($value, 'integer');
    $this->_fwrite( chr($value>>24 & 0xFF) .
                    chr($value>>16 & 0xFF) .
                    chr($value>>8  & 0xFF) .
                    chr($value     & 0xFF),   4  );
}

public function writeLong($value)
{ ..... }

protected function _fwrite($data, $length=null)
{
    if ($length === null ) {
        fwrite($this->_fileHandle, $data);
    } else {
        fwrite($this->_fileHandle, $data, $length);
    }
}

protected function _fread($length=1)
{
    if ($length == 0) {
        return '';
    }

    if ($length < 1024) {
        return fread($this->_fileHandle, $length);
    }

    $data = '';
    while ( $length > 0 && ($nextBlock = fread($this->_fileHandle, $length)) != false ) {
        $data .= $nextBlock;
        $length -= strlen($nextBlock);
    }
    return $data;
}

几乎所有内容都围绕着fileHandle。

在Golang中,我知道os.File可以包装在自定义的读取器和写入器(io.Reader和io.Writer)中,直到我需要移动偏移量(使用php中的seek)并替换一些字节之前,这是可以的。

type FileSystem struct {
    FileHandle      *os.File
    byte        []byte
    Pos   int64
}

func NewFileSystem(filepath string, create bool) (*FileSystem, error) {

    var file *os.File
    var err error

    if create == false {
        if _, err_r := os.Stat(filepath); os.IsNotExist(err_r) {
            return nil, err_r
        }
        file, err = os.OpenFile(filepath, os.O_RDWR, 0644)
    } else {
        file, err = os.Create(filepath)
    }

        if err != nil { 
            os.Exit(0)
            return nil, err
        }

        fileinfo, err := file.Stat()
        if err != nil {
          return nil, err
        }
        filesize := fileinfo.Size()
        text := make([]byte, filesize)

        if create == false {
            file.Read(text)
        }

        return &FileSystem{
            FileHandle: file,
            byte: text,
            Pos: 0,
        }, nil

}

func (fs *FileSystem) Seek(offset int64, whence int) (int64, error) {

   var newoffset int64
   switch whence {
   case 0:
       newoffset = offset
   case 1:
       newoffset = fs.Pos + offset
   case 2:
       newoffset = int64(len(fs.byte)) - offset
   }

   if newoffset == fs.Pos {
       return newoffset, nil
   }

   fs.Pos = newoffset
   return fs.Pos, nil
}

func (fs *FileSystem) ReadByte() (b byte, err error) {
    fs.Pos++
    return fs.byte[fs.Pos-1], nil
}

func (fs *FileSystem) ReadInt() (n int32, err error) {
   fs.Pos += 4
   return (int32(fs.byte[fs.Pos-4]) << 24) | (int32(fs.byte[fs.Pos-3]) << 16) |
    (int32(fs.byte[fs.Pos-2]) << 8) | int32(fs.byte[fs.Pos-1]), nil
}

func (fs *FileSystem) ReadLong() (n int64, err error) {
   i1, _ := fs.ReadInt()
   i2, _ := fs.ReadInt()
   return (int64(i1) << 32) | int64(i2), nil
}

func (fs *FileSystem) WriteByte(b byte) error {

    w := bufio.NewWriter(fs.FileHandle)
    if (len(fs.byte) <= 0) {
        fs.byte = append(fs.byte, b)
    } else {
        fs.byte[fs.Pos] = b
    }

    err := w.WriteByte(b)
    if err != nil {
        fmt.Errorf("Error writing data: ", err)
    }

    w.Flush()
    fs.Pos++
    return nil
}

func (fs *FileSystem) WriteInt(i int32) error {

    err := fs.WriteByte(byte(i >> 24))
    if err == nil {
        err = fs.WriteByte(byte(i >> 16))
        if err == nil {
            err = fs.WriteByte(byte(i >> 8))
            if err == nil {
                err = fs.WriteByte(byte(i))
            }
        }
    }
    return err
}

func (fs *FileSystem) WriteLong(i int64) error {
    err := fs.WriteInt(int32(i >> 32))
    if err == nil {
        err = fs.WriteInt(int32(i))
    }
    return err
}

当我这样做时,实际上并没有替换字节,例如Seek(12,0)和WriteInt / WriteLong等。(因为WriteByte()总是总是在文件末尾写入..是的,上面的示例实际上在索引超出范围时发出错误,尤其是对于新文件(长度为0))。

我想知道是否有某些东西(除了WriteByte()之外)以offset作为参数来覆盖该offset的字节。

0 个答案:

没有答案