How to append docx file in Golang - go

I want to copy all the contents of a docx file (including its formatting like bold, underline, bullets, paragraphs, etc.) and append it to another docx file.
In this case I want to copy contents from Source/D1.docx and append it to temp.docx
package main
import (
"io/ioutil"
"log"
"os"
)
func main() {
data, err := ioutil.ReadFile("./Source/D1.docx")
if err != nil {
log.Println(err)
}
file, err := os.OpenFile("temp.docx", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Println(err)
}
file.Write(data)
}

Do this:
git clone --depth 1 git://github.com/unidoc/unioffice
New-Item -ItemType Directory unioffice/document/merge
Set-Location unioffice/document/merge
git pull origin pull/448/head
Then in the merge folder, make this file:
package main
import (
"github.com/unidoc/unioffice/document"
"os"
"path/filepath"
)
func main() {
s := "TestDocument.docx"
doc0, e := document.Open(s)
if e != nil {
panic(e)
}
defer doc0.Close()
doc1, e := document.Open(s)
if e != nil {
panic(e)
}
defer doc1.Close()
doc0.AddParagraph().AddRun().AddPageBreak()
if e := doc0.Append(doc1); e != nil {
panic(e)
}
out := filepath.Join(os.TempDir(), "merged.docx")
doc0.SaveToFile(out)
}
Note this is just for testing, for real code you will want to get a license.
https://github.com/unidoc/unioffice

Related

How to create slice with filenames

There is a program which creates file per second. I want to append file names into slice and print them. Now my program executes incorrect, it appends names but only for one file name. So I expect to get []string{"1","2","3"}, instead I get []string{"1","1","1"}, []string{"2","2","2"}, []string{"3","3","3"}. How to correct my prog to get expected result?
package main
import (
"encoding/csv"
"fmt"
"os"
"strconv"
"time"
)
func main() {
for {
time.Sleep(1 * time.Second)
createFile()
}
}
func createFile() {
rowFile := time.Now().Second()
fileName := strconv.Itoa(rowFile)
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println(err)
}
defer file.Close()
writer := csv.NewWriter(file)
writer.Comma = '|'
err = writer.Write([]string{""})
if err != nil {
fmt.Println(err)
}
countFiles(fileName)
}
func countFiles(fileName string) {
arrFiles := make([]string, 0, 3)
for i := 0; i < 3; i++ {
arrFiles = append(arrFiles, fileName)
}
fmt.Println(arrFiles)// here I expect ["1","2","3"] then ["4","5","6"] and so on. But now there is ["1","1","1"] then ["2","2","2"] and so on
}
createFile() does not persist created file names in any way. You can do something like that:
package main
import (
"encoding/csv"
"fmt"
"os"
"strconv"
"time"
)
func main() {
files := []string{}
for {
time.Sleep(1 * time.Second)
files = append(files, createFile())
fmt.Println(files)
}
}
func createFile() string {
rowFile := time.Now().Second()
fileName := strconv.Itoa(rowFile)
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println(err)
}
defer file.Close()
writer := csv.NewWriter(file)
writer.Comma = '|'
err = writer.Write([]string{""})
if err != nil {
fmt.Println(err)
}
return fileName
}

Golang - Zip a directory which includes empty subdirectory and files

I am trying to zip an existing directory that has some empty subdirectories as well.
Here is the folder structure.
parent/
├── child
│   └── child.txt
├── empty-folder
└── parent.txt
2 directories, 2 files
Here is the source code. It writes all the subdirectories which have files on that. But it skipped an empty subdirectory. Is there any way to add an empty subdirectory as well in the zip file?. Thanks in advance.
package main
import (
"archive/zip"
"fmt"
"io"
"os"
"path/filepath"
)
// check for error and stop the execution
func checkForError(err error) {
if err != nil {
fmt.Println("Error - ", err)
os.Exit(1)
}
}
const (
ZIP_FILE_NAME = "example.zip"
MAIN_FOLDER_NAME = "parent"
)
// Main function
func main() {
var targetFilePaths []string
// get filepaths in all folders
err := filepath.Walk(MAIN_FOLDER_NAME, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
// add all the file paths to slice
targetFilePaths = append(targetFilePaths, path)
return nil
})
checkForError(err)
// zip file logic starts here
ZipFile, err := os.Create(ZIP_FILE_NAME)
checkForError(err)
defer ZipFile.Close()
zipWriter := zip.NewWriter(ZipFile)
defer zipWriter.Close()
for _, targetFilePath := range targetFilePaths {
file, err := os.Open(targetFilePath)
checkForError(err)
defer file.Close()
// create path in zip
w, err := zipWriter.Create(targetFilePath)
checkForError(err)
// write file to zip
_, err = io.Copy(w, file)
checkForError(err)
}
}
To write an empty directory you just need to call Create with the directory path with a trailing path separator.
package main
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
)
const (
ZIP_FILE_NAME = "example.zip"
MAIN_FOLDER_NAME = "parent"
)
type fileMeta struct {
Path string
IsDir bool
}
func main() {
var files []fileMeta
err := filepath.Walk(MAIN_FOLDER_NAME, func(path string, info os.FileInfo, err error) error {
files = append(files, fileMeta{Path: path, IsDir: info.IsDir()})
return nil
})
if err != nil {
log.Fatalln(err)
}
z, err := os.Create(ZIP_FILE_NAME)
if err != nil {
log.Fatalln(err)
}
defer z.Close()
zw := zip.NewWriter(z)
defer zw.Close()
for _, f := range files {
path := f.Path
if f.IsDir {
path = fmt.Sprintf("%s%c", path, os.PathSeparator)
}
w, err := zw.Create(path)
if err != nil {
log.Fatalln(err)
}
if !f.IsDir {
file, err := os.Open(f.Path)
if err != nil {
log.Fatalln(err)
}
defer file.Close()
if _, err = io.Copy(w, file); err != nil {
log.Fatalln(err)
}
}
}
}

