How to create a fixed length text file in Golang?

huangapple go评论77阅读模式
英文:

How to create a fixed length text file in Golang?

问题

我需要从数据库中的数据创建一个固定长度的文本文件。数据导出没有问题,将数据加载到Go中也可以。如何以固定长度的样式打印数据?

我有以下结构体:

type D struct {
  A10 string // 结果文件中应该有10个字符
  A20 string // 结果文件中应该有20个字符
  A50 string // 结果文件中应该有50个字符
}

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

因此,打印结构体的结果应该是:

|       ten|              twenty|                                   fifty|

我已经弄清楚了fmt.Printf("%10s", "ten")会在前面填充多达10个空格,但我无法弄清楚如何防止溢出:fmt.Printf("%10s", "tenaaaaaaaa")会打印11个字符。

我考虑了一个函数,它会遍历每个字段并截取过长的字符串:

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

是否有更好的方法?

英文:

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?

答案1

得分: 6

你可以使用字符串格式中的精度来截断输出的字段宽度。

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

将输出 "Hello A"。

所以在你的例子中,可以这样做:

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

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)

答案2

得分: 0

我认为你的方法很好。你还可以使用TextMarshalerStringer接口来比使用函数更清晰地完成。

英文:

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.

答案3

得分: 0

你的方法很好,但是我认为你应该重新考虑一下你的代码目标。

一种更简洁的实现方式是不使用TextMarshaler或String,而是使用类似以下的方法:

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上查看示例代码。

英文:

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
}

<kbd>playground</kbd>

huangapple
  • 本文由 发表于 2014年8月5日 18:20:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/25136415.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定