2

I am trying to make a program which writes at provided offsets in the file, like i can start writing from 20th offset etc.

here is one of sample code i was using as reference

package main

import (
    "fmt"
    "io/ioutil"
    "os"
)

const (
    filename   = "sample.txt"
    start_data = "12345"
)

func printContents() {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        panic(err)
    }
    fmt.Println("CONTENTS:", string(data))
}

func main() {
    err := ioutil.WriteFile(filename, []byte(start_data), 0644)
    if err != nil {
        panic(err)
    }

    printContents()

    f, err := os.OpenFile(filename, os.O_RDWR, 0644)
    if err != nil {
        panic(err)
    }
    defer f.Close()

    if _, err := f.Seek(20, 0); err != nil {
        panic(err)
    }

    if _, err := f.WriteAt([]byte("A"), 15); err != nil {
        panic(err)
    }

    printContents()
}

But i am always getting the same file content which is beginning from start like

12345A

I tried changing the seek values to (0,0) and (20,0) and (10,1) randomly which results in same output

Also i tried changing WriteAt offset to other offset like 10, 20 but this also resulted in same.

I want to get a solution so that i can write at any specified position in file, suggest me what is wrong in this code.

Abhishek Soni
  • 1,677
  • 4
  • 20
  • 27
  • but your file not have 20bytes – Jiang YD Jul 28 '16 at 09:18
  • Your code is doing what you want. Try an offset that IS NOT higher than the length of the file, and you'll see that the A will replace one of the character in the file. And if you use the Seek function, then you don't need WriteAt, you can use Write directly. Or if you use WriteAt, you don't need Seek. – jnmoal Jul 28 '16 at 09:37

1 Answers1

6

It works as expected.

After running your code, your "sample.txt" file content is (16 bytes):

[49 50 51 52 53 0 0 0 0 0 0 0 0 0 0 65]

try:

package main

import (
    "fmt"
    "io/ioutil"
)

const (
    filename   = "sample.txt"
    start_data = "12345"
)

func printContents() {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        panic(err)
    }
    fmt.Println(data)
}

func main() {
    printContents()
}

you need to write enough bytes first, the use WriteAt offset:
e.g. edit :

start_data = "1234567890123456789012345678901234567890"

then test your code:

package main

import (
    "fmt"
    "io/ioutil"
    "os"
)

const (
    filename   = "sample.txt"
    start_data = "1234567890123456789012345678901234567890"
)

func printContents() {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(data))
}

func main() {
    err := ioutil.WriteFile(filename, []byte(start_data), 0644)
    if err != nil {
        panic(err)
    }

    printContents()

    f, err := os.OpenFile(filename, os.O_RDWR, 0644)
    if err != nil {
        panic(err)
    }
    defer f.Close()

    if _, err := f.Seek(20, 0); err != nil {
        panic(err)
    }

    if _, err := f.WriteAt([]byte("A"), 15); err != nil {
        panic(err)
    }

    printContents()
}

output:

1234567890123456789012345678901234567890
123456789012345A789012345678901234567890
  • Yeah Thanks, I didn't noticed that but i really want to know how to add space in between rather than those **\00** because i just want to make something like this TUEFcdscsd12 NCSDJALCASJ R9czhncsdhx 00000010000 01011CCLPN03N010 these all pattern start from a specific offset there by wanted to implement something like this – Abhishek Soni Jul 28 '16 at 11:03
  • 1
    just write `start_data =" "` or use `start_data =strings.Repeat(" ", 20)` see: https://gobyexample.com/writing-files –  Jul 28 '16 at 11:06
  • Ok this means i am required to pre populate my data with empty string first – Abhishek Soni Jul 28 '16 at 11:09
  • yes if you needed text file and not binary file. or use comma separated values ( CSV) see: `encoding/csv` and see: https://golang.org/pkg/encoding/csv/ –  Jul 28 '16 at 11:13