2013-01-10 84 views
2

我不认为我正在处理的这一小段代码有任何实际应用,但我试图绕过异步并似乎挣扎了一下。比方说,我想从雅虎提取历史股票价格数据,将所有数据保存到单个csv文件,然后使用批量复制将其加载到SQL Server中。我并不担心将数据加载到SQL Server中,但我想知道如何将数据写入新的csv文件。可以/应该异步完成吗?使用async读取/写入数据

据我所知,当抓取历史数据时,没有办法在股票流中获取股票,所以我抓住流并将其映射到一个新列表中,并在每个股票的前面添加股票行情项目。有时我会进行一次测试,我会得到一个没有代码的记录,并且会有一个包含多个代码的记录(例如“MSFT,YHOO”)。

所以,我的问题是,如何将这些数据转储到一个单独的csv文件而不会导致问题?其次,当我分割数据时,我得到一个空尾项目。什么是最好的方法来放弃?

就像我说过的,我不知道这有什么实际应用,但我正在努力学习,所以我希望你能原谅我的无知。感谢您的帮助,我非常感谢。下面是我有:

open System 
open System.IO 
open System.Web 
open System.Net 

let fromDate = new DateTime(2013, 1, 1) 

let getTickers = 
    "MSFT" :: "YHOO" :: [] 

let getData (ticker : string) = 
    async { 
     let url = System.String.Format("http://ichart.finance.yahoo.com/table.csv?s={0}&g=d&ignore=.csv&a={1}&b={2}&c={3}", ticker, fromDate.Month - 1, fromDate.Day, fromDate.Year) 

     Console.WriteLine(url) 

     let req = WebRequest.Create(url) 
     let! rsp = req.AsyncGetResponse() 
     use stream = rsp.GetResponseStream() 
     use reader = new StreamReader(stream) 

     let lines = 
      reader.ReadToEnd().Split('\n') 
      |> Seq.skip 1 // skip header 
      |> Seq.map (fun line-> (String.Format("{0}, {1}", ticker, line.ToString()))) 

     Seq.iter (fun x->printfn "%s" (x.ToString())) lines 
     () 
    } 

let z = 
    getTickers 
    |> List.map getData 
    |> Async.Parallel 
    |> Async.RunSynchronously 
+0

您可以发布消息到一个代理,然后有一个单独的线程,让他们代理和写入csv文件 –

+0

这可能属于[codereview](http://codereview.stackexchange.com/),但您可能会发现这[[相关问题的答案]](http://stackoverflow.com/ a/11677368/162396)很有帮助。如果您只想将数据加载到SQL Server中,则不需要先将其写入文件。 – Daniel

+0

@ovatsus - 我会研究一下。知道任何好的例子吗? – nickfinity

回答

2

IMO,这是过头了,但希望它表明你想知道:

open System 
open System.IO 
open System.Net 

let tickers = 
    [ 
    "MSFT" 
    "YHOO" 
    ] 

let getData (writer: TextWriter) ticker = 
    async { 
    let url = sprintf "http://ichart.finance.yahoo.com/table.csv?s=%s&g=d&ignore=.csv" ticker 
    let req = WebRequest.Create(url) 
    let! resp = req.GetResponseAsync() |> Async.AwaitTask 
    use stream = resp.GetResponseStream() 
    use reader = new StreamReader(stream) 
    let! lines = reader.ReadToEndAsync() |> Async.AwaitTask 
    let lines = 
     lines.Split('\n') 
     |> Seq.skip 1 
     |> Seq.filter ((<>) "") //skip empty lines 
    for line in lines do 
     do! writer.WriteLineAsync(String.Format("{0}, {1}", ticker, line)).ContinueWith(ignore) |> Async.AwaitTask 
    } 

let writeAllToFile path = 
    use writer = new StreamWriter(path=path) 
    tickers 
    |> Seq.map (getData writer) 
    |> Async.Parallel 
    |> Async.RunSynchronously 
    |> ignore 

writeAllToFile @"C:\quotes.csv" 
+0

太棒了,谢谢。现在确保我理解这一切。 – nickfinity

+0

这应该在运行时给出时髦的结果,特别是当有更多的代价时。 StreamWriter不是线程安全的。 –

+0

毫无疑问。如果他想避免这种情况,他必须同步写入或使用排队代理。 – Daniel