Kiril
Kiril

Reputation: 6229

How to create a fixed length text file in Golang?

I need to create a fixed length text file from data in a database. The data export is no problem, and loading data into Go also works. How would I print the data in a fixed length style?

I have the following struct

type D struct {
  A10 string // Should be 10 characters in result file
  A20 string // Should be 20 characters in result file
  A50 string // Should be 50 characters in result file
}

var d := D{ "ten", "twenty", "fifty" }

So, the result of the printed struct should be

|       ten|              twenty|                                   fifty|

I already figured out, that fmt.Printf("%10s", "ten") will prepend up until 10 leading spaces, but I couldn't figure out how to stop it from overflowing: fmt.Printf("%10s", "tenaaaaaaaa") will print 11 characters.

I thought about a function which goes through every field and cuts out too long strings:

func trimTooLong(d *D) {
  d.A10 = d.A10[:10]
  d.A20 = d.A20[:20]
  d.A50 = d.A20[:50]
}

Would there be a better approach?

Upvotes: 3

Views: 7479

Answers (3)

Paul Hankin
Paul Hankin

Reputation: 58349

You can use the precision in the string format to truncate the output as the field width.

fmt.Printf("%5.5s", "Hello, world")
fmt.Printf("%5.5s", "A")

will output "Hello A".

So in your example, this will do the trick:

fmt.Printf("%10.10s%20.20s%50.50s", d.A10, d.A20, d.A50)

Upvotes: 8

OneOfOne
OneOfOne

Reputation: 99351

Your approach is fine really, but IMO you should rethink your goal with that code.

A clean way to implement it without TextMarshaler or String is using something like:

func writeTrimmed(w io.Writer, in []*D) error {
    for _, d := range in {
        a10, a20, a50 := d.A10, d.A20, d.A50
        if len(a10) > 10 {
            a10 = a10[:10]
        }
        if len(a20) > 20 {
            a20 = a20[:20]
        }
        if len(a50) > 50 {
            a50 = a50[:50]
        }
        if _, err := fmt.Fprintf(w, "|%10s|%20s|%50s|\n", a10, a20, a50); err != nil {
            return err
        }
    }
    return nil
}

playground

Upvotes: 0

Elwinar
Elwinar

Reputation: 9519

I think that your method is fine. You could also use the TextMarhsaler or the Stringer interface to do it more cleanly than with a function.

Upvotes: 0

Related Questions