This has been doing my head in and I hope someone can help. Please forgive me if it's a stupid question as I am very new to Go.
I have a struct that has base64 in it. the struct looks like this:
type UploadedFile struct {
PartnerId string
FileName string
UploadDateTime string
FileChecksum string
FileBase64 string
}
I want to take that base64 string, decode it and then save it, sounds simple right and it probably is, but I am struck.
The code looks like this:
decoder := json.NewDecoder(r.Body)
uploadedFile := models.UploadedFile{}
err := decoder.Decode(&uploadedFile)
dec, _ := base64.StdEncoding.DecodeString(uploadedFile.FileBase64)
Where do I go from here? I have tried so many things and I just keep getting errors all over the file.
I have tried adapting code that people use for images, but I always crash and burn as the file isn't an image, it could be anything
Thanks in advance.
Update: I forgot to mention that, if you use f.Write make sure to also call f.Sync after you're done writing to ensure that all the contents you've written are actually stored. The example shows the updated code.
Not sure if your code example is incomplete, so this answer might be irrelevant but to save your decoded string bytes to a file you first need to open or create a file and then write the bytes into it. Something like this:
package main
import (
"encoding/base64"
"io"
"os"
)
var b64 = `TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=`
func main() {
dec, err := base64.StdEncoding.DecodeString(b64)
if err != nil {
panic(err)
}
f, err := os.Create("myfilename")
if err != nil {
panic(err)
}
defer f.Close()
if _, err := f.Write(dec); err != nil {
panic(err)
}
if err := f.Sync(); err != nil {
panic(err)
}
}
Run it here: https://play.golang.org/p/SZVquhZdXC
Related
func FileFill(filename string) error {
f, err := os.Open("file.txt")
if err != nil {
panic("File not opened")
}
defer f.Close()
for i := 0; i < 10; i++ {
//I know this should have some error checking here
f.WriteString("some text \n")
}
return nil
}
Hi, I'm new to learning Go and I've been trying out some small use cases to learn it a bit better. I made this function to fill 10 lines of a file with "some text". When I tried this with error checking, the program panicked at the WriteString line. Am I misunderstanding something fundamental here? I looked at the documentation and I can't figure out why it doesn't like this. Thanks.
Need to use a function with write or append permission:
package main
import "os"
func main() {
f, err := os.Create("file.txt")
if err != nil {
panic(err)
}
defer f.Close()
for range [10]struct{}{} {
f.WriteString("some text\n")
}
}
https://golang.org/pkg/os#Create
// Choose the permit you want with os.OpenFile flags
file, err := os.OpenFile(path, os.O_RDWR, 0644)
// or crate new file if not exist
file, err = os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755)
// or append new data into your file with O_APPEND flag
file, err = os.OpenFile(path, os.O_APPEND, 0755)
docs: https://pkg.go.dev/os#OpenFile
I try to serialize a structured data to file. I looked through some examples and made such construction:
func (order Order) Serialize(folder string) {
b := bytes.Buffer{}
e := gob.NewEncoder(&b)
err := e.Encode(order)
if err != nil { panic(err) }
os.MkdirAll(folder, 0777)
file, err := os.Create(folder + order.Id)
if err != nil { panic(err) }
defer file.Close()
writer := bufio.NewWriter(file)
n, err := writer.Write(b.Bytes())
fmt.Println(n)
if err != nil {
panic(err)
}
}
Serialize is a method serializing its object to file called by it's id property. I looked through debugger - byte buffer contains data before writing. I mean object is fully initialized. Even n variable representing quantity of written bytes is more than a thousand - the file shouldn't be empty at all. The file is created but it is totally empty. What's wrong?
bufio.Writer (as the package name hints) uses a buffer to cache writes. If you ever use it, you must call Writer.Flush() when you're done writing to it to ensure the buffered data gets written to the underlying io.Writer.
Also note that you can directly write to an os.File, no need to create a buffered writer "around" it. (*os.File implements io.Writer).
Also note that you can create the gob.Encoder directly directed to the os.File, so even the bytes.Buffer is unnecessary.
Also os.MkdirAll() may fail, check its return value.
Also it's better to "concatenate" parts of a file path using filepath.Join() which takes care of extra / missing slashes at the end of folder names.
And last, it would be better to signal the failure of Serialize(), e.g. with an error return value, so the caller party has the chance to examine if the operation succeeded, and act accordingly.
So Order.Serialize() should look like this:
func (order Order) Serialize(folder string) error {
if err := os.MkdirAll(folder, 0777); err != nil {
return err
}
file, err := os.Create(filepath.Join(folder, order.Id))
if err != nil {
return err
}
defer file.Close()
if err := gob.NewEncoder(file).Encode(order); err != nil {
return err
}
return nil
}
I am trying to use a file instead of a DB to get a prototype up and running. I have a program that (1) reads existing content from the file to a map, (2) takes JSON POSTs that add content to the map, (3) on exit, writes to the file.
First, the file is not being created. Then I created an empty file. It is not being written to.
I am trying to read the file, determine if there is existing content. If there is not existing content, create a blank map. If there is existing content, unmarshal it into a new map.
func writeDB() {
eventDBJSON, err := json.Marshal(eventDB)
if err != nil {
panic(err)
}
err2 := ioutil.WriteFile("/Users/sarah/go/dat.txt", eventDBJSON, 0777)
if err2 != nil {
panic(err2)
}
}
func main() {
dat, err := ioutil.ReadFile("/Users/sarah/go/dat.txt")
if err != nil {
panic(err)
}
if dat == nil {
eventDB = DB{
events: map[string]event{},
}
} else {
if err2 := json.Unmarshal(dat, &eventDB); err2 != nil {
panic(err2)
}
}
router := httprouter.New()
router.POST("/join", JoinEvent)
router.POST("/create", CreateEvent)
log.Fatal(http.ListenAndServe(":8080", router))
defer writeDB()
}
There is no way for the server to ever reach defer writeDB().
http.ListenAndServe blocks, and if it did return anything, you log.Fatal that, which exits your app at that point.
You can't intercept all ways an app can exit, getting SIGKILL, machine loss of power, etc.
I'm assuming you really just want to write some code, bounce the server, repeat
If that's the case, then Ctrl-C is good enough.
If you want to write your file on Ctrl-C, look at the signal package.
Also, defer on the last line of a function really has no purpose as defer basically means "do this last".
you can use (*os.File).Stat() to get a file's FileInfo which contain its size
file, err := os.Open( filepath )
if err != nil {
// handle error
}
fi, err := file.Stat()
if err != nil {
// handle error
}
s := fi.Size()
Is there a way to write a byte array to a file? I have the file name and file extension(like temp.xml).
Sounds like you just want the ioutil.WriteFile function from the standard library.
https://golang.org/pkg/io/ioutil/#WriteFile
It would look something like this:
permissions := 0644 // or whatever you need
byteArray := []byte("to be written to a file\n")
err := ioutil.WriteFile("file.txt", byteArray, permissions)
if err != nil {
// handle error
}
According to https://golang.org/pkg/io/ioutil/#WriteFile, as of Go 1.16 this function is deprecated. Use https://pkg.go.dev/os#WriteFile instead (ioutil.WriteFile simply calls os.WriteFile as of 1.16).
Otherwise, Jeffrey Martinez's answer remains correct:
permissions := 0644 // or whatever you need
byteArray := []byte("to be written to a file\n")
err := os.WriteFile("file.txt", byteArray, permissions)
if err != nil {
// handle error
}
I'm currently learning how to develop with Go (or golang) and I have a strange issue:
I try to create a script looking inside an HTML file in order to get all the sources of each tags.
The goal of the script is to merge all the retrieved files.
So, that's for the story: for now, I'm able to get the content of each JavaScript files but... I can't concatenate them...
You can see below my script:
//Open main file
mainFilePath := "/path/to/my/file.html"
mainFileDir := path.Dir(mainFilePath)+"/"
mainFileContent, err := ioutil.ReadFile(mainFilePath)
if err == nil {
mainFileContent := string(mainFileContent)
var finalFileContent bytes.Buffer
//Start RegExp searching for JavaScript src
scriptReg, _ := regexp.Compile("<script src=\"(.*)\">")
scripts := scriptReg.FindAllStringSubmatch(mainFileContent,-1)
//For each SRC found...
for _, path := range scripts {
//We open the corresponding file
subFileContent, err := ioutil.ReadFile(mainFileDir+path[1])
if err == nil {
//And we add its content to the "final" variable
fmt.Println(finalFileContent.Write(subFileContent))
} else {
fmt.Println(err)
}
}
//Try to display the final result
// fmt.Println(finalFileContent.String())
fmt.Printf(">>> %#v", finalFileContent)
fmt.Println("Y U NO WORKS? :'(")
} else {
fmt.Println(err)
}
So, each fmt.Println(finalFileContent.Write(subFileContent)) display something like 6161 , so I assume the Write() method is correctly executed.
But fmt.Printf(">>> %#v", finalFileContent) displays nothing. Absolutely nothing (even the ">>>" are not displayed!) And it's the same for the commented line just above.
The funny part is that the string "Y U NO WORK ? :'(" is correctly displayed...
Do you know why?
And do you know how to solve this issue?
Thanks in advance!
You are ignoring some errors. What are your results when you run the following version of your code?
package main
import (
"bytes"
"fmt"
"io/ioutil"
"path"
"regexp"
)
func main() {
//Open main file
mainFilePath := "/path/to/my/file.html"
mainFileDir := path.Dir(mainFilePath) + "/"
mainFileContent, err := ioutil.ReadFile(mainFilePath)
if err == nil {
mainFileContent := string(mainFileContent)
var finalFileContent bytes.Buffer
//Start RegExp searching for JavaScript src
scriptReg, _ := regexp.Compile("<script src=\"(.*)\">")
scripts := scriptReg.FindAllStringSubmatch(mainFileContent, -1)
//For each SRC found...
for _, path := range scripts {
//We open the corresponding file
subFileContent, err := ioutil.ReadFile(mainFileDir + path[1])
if err == nil {
//And we add its content to the "final" variable
// fmt.Println(finalFileContent.Write(subFileContent))
n, err := finalFileContent.Write(subFileContent)
fmt.Println("finalFileContent Write:", n, err)
} else {
fmt.Println(err)
}
}
//Try to display the final result
// fmt.Println(finalFileContent.String())
// fmt.Printf(">>> %#v", finalFileContent)
n, err := fmt.Printf(">>> %#v", finalFileContent)
fmt.Println()
fmt.Println("finalFileContent Printf:", n, err)
fmt.Println("Y U NO WORKS? :'(")
} else {
fmt.Println(err)
}
}
UPDATE:
The statement:
fmt.Println("finalFileContent Printf:", n, err)
Outputs:
finalFileContent Printf: 0 write /dev/stdout: winapi error #8
or
finalFileContent Printf: 0 write /dev/stdout: Not enough storage is available to process this command.
From MSDN:
ERROR_NOT_ENOUGH_MEMORY
8 (0x8)
Not enough storage is available to process this command.
The formatted output to the Windows console overflows the buffer (circa 64KB).
There is a related Go open issue:
Issue 3376: windows: detect + handle console in os.File.Write