os.OpenFile (?) adds garbage to file

Every time I open a file osOpen adds spaces and newlines to the file. These garbage does not exists in the file. How can I get rid of this?

package main

import (
	"fmt"
	"os"
)

func main() {
	file, err := os.OpenFile("log.txt", os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Println(err.Error())
	}

	file.WriteString("test")

	timestamp, _ := ioutil.ReadFile("log.txt")
	tpl.ExecuteTemplate(w, page, string(timestamp))
}

Actual output:

Desired output:

1 Like

The cause of the problem is still a mysterium. I think it is added by Go but I cannot confirm it. But a quick fix is to add a line to the CSS that removes the spaces.

white-space: pre-line;

Before:

image

After:

image

FWIW

Looking at your first attempt… You are opening the file and writing to it and then opening the file ‘again’ and reading from it.

I would try opening the file and writing to it, and then close the file.
I would then try opening the file and read from it and then close the file

1 Like

Is this better:

package main

import (
  "fmt"
  "github.com/robfig/cron"
  "os"
  "time"
)

func crontsk() {
  c := cron.New()
  c.AddFunc("@every 5s", addstamp)
  c.AddFunc("@every 60s", cleardoc)
  c.Start()
  time.Sleep(time.Duration(1<<63 - 1)) // running for more than 260 years
}

func addstamp() {
  t := time.Now()
  t.String()
  crondoc(t.Format("2006-01-02T15-04-05.000Z"))
}

func crondoc(msg string) {
  file, err := os.OpenFile("log.txt", os.O_APPEND|os.O_WRONLY, 0644)
  if err != nil {
    fmt.Println(err.Error())
  }
  
  file.WriteString(msg + "\n")
  defer file.Close()
}

func cleardoc() {
  if err := os.Truncate("log.txt", 0); err != nil {
    fmt.Println("Failed to truncate: %v", err)
  }
}

AFAIK you do not have to close a file when using ioutil?

Yes you are right. You don’t have to close the output file but you should at least make sure the output buffer is flushed before you read data from it(the file).

How do I flush os? I read this:

Why is there no flush function in os.file?

You’ll notice that an os.File doesn’t have a .Flush () because it doesn’t need one because it isn’t buffered. Writes to it are direct syscalls to write to the file.

If that’s true then why do they have a sync function for os?

Sync commits the current contents of the file to stable storage. Typically, this means flushing the file system’s in-memory copy of recently written data to disk.

Direct file access is an ■■■■■■■, what is implemented as an unbuffered stream in the language might be buffered at the kernel or filesystem driver.

Still the language can’t do anything as the interface with the kernel ist unbuffered.

How do I flush a file using “os”?

Could you elaborate this further?

Between your application and the actual disk are many layers of abstractions.

Some of them delay and buffer read and writes, some don’t.

Your best bet is to not read “dirty” files, which are already opened for writing.

How should I do instead?

func crondoc(msg string) {
  file, err := os.OpenFile("log.txt", os.O_APPEND|os.O_WRONLY, 0644)
  if err != nil {
    fmt.Println(err.Error())
  }
  
  file.WriteString(msg + "\n")
  defer file.Close()
}

You close after write, so that should be fine and “sync”.

I thought I was explicit. Use the Sync method to flush the output buffer.

func (f *File) Sync() error

Sync commits the current contents of the file to stable storage. Typically, this means flushing the file system’s in-memory copy of recently written data to disk.

From here: os package - os - pkg.go.dev

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.