golang中的File.WriteString函数是用于覆盖写入文件的。

huangapple go评论86阅读模式
英文:

golang File WriteString cover

问题

我想通过文件获取递增的ID,以下是代码:

// 获取递增的ID
func GetID() uint64 {
    appIdLock.Lock()
    defer appIdLock.Unlock()

    f, err := os.OpenFile(idPath, os.O_RDWR, 0666)
    if err != nil {
        return 0
    }
    defer f.Close()

    // 读取
    bufferTemp := make([]byte, 16)
    bufferResult := make([]byte, 0)
    for {
        n, _ := f.Read(bufferTemp)
        if n > 0 {
            bufferResult = append(bufferResult, bufferTemp[:n]...)
        } else {
            break
        }
    }

    if len(bufferResult) == 0 {
        return 0
    }

    s := common.StringToUint64(string(bufferResult))
    s += 1

    // 写入(如何覆盖?)
    f.Truncate(0)
    f.Seek(0, 0)
    f.WriteString(strconv.FormatUint(s, 10))

    return s
}

f.WriteString 函数是追加写入的,例如,我的文件内容是 123,运行 GetID() 后,我希望文件内容变为 124,但实际结果是 123124。为了覆盖写入,你可以使用 f.Truncate(0) 将文件截断为0字节,然后使用 f.Seek(0, 0) 将文件指针移动到文件开头,再进行写入操作。

英文:

I want get increment id with file, code as below:

// get increment id
func GetID() uint64 {

	appIdLock.Lock()
    defer appIdLock.Unlock()

	f, err := os.OpenFile(idPath, os.O_RDWR, 0666)
    if err != nil {
	    return 0
    }
	defer f.Close()

    // Read
    bufferTemp := make([]byte, 16)
    bufferResult := make([]byte, 0)
    for {
	    n, _ := f.Read(bufferTemp)
	    if n > 0 {
		    bufferResult = append(bufferResult, bufferTemp[:n]...)
	    } else {
		    break
	    }
    }

    if len(bufferResult) == 0 {
	    return 0
    }

    s := common.StringToUint64(string(bufferResult))
    s += 1

    // Write (how to cover?)
    f.WriteString(strconv.FormatUint(s, 10))

    return s
}

f.WriteString function was append, example, my file content: 123, run GetID() I hope my file content is: 124, But result was: 123124

答案1

得分: 1

不改变你的代码太多,这是一个可以工作并实现你想要的功能的解决方案。没有循环或多个字节切片。

func GetID() uint64 {

    appIdLock.Lock()
    defer appIdLock.Unlock()

    // 添加 os.O_CREATE 以在文件不存在时创建文件。
    f, err := os.OpenFile(idPath, os.O_RDWR+os.O_CREATE, 0666)
    if err != nil {
        fmt.Println(err)
        return 0
    }
    defer f.Close()

    // 预先知道文件内容,因此我分配了一个合适的字节切片。
    fileStat, err := f.Stat()
    if err != nil {
        fmt.Println(err)
        return 0
    }

    buffer := make([]byte, fileStat.Size())

    _, err = f.Read(buffer)
    if err != nil {
        fmt.Println(err)
        return 0
    }

    s, _ := strconv.ParseUint(string(buffer), 10, 64)
    s += 1

    // 这里的魔法在于~将字节写入文件的索引0处。
    _, err = f.WriteAt([]byte(strconv.FormatUint(s, 10)), 0)
    if err != nil {
        fmt.Println(err)
        return 0
    }

    return s
}

希望能对你有所帮助!

英文:

Without changing much of your code, here is the solution that will work and do what you want to do. No loops or more than a single byte slice.

func GetID() uint64 {

	appIdLock.Lock()
	defer appIdLock.Unlock()

	// Added  + os.O_CREATE to create the file if it doesn't exist.
	f, err := os.OpenFile(idPath, os.O_RDWR + os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		return 0
	}
	defer f.Close()

	// Know file content beforehand so I allocate a suitable bytes slice.
	fileStat, err := f.Stat()
	if err != nil {
		fmt.Println(err)
		return 0
	}


	buffer := make([]byte, fileStat.Size())

	_, err = f.Read(buffer)
	if err != nil {
		fmt.Println(err)
		return 0
	}

	s, _ := strconv.ParseUint(string(buffer), 10, 64)
	s += 1

	// The Magic is here ~ Writes bytes at 0 index of the file.
	_, err = f.WriteAt([]byte(strconv.FormatUint(s, 10)), 0)
	if err != nil {
		fmt.Println(err)
		return 0
	}

	return s
}

<br />
Hope it helps!

huangapple
  • 本文由 发表于 2017年8月22日 11:43:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/45808576.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定