我是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的字节。