F# 用流写入二进制文件
如何通过temp目录中的streams下载图像文件,我有以下代码,我被卡住了,需要seek和count部分的指导。有一些包装器方法,但出于RAM效率的原因,我特别寻找while循环方法 写作F# 用流写入二进制文件,f#,F#,如何通过temp目录中的streams下载图像文件,我有以下代码,我被卡住了,需要seek和count部分的指导。有一些包装器方法,但出于RAM效率的原因,我特别寻找while循环方法 写作 let tempFileName = Path.GetTempFileName() let request = WebRequest.CreateHttp "http://example.com/image.png" use response = request.GetResponse() :?>
let tempFileName = Path.GetTempFileName()
let request = WebRequest.CreateHttp "http://example.com/image.png"
use response = request.GetResponse() :?> HttpWebResponse
use stream = response.GetResponseStream()
let buffer = Array.zeroCreate 1024
use reader = new BinaryReader(stream)
use memoryStream = new MemoryStream()
use fileStream = new FileStream(tempFileName, FileMode.Open)
while not (reader.PeekChar() <> -1) do
fileStream.Write(reader.ReadBytes(1024), 0, 1024)
return Ok (tempFileName)
let tempFileName=Path.GetTempFileName()
let request=WebRequest.CreateHttp“http://example.com/image.png"
使用response=request.GetResponse():?>HttpWebResponse
使用stream=response.GetResponseStream()
让buffer=Array.zeroCreate 1024
使用读取器=新二进制读取器(流)
使用memoryStream=新的memoryStream()
使用fileStream=newfilestream(tempFileName,FileMode.Open)
而不是(reader.PeekChar()-1)执行以下操作
fileStream.Write(reader.ReadBytes(1024)、0、1024)
返回Ok(tempFileName)
首先,我注意到,尽管您正在创建一个缓冲区
数组,但实际上并没有使用它。其次,当我查看时,特别是的文档时,我注意到它接受一个int参数并返回一个字节数组。这一定意味着它每次都在分配一个新的数组,这似乎与您的意图相反(因为您提到了RAM效率,我假设您实际想要的是每次重复使用相同的缓冲区)
还有一个观察结果:ReadBytes方法表示,如果可用字节数较少,它可能返回一个小于请求大小的数组。您的代码当前未处理该情况
不过,所有这些问题都可以通过切换到新的解决方案来解决。使用此方法,您的while
循环将如下所示:
while not (reader.PeekChar() <> -1) do
let bytesRead = reader.Read(buffer, 0, 1024)
fileStream.Write(buffer, 0, bytesRead)
如果bytesRead为0,您想更明确地说明跳过Write
的事实,您可以添加if
块:
let mutable bytesRead = -1
while not (bytesRead = 0) do
bytesRead <- reader.Read(buffer, 0, 1024)
if bytesRead > 0 then
fileStream.Write(buffer, 0, bytesRead)
让可变字节读取=-1
而不是(bytesRead=0)执行
字节读取0
写入(缓冲区,0,字节读取)
最后一个
if
语句严格来说不是必需的,但是:FileStream.Write
如果被要求写入0字节,则应该返回而不做任何操作。但是,由于在我能找到的任何地方都没有文档记录,为了安全起见,我在最后一个代码示例中添加了if
语句。从.NET 4.6.2开始,有System.IO.Stream#CopyTo方法:
namespace-fsharp-basics
模块图像爬虫=
开放系统.Net
开放系统
打开System.Text.RegularExpressions
让私有myurl=”https://cdn.pixabay.com/photo/2016/07/06/15/29/math-1500720_960_720.jpg"
let爬虫程序(url:string)=
让fileName=Regex.Match(url,@“\/([^\/]+)$”,RegexOptions.RightToLeft).Groups[1]。Value
let request=WebRequest.CreateHttp url
let response=request.GetResponse()
使用s=response.GetResponseStream()
使用w=File。创建文件名
s、 抄袭
w、 同花顺
[]
让主argv=
printfn“将保存JPEG文件”
爬虫myurl
printf“已保存”
0
您的问题是什么?你想做什么,你期望会发生什么,以及会发生什么?你指的是什么“查找和计数部分”?我所说的RAM效率是指那些包装器函数将整个图像数据读取到内存中,然后写入文件,这对于大型图像和多个请求来说是低效的。所谓效率,我指的是在数据块到达/传输时立即将其写入磁盘。
let mutable bytesRead = -1
while not (bytesRead = 0) do
bytesRead <- reader.Read(buffer, 0, 1024)
if bytesRead > 0 then
fileStream.Write(buffer, 0, bytesRead)
namespace FSharpBasics
module ImageCrawler =
open System.Net
open System.IO
open System.Text.RegularExpressions
let private myurl = "https://cdn.pixabay.com/photo/2016/07/06/15/29/math-1500720_960_720.jpg"
let crawler (url: string) =
let fileName = Regex.Match(url, @"\/([^\/]+)$", RegexOptions.RightToLeft).Groups.[1].Value
let request = WebRequest.CreateHttp url
let response = request.GetResponse()
use s = response.GetResponseStream()
use w = File.Create fileName
s.CopyTo w
w.Flush true
[<EntryPoint>]
let main argv =
printfn "JPEG file will be saved"
crawler myurl
printf "Saved"
0