স্ট্রিং অ্যারেতে পাঠ্য ফাইলটি পড়ুন (এবং লিখুন)


103

একটি স্ট্রিং অ্যারে এবং এর বাইরে একটি পাঠ্য ফাইল পড়ার (এবং লেখার) দক্ষতা হ'ল আমি বিশ্বাস করি যে মোটামুটি সাধারণ প্রয়োজন। কোনও ডেটাবেস অ্যাক্সেস করার জন্য প্রাথমিকভাবে প্রয়োজন মুছে ফেলা কোনও ভাষা দিয়ে শুরু করার সময় এটি বেশ কার্যকর useful গোলাঙে একটির কি অস্তিত্ব আছে?
যেমন

func ReadLines(sFileName string, iMinLines int) ([]string, bool) {

এবং

func WriteLines(saBuff[]string, sFilename string) (bool) { 

আমি নকলের পরিবর্তে একটি বিদ্যমান ব্যবহার করতে পছন্দ করব।


4
ব্যবহারের bufio.Scanner একটি ফাইল থেকে লাইন পড়তে দেখুন stackoverflow.com/a/16615559/1136018 এবং golang.org/pkg/bufio
জ্যাক Valmadre

উত্তর:


129

Go1.1 প্রকাশ হিসাবে, একটি বুফিও রয়েছে .স্ক্যানার এপিআই যা সহজেই কোনও ফাইল থেকে লাইন পড়তে পারে। উপরের থেকে নীচের উদাহরণটি বিবেচনা করুন, স্ক্যানার দিয়ে আবার লিখেছেন:

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    var lines []string
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        lines = append(lines, scanner.Text())
    }
    return lines, scanner.Err()
}

// writeLines writes the lines to the given file.
func writeLines(lines []string, path string) error {
    file, err := os.Create(path)
    if err != nil {
        return err
    }
    defer file.Close()

    w := bufio.NewWriter(file)
    for _, line := range lines {
        fmt.Fprintln(w, line)
    }
    return w.Flush()
}

func main() {
    lines, err := readLines("foo.in.txt")
    if err != nil {
        log.Fatalf("readLines: %s", err)
    }
    for i, line := range lines {
        fmt.Println(i, line)
    }

    if err := writeLines(lines, "foo.out.txt"); err != nil {
        log.Fatalf("writeLines: %s", err)
    }
}

126

যদি ফাইলটি খুব বড় না হয় তবে এটি ioutil.ReadFileএবং এর strings.Splitমতো ফাংশনগুলি দিয়ে সম্পন্ন করা যেতে পারে :

content, err := ioutil.ReadFile(filename)
if err != nil {
    //Do something
}
lines := strings.Split(string(content), "\n")

আপনি ioutil এবং স্ট্রিং প্যাকেজগুলিতে ডকুমেন্টেশন পড়তে পারেন ।


5
এটি মেমরির মধ্যে পুরো ফাইলটি পড়ে, ফাইলটি বড় হলে কোনও সমস্যা হতে পারে।
জর্জিজন

22
@Jergason, যা কেন তিনি তার উত্তর সঙ্গে "ফাইল খুব বড় ... না হয়, তাহলে" শুরু
লরেন্ট

9
ioutil হিসাবে আমদানি করা যায়"io/ioutil"
প্রমোদ

7
নোট strings.Split যখন নিয়মিত POSIX পাঠ্য ফাইল পার্স এক অতিরিক্ত লাইন (একটি খালি স্ট্রিং) যোগ হবে উদাহরণস্বরূপ
বেইন

4
উইন্ডোজ এফওয়াইআই, এটি মুছে ফেলবে না \r। সুতরাং আপনি \rপ্রতিটি উপাদান সংযোজন হতে পারে ।
ম্যাটফ্যাক্স

32

প্রথম উত্তর আপডেট করা যাবে না।
যাইহোক, Go1 প্রকাশের পরে, কিছু ব্রেকিং পরিবর্তন রয়েছে, সুতরাং আমি নীচের মত দেখিয়ে আপডেট করেছি:

package main

import (
    "os"
    "bufio"
    "bytes"
    "io"
    "fmt"
    "strings"
)

