请问:
fileStream在写文件的时候 可以指定写文件的位置吗?如一个5M的文件 我想写1M到2M之间的流 可以做到吗?我做的是多线程下载文件,平均把文件分为5块下载,那么第一块是0M到1M,第二块是1M到2M,那我现在按流的方式下载了第二块,想把这一块写到这个文件中可以做到吗?我不想先生成临时文件再合并,因为合并太慢,又会有一些问题.
fileStream在写文件的时候 可以指定写文件的位置吗?如一个5M的文件 我想写1M到2M之间的流 可以做到吗?我做的是多线程下载文件,平均把文件分为5块下载,那么第一块是0M到1M,第二块是1M到2M,那我现在按流的方式下载了第二块,想把这一块写到这个文件中可以做到吗?我不想先生成临时文件再合并,因为合并太慢,又会有一些问题.
Position
属性
f.Position = 10;//上次写到10。从10开始。
f.Write(dd, 0, dd.Length);
f.Close();
如果设置Position好像最大也就512 是这样吧?
#region 接收线程
public void receive()
{
strUrl = Download.strurl;
ns = null;
nbytes = new byte[512];
nreadsize = 0;
try
{
request = (HttpWebRequest)HttpWebRequest.Create(strUrl);
request.ServicePoint.ConnectionLimit = 10;
request.AddRange(Download.filestartw[threadh], Download.filestartw[threadh] + Download.filesizew[threadh]);
ns = request.GetResponse().GetResponseStream(); //获得接收流
nreadsize = ns.Read(nbytes, 0, 512);
while (nreadsize > 0)
{
fs.Write(nbytes, Download.filestartw[threadh], nreadsize);
nreadsize = ns.Read(nbytes, 0, 512);
Console.WriteLine("线程" + threadh.ToString() + "正在接收");
}
ns.Close();
}
catch (Exception er)
{
throw new Exception(er.Message);
}
Console.WriteLine("线程" + threadh.ToString() + "接收完毕!");
}
#endregion 接收线程fs就是这个文件的流,ns是接收文件的流, nbytes是接收缓冲区, nreadsize是接收的字节数请问如何指定下载的位置 我尝试着没指定下载的位置,结果他就只会由头写到尾.麻烦高手看看可以吗?谢谢!
请高手帮帮忙,万分感谢!
#region 接收线程
public void receive()
{
strUrl = Download.strurl;
ns = null;
nbytes = new byte[512];
nreadsize = 0;
try
{
request = (HttpWebRequest)HttpWebRequest.Create(strUrl);
request.ServicePoint.ConnectionLimit = 10;
request.AddRange(Download.filestartw[threadh], Download.filestartw[threadh] + Download.filesizew[threadh]);
ns = request.GetResponse().GetResponseStream(); //获得接收流
nreadsize = ns.Read(nbytes, 0, 512);
while (nreadsize > 0)
{
fs.Seek(Download.filestartw[threadh] + threadreadsize[threadh] * nreadsize, SeekOrigin.Begin);
fs.Write(nbytes, Download.filestartw[threadh], nreadsize);
nreadsize = ns.Read(nbytes, 0, 512);
threadreadsize[threadh]++; //用于记录某个线程下载了多少次数据
Console.WriteLine("线程" + threadh.ToString() + "正在接收");
}
ns.Close();
}
catch (Exception er)
{
throw new Exception(er.Message);
}
Console.WriteLine("线程" + threadh.ToString() + "接收完毕!");
}
#endregion 接收线程 这样下载出来的文件还是有一部分读错了,有人告诉我错在哪里吗?谢谢!
while (nreadsize > 0)
{
fs.Seek(Download.filestartw[threadh] + threadreadsize[threadh] * nreadsize, SeekOrigin.Begin);
// 定位方法如下,原因在后面
fs.Seek(Download.filestartw[threadh] + threadreadsize[threadh], SeekOrigin.Begin);
fs.Write(nbytes, Download.filestartw[threadh], nreadsize);
nreadsize = ns.Read(nbytes, 0, 512);
threadreadsize[threadh]++; //用于记录某个线程下载了多少次数据
// fs.Write之后,先记录数据,而且不要用次数,你如何确定最后一次Read的数据一定是512?
threadreadsize[threadh] += nreadsize;
nreadsize = ns.Read(nbytes, 0, 512);
Console.WriteLine("线程" + threadh.ToString() + "正在接收");
}
你读错的部分应该就是每个线程最后的一段数据,因为你不能够保证最后读取的数据字节长度一定是512
nreadsize = ns.Read(nbytes, 0, 512);
while (nreadsize > 0)
{
fs.Seek(Download.filestartw[threadh] + threadreadsize[threadh], SeekOrigin.Begin);
fs.Write(nbytes, Download.filestartw[threadh], nreadsize);
threadreadsize[threadh] += nreadsize; //用于记录某个线程下载了多少字节数据
nreadsize = ns.Read(nbytes, 0, 512);
Console.WriteLine("线程" + threadh.ToString() + "正在接收");
}
我的代码是这样的:跟你给我的一样
nreadsize = ns.Read(nbytes, 0, 512);
while (nreadsize > 0)
{
fs.Seek(Download.filestartw[threadh] + threadreadsize[threadh], SeekOrigin.Begin);
fs.Write(nbytes, Download.filestartw[threadh], nreadsize);
nreadsize = ns.Read(nbytes, 0, 512);
threadreadsize[threadh] += nreadsize;
Console.WriteLine("线程" + threadh.ToString() + "正在接收");
}
LZ的fs,是不是在下载开始的时候打开的,然后在每个线程里调用?比如这样:
private void Download()
{
// ....
// 打开fs
FileStream fs....
// 后面开始调用Thread [] thread,thread.Run()
// ....
}简单的说,LZ要解决同步问题,即
fs.Seek(Download.filestartw[threadh] + threadreadsize[threadh], SeekOrigin.Begin);
fs.Write(nbytes, Download.filestartw[threadh], nreadsize); LZ要把每个线程中这两句的执行,当作是一个语句,就像数据库里的事物那样
在你的Download类里面定义一个static Object obj = new Object()
然后
lock(obj)
{
fs.Seek(Download.filestartw[threadh] + threadreadsize[threadh], SeekOrigin.Begin);
fs.Write(nbytes, Download.filestartw[threadh], nreadsize);
}
我觉得哈:
任务开始的时候,就先在硬盘上开辟出这个文件的总大小,比如5M,然后就可以任意在这5M里,用Position指定位置了,其他软件应该也是这样做的吧,比如BT下载一个2G的文件的时候,硬盘上直接就会出现一个2G大小的文件,还有一个文件用于记录下载数据写入的情况。 加分哈!!!
nreadsize = ns.Read(nbytes, 0, 512);
threadreadsize[threadh] += nreadsize;
这两句写反了哈哈 应该是
threadreadsize[threadh] += nreadsize;
nreadsize = ns.Read(nbytes, 0, 512);
才对.
至于如何解决同步问题,是不是用上锁和解锁就可以了?定义static Object obj = new Object() 有什么用?请问