Hi i have a implementation to read a file Line Feed, but it does not work to Carriage Return files the implementation is:
file, err := os.Open(filePath)
if err != nil {
ross := int32(1)
fileValidation = append(fileValidation, p.createPharmacyPanelLoaderResultErr(pharmacyPanel, &ross, err.Error(), err.Error()))
return nil, fileValidation, int32(0)
}
scanner := bufio.NewScanner(file)
for i := 0; scanner.Scan(); i++ {
line := scanner.Text()
}
i want to transform this function to can work with both Carriage Return and Line Feed
I took the ScanLines function from the source code and changed it so it works with \r but now it will only work with \r and not \n or \r\n
package main
import (
"bufio"
"bytes"
"fmt"
"os"
)
func ScanLinesWithCR(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
if i := bytes.IndexByte(data, '\r'); i >= 0 {
// We have a full newline-terminated line.
return i + 1, data[0:i], nil
}
// If we're at EOF, we have a final, non-terminated line. Return it.
if atEOF {
return len(data), data, nil
}
// Request more data.
return 0, nil, nil
}
func main() {
f, _ := os.Open("test.txt")
defer f.Close()
scanner := bufio.NewScanner(f)
scanner.Split(ScanLinesWithCR)
for scanner.Scan() {
fmt.Println(">", scanner.Text())
}
}
Related
I have two columns in a CSV file. I am accessing only the first column using the SearchData() function.
The problem is that I want to access the data as an array but when I return an array string in the AccessData() function and write the products[0] in the SearchData(), it gives me all the data by removing the bracket sign [] only and when I write products[1], it gives me runtime error: index out of range [1] with length 1.
Required result
products[0] = First Item
products[1] = Second Item
...
so on
Code
func AccessData(number int) string {
content, err := ioutil.ReadFile("products/data1.csv")
if err != nil {
log.Fatal(err)
}
Data := string(content)
sliceData := strings.Split(Data, ",")
return sliceData[number]
}
func SearchData(){
for i := 0; i <= 34; i = i + 2 {
products := AccessData(i)
fmt.Println(products)
}
}
This should do the trick:
func firstColumns(filename string) []string {
f, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer f.Close()
r := csv.NewReader(f)
var result []string
for {
row, err := r.Read()
if err != nil {
if err == io.EOF {
break
}
log.Fatal(err)
}
if len(row) > 0 {
result = append(result, row[0])
}
}
return result
}
func main() {
data := firstColumns("products/data1.csv")
fmt.Println(data)
fmt.Println(data[1])
}
This turns the the first column of every row into a []string which can be access index.
The output is:
[First item Second item]
Second item
Am trying to encode the videos with Golang ffmpeg. Am not able to get the video file, it shows this error
invalid character '-' in numeric literal
Postman:
This is my code:
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/xfrr/goffmpeg/transcoder"
)
type Encode struct {
Video string `json:"video"`
}
func encodeFfmpeg(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Println("Encodeing Started")
var encode Encode
video := json.NewDecoder(r.Body).Decode(encode)
file, err := os.Open(video)
if err != nil {
log.Fatalln(err)
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
if err != nil {
log.Fatalln(err)
}
cmd := exec.Command("ffmpeg",
"-i", "pipe:0", // take stdin as input
"-c:a", "libmp3lame", // use mp3 lame codec
"-f", "avi",
"pipe:1",
)
resultBuffer := bytes.NewBuffer(make([]byte, 5*1024*1024)) // pre allocate 5MiB buffer
cmd.Stderr = os.Stderr // bind log stream to stderr
cmd.Stdout = resultBuffer // stdout result will be written here
stdin, err := cmd.StdinPipe() // Open stdin pipe
if err != nil {
log.Fatalln(err)
}
err = cmd.Start() // Start a process on another goroutine
if err != nil {
log.Fatalln(err)
}
_, err = stdin.Write(buf) // pump audio data to stdin pipe
if err != nil {
log.Fatalln(err)
}
err = stdin.Close() // close the stdin, or ffmpeg will wait forever
if err != nil {
log.Fatalln(err)
}
err = cmd.Wait() // wait until ffmpeg finish
if err != nil {
log.Fatalln(err)
}
outputFile, err := os.Create(encodeFile) // create new file
if err != nil {
log.Fatalln(err)
}
defer outputFile.Close()
_, err = outputFile.Write(resultBuffer.Bytes()) // write result buffer to file
if err != nil {
log.Fatalln(err)
}
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "success",
"statusCode": 200,
"data": "Successfully Encoded file",
})
}
func main() {
router := mux.NewRouter()
router.HandleFunc("/encode", encodeFfmpeg).Methods("POST")
//router.HandleFunc("/rtsp", rtsp).Methods("POST")
// config port
fmt.Printf("Starting server at 8080 \n")
http.ListenAndServe(":8080", router)
}
video.mp4 file not showing in request body. Please help me to solve this issue
json.NewDecoder(r.Body).Decode(encode) returns error not video and another thing is that you send your data in form so you can access file from form like:
file, header, err := r.FormFile("video")
i am trying to learn some new stuff with GoLang, and got a litlebit stuck, probaly the reason is just that i am not very good at using arrays.
So heres what i want to do:
Make variable.
Download with that variable.
Add ++1 for that variable
Download with added 1
and loop it lets say 10 times.
I am all good with points 1 and two, but little stuck with 3 & 4. :).
all the files come in .pdf, thats why i made that strconv there.
I probaly should make somekind of Loop in main, and call DownloadFile function with some array parameters in there?
package main
import (
"fmt"
"io"
"net/http"
"os"
"strconv"
)
func main() {
url_id := strconv.Itoa(23430815+2)
filename := url_id+".pdf"
fileUrl := "https://someurLid="+url_id
if err := DownloadFile(filename, fileUrl); err != nil {
panic(err)
}
fmt.Println(fileUrl)
}
func DownloadFile(filepath string, url string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, resp.Body)
return err
}
try this.
package main
import (
"fmt"
"io"
"net/http"
"os"
"strconv"
)
func main() {
url_id_num := 23430815+2
for i := 0; i < 10; i++ {
url_id := strconv.Itoa(url_id_num+i)
filename := url_id+".pdf"
fileUrl := "https://someurLid="+url_id
if err := DownloadFile(filename, fileUrl); err != nil {
panic(err)
}
fmt.Println(fileUrl)
}
}
func DownloadFile(filepath string, url string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, resp.Body)
return err
}
Cerise Limón gave the answer and thats thats how it worked out.
arr := make([]uint8, 3) //How many times it loops
url_id := 23430815 //Starting from id, filename
for range arr {
filename := strconv.Itoa(url_id)+".pdf"
fileUrl := "https://someurl?id="+strconv.Itoa(url_id)
if err := DownloadFile(filename, fileUrl); err != nil {
panic(err)
}
fmt.Println(fileUrl)
url_id++
}
Thank you for pointing out where i should start! :).
I want to run 2 goroutines parallel in App Engine, so that when the first goroutine finish its job, the handler doesn't need to wait the second goroutine - it stops the secend goroutine and returns the result to the client. Is this possible? I tried it with context.WithCancel(), but it didn't work (I use go1.6).
Here is my code:
package mytest
import (
"net/http"
"sync"
"time"
"golang.org/x/net/context"
"google.golang.org/appengine"
"google.golang.org/appengine/log"
"google.golang.org/appengine/urlfetch"
)
func init() {
http.HandleFunc("/test", handlerTest)
http.HandleFunc("/testwait10s", handlerTest10s)
http.HandleFunc("/testwait5s", handlerTest5s)
}
func handlerTest(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
ctx, _ := context.WithTimeout(c, 30*time.Second)
ctx1, ctx1Cancel := context.WithCancel(ctx)
ctx2, ctx2Cancel := context.WithCancel(ctx)
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
log.Infof(ctx1, "Go1 begin ...")
client1 := urlfetch.Client(ctx1)
_, err := client1.Get("http://APP_NAME.appspot.com/testwait5s")
if err != nil {
log.Errorf(ctx1, "Go1 failed: %v", err)
}
ctx2Cancel()
log.Infof(ctx1, "Go1 over ...")
}()
go func() {
defer wg.Done()
log.Infof(ctx2, "Go2 begin ...")
client2 := urlfetch.Client(ctx2)
_, err := client2.Get("http://APP_NAME.appspot.com/testwait10s")
if err != nil {
log.Errorf(ctx2, "Go2 failed %v", err)
}
ctx1Cancel()
log.Infof(ctx2, "Go2 over ...")
}()
wg.Wait()
log.Infof(ctx1, "Go1 and GO2 over")
}
func handlerTest10s(w http.ResponseWriter, r *http.Request) {
time.Sleep(10 * time.Second)
return
}
func handlerTest5s(w http.ResponseWriter, r *http.Request) {
time.Sleep(5 * time.Second)
return
}
Any ideas? Thanks!
Just create a notification channel and send there a signal that one of computations is over and you can proceed without waiting for the other.
func handlerTest(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
ctx, cancel := context.WithTimeout(c, 30*time.Second)
done := make(chan error, 2)
work := func(url, name string) {
log.Infof(ctx, "%s begin ...", name)
client := urlfetch.Client(ctx)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
log.Errorf(ctx, "%s failed: %v", name, err)
done <- err
return
}
req = req.WithContext(ctx)
_, err = client.Do(req)
done <- err
if err != nil {
log.Errorf(ctx, "%s failed: %v", name, err)
return
}
cancel()
log.Infof(ctx, "%s over ...", name)
}
go work("go1", "http://APP_NAME.appspot.com/testwait5s")
go work("go2", "http://APP_NAME.appspot.com/testwait10s")
for i := 0; i < cap(done); i++ {
if err := <-done; err == nil {
log.Infof(ctx, "executed without errors")
return
}
}
log.Error(ctx, "both computations have failed")
}
You can try reducing the value of wg.Add() to wg.Add(1) instead of wg.Add(2).
When one go-routine completes, wg.Done() will reduce the counter value by 1. So, In this case, the WaitGroup (wg) counter value will become ZERO. As a result, wg.Wait() on last line, will not wait for other go-routines to complete.
Note that, if the value of wg counter falls below zero, it will panic the remaining go-routines. So, the go-routines will be exited forcefully.
I need to compute the hash (md5 is ok) for a large number of files. So, in Go I have this code:
package main
import (
"io"
"os"
"fmt"
"path/filepath"
"crypto/md5"
"encoding/hex"
)
func strSliceRemove(slice []string, str string) []string {
var tempSlice []string;
for _, item := range slice {
if item != str {
tempSlice = append(tempSlice, item)
}
}
return tempSlice
}
func fileMD5(path string) (string, error) {
var returnMD5String string
file, err := os.Open(path)
if err != nil {
return returnMD5String, err
}
defer file.Close()
hash := md5.New()
if _, err := io.Copy(hash, file); err != nil {
return returnMD5String, err
}
hashInBytes := hash.Sum(nil)[:16]
returnMD5String = hex.EncodeToString(hashInBytes)
return returnMD5String, nil
}
func main() {
var doRead func(string)
doRead = func(sd string) {
filepath.Walk(sd, func(path string, f os.FileInfo, err error) error {
resolvedPath, resolvedPathErr := filepath.EvalSymlinks(path)
if resolvedPathErr != nil {
return nil
}
if f.Mode()&os.ModeSymlink == os.ModeSymlink {
doRead(resolvedPath)
} else {
if !f.IsDir() {
md5, _ := fileMD5(path)
fmt.Printf("%s\n", md5)
}
}
return nil
})
}
doRead("/tmp/electron")
return
}
It hashes correctly 1400 files in almost one second. If I use my OSX md5 command line utility, it takes more than 10 times the time. It is 10 times slower:
for FILE in `find /tmp/electron`; do
if [ ! -d "$FILE" ]; then
md5 $FILE;
fi;
done;
I tried a basic c program that does the same (based on this answer How to calculate the MD5 hash of a large file in C?) and still the time seems more or less 10 seconds.
What kind of strategy / library does crypto/md5 use?