// Read a whole file into the memory and store it as array of lines
func readLines(path string) (lines []string, err error) {
    var (
        file *os.File
        part []byte
        prefix bool
    )
    if file, err = os.Open(path); err != nil {
        return
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    buffer := bytes.NewBuffer(make([]byte, 0))
    for {
        if part, prefix, err = reader.ReadLine(); err != nil {
            break
        }
        buffer.Write(part)
        if !prefix {
            lines = append(lines, buffer.String())
            buffer.Reset()
        }
    }
    if err == io.EOF {
        err = nil
    }
    return
}

func writeLines(lines []string, path string) (err error) {
    var (
        file *os.File
    )

    if file, err = os.Create(path); err != nil {
        return
    }
    defer file.Close()

    //writer := bufio.NewWriter(file)
    for _,item := range lines {
        //fmt.Println(item)
        _, err := file.WriteString(strings.TrimSpace(item) + "\n"); 
        //file.Write([]byte(item)); 
        if err != nil {
            //fmt.Println("debug")
            fmt.Println(err)
            break
        }
    }
    /*content := strings.Join(lines, "\n")
    _, err = writer.WriteString(content)*/
    return
}

func main() {
    lines, err := readLines("foo.txt")
    if err != nil {
        fmt.Println("Error: %s\n", err)
        return
    }
    for _, line := range lines {
        fmt.Println(line)
    }
    //array := []string{"7.0", "8.5", "9.1"}
    err = writeLines(lines, "foo2.txt")
    fmt.Println(err)
}

18

আপনি এটির জন্য বুফিও প্যাকেজটির সাহায্যে OS.File (যা io.Reader ইন্টারফেস প্রয়োগ করে ) ব্যবহার করতে পারেন । যাইহোক, এই প্যাকেজগুলি স্থির মেমরির ব্যবহারটি (ফাইল যত বড় হোক তা বিবেচনা করে) নিয়ে নির্মিত এবং বেশ দ্রুত।

দুর্ভাগ্যক্রমে এটি মেমরির মধ্যে পুরো ফাইলটি পড়া আরও জটিল করে তোলে। আপনি লাইন সীমা অতিক্রম করলে লাইনটির অংশগুলিতে যোগ দিতে আপনি বাইট ব্যবহার করতে পারেন B বাফার যাইহোক, আমি আপনাকে সরাসরি আপনার প্রকল্পে লাইন রিডারটি ব্যবহার করার চেষ্টা করার পরামর্শ দিচ্ছি (বিশেষত যদি না জানেন তবে টেক্সট ফাইলটি কত বড়!)। তবে ফাইলটি যদি ছোট হয় তবে নিম্নলিখিত উদাহরণটি আপনার পক্ষে যথেষ্ট:

package main

import (
    "os"
    "bufio"
    "bytes"
    "fmt"
)

// Read a whole file into the memory and store it as array of lines
func readLines(path string) (lines []string, err os.Error) {
    var (
        file *os.File
        part []byte
        prefix bool
    )
    if file, err = os.Open(path); err != nil {
        return
    }
    reader := bufio.NewReader(file)
    buffer := bytes.NewBuffer(make([]byte, 1024))
    for {
        if part, prefix, err = reader.ReadLine(); err != nil {
            break
        }
        buffer.Write(part)
        if !prefix {
            lines = append(lines, buffer.String())
            buffer.Reset()
        }
    }
    if err == os.EOF {
        err = nil
    }
    return
}

func main() {
    lines, err := readLines("foo.txt")
    if err != nil {
        fmt.Println("Error: %s\n", err)
        return
    }
    for _, line := range lines {
        fmt.Println(line)
    }
}

অন্য বিকল্পটি হ'ল io.ioutil.ReadAll ব্যবহার করে সম্পূর্ণ ফাইলটি একবারে পড়তে পারেন এবং পরে লাইন দ্বারা স্লাইসিং করতে পারেন। আমি কীভাবে ফাইলটিতে রেখাগুলি লিখতে হয় তার একটি সুস্পষ্ট উদাহরণ দিচ্ছি না, তবে এটি মূলত os.Create()উদাহরণের (লোগো main()) অনুরূপ একটি লুপ অনুসরণ করবে ।


এই তথ্যের জন্য ধন্যবাদ। পুরো কাজটি করার জন্য আমি বিদ্যমান প্যাকেজটি ব্যবহার করতে আরও আগ্রহী ছিলাম, কারণ আমি মনে করি এটি বেশ কার্যকর। উদাহরণস্বরূপ, আমি প্রাথমিকভাবে কোনও ডাটাবেস ব্যবহার না করে ডেটার অধ্যবসায়ের সাথে গো ব্যবহার করতে চাই। কিছু ভাষায় এটি বিশ্বাস করি। যেমন আমি মনে করি রুবির কাছে রেডলাইন রয়েছে যা একটি স্ট্রিংয়ের অ্যারে (স্মৃতি থেকে) পড়ে - এটি নয় যে আমি বিশেষত রুবি পাখা। এটি আমার অনুমানের কোন বড় বিষয় নয়, আমি কেবল সদৃশ পছন্দ করি না তবে এটি কেবল আমারই চাই it যাইহোক, আমি এটি করার জন্য একটি প্যাকেজ লিখেছি এবং সম্ভবত আমি এটি গিথুবে রাখব। এই ফাইলগুলি সাধারণত খুব ছোট।
brianoh

আপনি যদি কোনও ধরণের গো স্ট্রাকচারগুলি (যেমন স্ট্রিং, ইন্টিজার, মানচিত্র বা আরও জটিল স্ট্রাকচারের একটি অ্যারে) চালিয়ে যেতে চান তবে আপনি কেবল এটির gob.Encode()জন্য এটি ব্যবহার করতে পারেন । ফলাফলটি একটি নতুন লাইন পৃথক টেক্সট ফাইলের পরিবর্তে বাইনারি ফাইল। এই ফাইলটিতে সমস্ত ধরণের ডেটা থাকতে পারে, দক্ষতার সাথে পার্স করা যায়, ফলস্বরূপ ফাইলটি আরও ছোট হবে এবং আপনাকে নতুন লাইনগুলি এবং গতিশীল বরাদ্দের মোকাবেলা করতে হবে না। সুতরাং আপনি যদি Go এর সাথে পরবর্তী ব্যবহারের জন্য কিছু চালিয়ে যেতে চান তবে এটি সম্ভবত আপনার পক্ষে আরও উপযুক্ত।
tux21b

আমি যা চাই তা পাঠ্য লাইনের একটি অ্যারে যাতে আমি কোনও লাইন (ক্ষেত্র) পরিবর্তন করতে পারি। এই ফাইলগুলি খুব ছোট। যখন পরিবর্তনগুলি করা হয়, ভেরিয়েবল-দৈর্ঘ্যের স্ট্রিংগুলি শেষ পর্যন্ত আবার লেখা হয়। আমি যা করতে চাই তা এটি খুব নমনীয় এবং দ্রুত। লাইনগুলি (ক্ষেত্রগুলি) আলাদা করতে আমার নতুন লাইনের দরকার। সম্ভবত আরও ভাল উপায় আছে, কিন্তু বর্তমানে এটি আমার উদ্দেশ্যগুলির জন্য ঠিক আছে। আপনার পরামর্শের পরে আমি যাচাই করব এবং সম্ভবত এটি তখন পরিবর্তন করব।
brianoh

4
মনে রাখবেন যে r58 (জুলাই ২০১১) অনুযায়ী এনকোডিং / লাইন প্যাকেজটি সরানো হয়েছে। "এর কার্যকারিতা এখন বুফিয়োতে।"
ক্রিশ্চিয়ানপ

4
func readToDisplayUsingFile1(f *os.File){
    defer f.Close()
    reader := bufio.NewReader(f)
    contents, _ := ioutil.ReadAll(reader)
    lines := strings.Split(string(contents), '\n')
}

বা

func readToDisplayUsingFile1(f *os.File){
    defer f.Close()
    slice := make([]string,0)

    reader := bufio.NewReader(f)

    for{

    str, err := reader.ReadString('\n')
    if err == io.EOF{
        break
    }

        slice = append(slice, str)
    }

4
যত বেশি "আধুনিক" প্রত্যেকে গো বলে চলেছে, ততটা দেখতে 35 বছরের পুরানো ন্যূনতম-ন্যূনতম গ্রন্থাগার বাইন্ডিং কোডের মতো দেখায়। : Simply কেবল একটি লাইন-ভিত্তিক পাঠ্য ফাইলটি পড়া এমন একটি গোলমাল কেবলমাত্র আরও জোরদার করে যে আরও সাধারণ উদ্দেশ্য হতে .... যেতে ... যেতে অনেক দীর্ঘ পথ রয়েছে। অনেকগুলি পাঠ্য আছে, লাইন-ভিত্তিক ডেটা রয়েছে এখনও অন্যান্য ল্যাং এবং প্ল্যাটফর্মগুলিতে খুব দক্ষতার সাথে প্রক্রিয়াজাত করা হচ্ছে। 0 .02
ক্রিশ এইচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.