dt2015 2017-09-25 07:06
浏览 194
已采纳

Golang重定向fmt.Scanf从文件而不是os.Stdin读取

Normally when we call fmt.Scanf() in Golang, the program will read from standard input stream i.e. os.stdin

I want, by Golang code, to make fmt.Scanf() to reading from a file stream - similarly to a technique in Python here.

Please note that we have the piping workaround at command line level; here I'm looking for in-Golang code solution.

If you know how to get there, please share.

p.s.

I guess it requires us to

  • read from file stream and store in a string variable bytes
  • assign bytes to os.stdin stream

Though I'm a Golang newbie and my google search is not very helpful so I asked here.

  • 写回答

1条回答 默认 最新

  • doushuzd3033 2017-09-25 07:18
    关注

    Setting a file as os.Stdin

    If this is truly what you want: os.Stdin is a variable (of type *os.File) which you can modify to your liking, you can assign a new value to it. Opening a file and assigning it to os.Stdin, fmt.Scanf() will read directly from that file. For details, see Fill os.Stdin for function that reads from it.

    Here's a complete example which opens a file named a.txt, sets it as os.Stdin, then calls fmt.Scanf() to read a string value from os.Stdin (indirectly from the a.txt file). The code below also handles saving and restoring the original value of os.Stdin. It is not needed here, but it serves as an example, and it's also good habit to restore global things you modify temporarily.

    f, err := os.Open("a.txt")
    if err != nil {
        panic(err)
    }
    defer f.Close()
    
    oldStdin := os.Stdin
    defer func() { os.Stdin = oldStdin }()
    
    os.Stdin = f
    
    var s string
    if _, err := fmt.Scanf("%s", &s); err != nil {
        fmt.Printf("Error reading: %v", err)
    }
    fmt.Println("Read:", s)
    

    Note that you can also redirect os.Stdout to a file like:

    f2, err := os.Create("out.txt")
    if err != nil {
        panic(err)
    }
    defer f2.Close()
    
    oldStdout := os.Stdout
    defer func() { os.Stdout = oldStdout }()
    
    os.Stdout = f2
    
    fmt.Printf("This will be written to the file: %s", f2.Name())
    

    Using fmt.Fscanf()

    An easier, better alternative would be to use fmt.Fscanf() which is analogue to fmt.Scanf(), but here you can also pass an io.Reader to read from, and os.File implements io.Reader, so you can directly pass a file to it.

    Redirecting a file to the standard input of your app

    Another option would be to redirect a file to your app as its standard input when you launch your app. For example:

    go run myapp.go < a.txt
    

    This command will start your app, streaming the contents of the a.txt file to the standard input of your app. And so fmt.Scanf() will read the contents of the a.txt file.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 在若依框架下实现人脸识别
  • ¥15 网络科学导论,网络控制
  • ¥100 安卓tv程序连接SQLSERVER2008问题
  • ¥15 利用Sentinel-2和Landsat8做一个水库的长时序NDVI的对比,为什么Snetinel-2计算的结果最小值特别小,而Lansat8就很平均
  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同