请问:
fileStream在写文件的时候 可以指定写文件的位置吗?如一个5M的文件 我想写1M到2M之间的流 可以做到吗?我做的是多线程下载文件,平均把文件分为5块下载,那么第一块是0M到1M,第二块是1M到2M,那我现在按流的方式下载了第二块,想把这一块写到这个文件中可以做到吗?我不想先生成临时文件再合并,因为合并太慢,又会有一些问题.

解决方案 »

  1.   

    设置
    Position
    属性
      

  2.   

           FileStream f = new FileStream("D:\\test.txt",FileMode.Read);            byte[] dd = System.Text.Encoding.Default.GetBytes("asasasas");
                f.Position = 10;//上次写到10。从10开始。
                f.Write(dd, 0, dd.Length);
                f.Close();
      

  3.   

    设置Position属性好像也不行 会超出界限 我是这样做的 获得请求 然后每次下载512K 再写入文件 最后循坏,
    如果设置Position好像最大也就512 是这样吧?
      

  4.   

    贴出我的代码:
            #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是接收的字节数请问如何指定下载的位置 我尝试着没指定下载的位置,结果他就只会由头写到尾.麻烦高手看看可以吗?谢谢!
      

  5.   

    其中Download.filestartw[threadh]是一个线程的开始位置,Download.filesizew[threadh]是一个线程的大小
    请高手帮帮忙,万分感谢!
      

  6.   

    先生成一个足够大的文件,比如5M,然后设置Position属性,开始写文件就可以了
      

  7.   

    还是不行阿 我加了一句fs.Position = Download.filestartw[threadh]; 写出来的文件还是有错阿 请高手帮帮忙
      

  8.   

    设置position在单线程中是可以的,但是在多线程如果有多个线程同时下载,那么在下载的过程中会出现不知道当前的position的问题,请问要如何解决?
      

  9.   

       貌似有一个Seek函数。。
      

  10.   

    我把代码改为这样:
            #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 接收线程 这样下载出来的文件还是有一部分读错了,有人告诉我错在哪里吗?谢谢!
      

  11.   

                    nreadsize = ns.Read(nbytes, 0, 512); 
                    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
      

  12.   


                    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() + "正在接收"); 
                    } 
      

  13.   

    silwol,还是每个线程有几行是空白的!为什么呢?请教一下.
    我的代码是这样的:跟你给我的一样
                    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() + "正在接收");
                    }
      

  14.   

    不好意思,我一开始是当成单线程考虑了
    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); 
    }
      

  15.   


     我觉得哈:
     任务开始的时候,就先在硬盘上开辟出这个文件的总大小,比如5M,然后就可以任意在这5M里,用Position指定位置了,其他软件应该也是这样做的吧,比如BT下载一个2G的文件的时候,硬盘上直接就会出现一个2G大小的文件,还有一个文件用于记录下载数据写入的情况。 加分哈!!!
      

  16.   

    暂时测试通过了!谢谢silwol.原来是                    
    nreadsize = ns.Read(nbytes, 0, 512);
    threadreadsize[threadh] += nreadsize; 
    这两句写反了哈哈 应该是
    threadreadsize[threadh] += nreadsize; 
    nreadsize = ns.Read(nbytes, 0, 512);
    才对.
    至于如何解决同步问题,是不是用上锁和解锁就可以了?定义static Object obj = new Object() 有什么用?请问