How to sort file names with Go Programming Language?

In my Go project, I need to sort the .json files and to display their name on the terminal when I'm running this command on the terminal go run main.go.
I coded a program which displays all the files in the folder, but I need to sort the .json file.
My code is the following :
package main
import (
"fmt"
"log"
"os"
"bytes"
"io"
)
func main() {
if os.Args[1] == "display-json-name" {
//reads the directory name and returns a list of directory entries
dirname := "."
f, err := os.Open(dirname)
if err != nil {
log.Fatal(err)
}
files, err := f.Readdir(-1)
f.Close()
if err != nil {
log.Fatal(err)
}
for _, file := range files {
fmt.Println(file.Name())
}
}
How can we sort just the different .json files?
And the hierarchy of my project is :
Based on comments, it appears that the question is "How to print files where the file has a .json extension". Here's the code:
if os.Args[1] == "display-json-name" {
//reads the directory name and returns a list of directory entries
dirname := "."
f, err := os.Open(dirname)
if err != nil {
log.Fatal(err)
}
files, err := f.Readdir(-1)
f.Close()
if err != nil {
log.Fatal(err)
}
for _, file := range files {
if filepath.Ext(file.Name()) == ".json" {
fmt.Println(file.Name())
}
}
}
https://golang.org/pkg/io/ioutil/#ReadDir
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
files, err := ioutil.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, file := range files {
fmt.Println(file.Name())
}
}

How to create new file using go script

I am new to go lang. I am able to create a new file from the terminal using go script. like this
go run ../myscript.go > ../filename.txt
but I want to create the file from the script.
package main
import "fmt"
func main() {
fmt.Println("Hello") > filename.txt
}
If you are trying to print some text to a file one way to do it is like below, however if the file already exists its contents will be lost:
package main
import (
"fmt"
"os"
)
func main() {
err := os.WriteFile("filename.txt", []byte("Hello"), 0755)
if err != nil {
fmt.Printf("Unable to write file: %v", err)
}
}
The following way will allow you to append to an existing file if it already exists, or creates a new file if it doesn't exist:
package main
import (
"os"
"log"
)
func main() {
// If the file doesn't exist, create it, or append to the file
f, err := os.OpenFile("access.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
_, err = f.Write([]byte("Hello"))
if err != nil {
log.Fatal(err)
}
f.Close()
}
you just need to check the API documentation. This is one way to do it, there is others (with os or bufio)
package main
import (
"io/ioutil"
)
func main() {
// read the whole file at once
b, err := ioutil.ReadFile("input.txt")
if err != nil {
panic(err)
}
// write the whole body at once
err = ioutil.WriteFile("output.txt", b, 0644)
if err != nil {
panic(err)
}
}
Fprintln is pretty close to what you were trying to do:
package main
import (
"fmt"
"os"
)
func main() {
f, e := os.Create("filename.txt")
if e != nil {
panic(e)
}
defer f.Close()
fmt.Fprintln(f, "Hello")
}
https://golang.org/pkg/fmt#Fprintln

Is it possible to extract a tar.xz package in golang?

Is it possible to extract a tar.xz package in golang? My understanding is it's possible to use the library for tar and sending it to an xz go library.
I recently created an XZ decompression package so it is now
possible to extract a tar.xz using only Go code.
The following code extracts the file myfile.tar.xz to the current
directory:
package main
import (
"archive/tar"
"fmt"
"io"
"log"
"os"
"github.com/xi2/xz"
)
func main() {
// Open a file
f, err := os.Open("myfile.tar.xz")
if err != nil {
log.Fatal(err)
}
// Create an xz Reader
r, err := xz.NewReader(f, 0)
if err != nil {
log.Fatal(err)
}
// Create a tar Reader
tr := tar.NewReader(r)
// Iterate through the files in the archive.
for {
hdr, err := tr.Next()
if err == io.EOF {
// end of tar archive
break
}
if err != nil {
log.Fatal(err)
}
switch hdr.Typeflag {
case tar.TypeDir:
// create a directory
fmt.Println("creating: " + hdr.Name)
err = os.MkdirAll(hdr.Name, 0777)
if err != nil {
log.Fatal(err)
}
case tar.TypeReg, tar.TypeRegA:
// write a file
fmt.Println("extracting: " + hdr.Name)
w, err := os.Create(hdr.Name)
if err != nil {
log.Fatal(err)
}
_, err = io.Copy(w, tr)
if err != nil {
log.Fatal(err)
}
w.Close()
}
}
f.Close()
}
http://golang.org/pkg/archive/tar/#example_
also you can do
import "os/exec"
cmd := exec.Command("tar", "-x", "/your/archive.tar.xz")
err := cmd.Run()
There is no Lempel-Ziv-Markow encoder or decoder in the Go standard library. If you are allowed to assume that the platform your code runs on provides the xz utility, you could use stub functions like these:
import "os/exec"
// decompress xz compressed data stream r.
func UnxzReader(r io.Reader) (io.ReadCloser, error) {
unxz := exec.Command("xz", "-d")
unxz.Stdin = r
out, err := unxz.StdoutPipe()
if err != nil {
return nil, err
}
err = unxz.Start()
if err != nil {
return nil, err
}
// we are not interested in the exit status, but we should really collect
// that zombie process
go unxz.Wait()
return out, nil
}

Resources