StreamReader太贪婪 [英] StreamReader is too greedy
问题描述
我正在尝试处理文本文件的一部分,然后使用 UploadFromStream
将文本文件的其余部分写入云Blob.问题在于StreamReader似乎从底层流中获取了太多内容,因此后续的写入操作什么也不做.
I'm trying to process part of a text file, and write the remainder of the text file to a cloud blob using UploadFromStream
. The problem is that the StreamReader appears to be grabbing too much content from the underlying stream, and so the subsequent write does nothing.
文本文件:
3
Col1,String
Col2,Integer
Col3,Boolean
abc,123,True
def,3456,False
ghijkl,532,True
mnop,1211,False
代码:
using (var stream = File.OpenRead("c:\\test\\testinput.txt"))
using (var reader = new StreamReader(stream))
{
var numColumns = int.Parse(reader.ReadLine());
while (numColumns-- > 0)
{
var colDescription = reader.ReadLine();
// do stuff
}
// Write remaining contents to another file, for testing
using (var destination = File.OpenWrite("c:\\test\\testoutput.txt"))
{
stream.CopyTo(destination);
destination.Flush();
}
// Actual intended usage:
// CloudBlockBlob blob = ...;
// blob.UploadFromStream(stream);
}
调试时,我发现在第一次调用 reader.ReadLine()
时, stream.Position
会跳到文件末尾,这是我所不希望的.我希望流只会根据读者阅读某些内容所需的位置而前进.
When debugging, I observe that stream.Position
jumps to the end of the file on the first call to reader.ReadLine()
, which I don't expect. I expected the stream to be advanced only as many positions as the reader needed to read some content.
我认为流读取器出于性能原因正在进行一些缓冲,但是似乎没有一种方法可以询问读取器真正"在底层流中的位置.(如果有的话,我可以在 CopyingTo
之前手动将流 Seek
移到该位置.)
I imagine that the stream reader is doing some buffering for performance reasons, but there doesn't seem to be a way to ask the reader where in the underlying stream it "really" is. (If there was, I could manually Seek
the stream to that position before CopyingTo
).
我知道我可以继续使用相同的阅读器记录行,然后将其顺序附加到我正在编写的文本文件中,但是我想知道是否有更干净的方法?
I know that I could keep taking lines using the same reader and sequentially append them to the text file I'm writing, but I'm wondering if there's a cleaner way?
我找到了一个StreamReader构造函数,该构造函数在处理底层流时将其保持打开状态,因此我尝试了此操作,希望读者可以在处理流时设置其位置:
I found a StreamReader constructor which leaves the underlying stream open when it is disposed, so I tried this, hoping that the reader would set the stream's position as it's being disposed:
using (var stream = File.OpenRead("c:\\test\\testinput.txt"))
{
using (var reader = new StreamReader(stream, Encoding.UTF8,
detectEncodingFromByteOrderMarks: true,
bufferSize: 1 << 12,
leaveOpen: true))
{
var numColumns = int.Parse(reader.ReadLine());
while (numColumns-- > 0)
{
var colDescription = reader.ReadLine();
// do stuff
}
}
// Write remaining contents to another file
using (var destination = File.OpenWrite("c:\\test\\testoutput.txt"))
{
stream.CopyTo(destination);
destination.Flush();
}
}
但事实并非如此.如果没有让流处于直观状态/位置,为什么要暴露此构造函数?
But it doesn't. Why would this constructor be exposed if it doesn't leave the stream in an intuitive state/position?
推荐答案
当然,有一种更清洁的方法.使用 ReadToEnd 读取剩余数据,然后将其写入新文件.例如:
Sure, there's a cleaner way. Use ReadToEnd to read the remaining data, and then write it to a new file. For example:
using (var reader = new StreamReader("c:\\test\\testinput.txt"))
{
var numColumns = int.Parse(reader.ReadLine());
while (numColumns-- > 0)
{
var colDescription = reader.ReadLine();
// do stuff
}
// write everything else to another file.
File.WriteAllText("c:\\test\\testoutput.txt", reader.ReadToEnd());
}
评论后编辑
如果您想阅读文本并将其上传到流中,则可以将 File.WriteAllText
替换为读取剩余文本并将其写入 StreamWriter
的代码.>由 MemoryStream
支持,然后发送该 MemoryStream
的内容.像这样:
Edit after comment
If you want to read the text and upload it to a stream, you could replace the File.WriteAllText
with code that reads the remaining text, writes it to a StreamWriter
backed by a MemoryStream
, and then sends the contents of that MemoryStream
. Something like:
using (var memStream = new MemoryStream())
{
using (var writer = new StreamWriter(memStream))
{
writer.Write(reader.ReadToEnd());
writer.Flush();
memStream.Position = 0;
blob.UploadFromStream(memStream);
}
}
这篇关于StreamReader太贪婪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!