【问题标题】:Missing last bytes of a file缺少文件的最后一个字节
【发布时间】:2012-05-23 05:03:08
【问题描述】:

我是编程新手,但我有一个无法解决的问题。我创建了一个共享文件的程序,例如 Dropbox。我有一台运行良好的服务器和一个客户端。 问题是,当我尝试从服务器下载文件时,流中似乎缺少一些字节。

clientSocket = new TcpClient(Program.host, Program.port);
NetworkStream networkStream = clientSocket.GetStream();
StreamWriter write = new StreamWriter(networkStream);
write.WriteLine(need);
write.Flush();
write.WriteLine(loca);
write.Flush();
StreamReader read = new StreamReader(networkStream);
Int64 size = Convert.ToInt64(read.ReadLine());
long blocks = size / 1024;
long blocksDown = 0;
try
{
    string fileName = string.Empty;
    int qtd = 0;
    int blockSize = 1024;
    double progress = 0;
    Int64 qtdDown = 0;
    Byte[] dataByte = new Byte[blockSize];
    bool download = true;
    lock (this)
    {
        networkStream.Read(dataByte, 0, dataByte.Length);
        int fileNameLen = BitConverter.ToInt32(dataByte, 0);
        fileName = Encoding.ASCII.GetString(dataByte, 4, fileNameLen);
        if (File.Exists(Program.loc + fileName))
            switch (MessageBox.Show("Ficheiro já existente!\r\nDeseja Substituir?", "Aviso", MessageBoxButtons.YesNo,
                MessageBoxIcon.Warning))
            {
                case DialogResult.Yes:
                    File.Delete(Program.loc + fileName);
                    download = true;
                    break;
                case DialogResult.No:
                    download = false;
                    break;
            }
        if (download)
        {
            Stream fileStream = File.OpenWrite(Program.loc + fileName);
            fileStream.Write(dataByte, 4 + fileNameLen, (1024 - (4 + fileNameLen)));
            bool progChanged = false;
            backWork.WorkerReportsProgress = true;
            double progAnt = 0;
            while (true)
            {
                qtd = networkStream.Read(dataByte, 0, blockSize);
                qtdDown += qtd;
                progress = (double)qtdDown * (double)100 / (double)size;
                if (Math.Round(progress) > Math.Round(progAnt))
                {
                    progChanged = true;
                    progAnt = progress;
                }
                if (Math.Round(progress) > 0 && progChanged)
                {
                    backWork.ReportProgress(((int)Math.Round(progress)));
                    progChanged = false;
                }
                fileStream.Write(dataByte, 0, qtd);
                fileStream.Flush();
                blocksDown++;
                if (qtd == 0)
                {
                    backWork.ReportProgress(100);
                    qtd = networkStream.Read(dataByte, 0, blockSize);
                    networkStream.Close();
                    fileStream.Close();
                    break;
                }
            }
            MessageBox.Show("O ficheiro " + fileName + " foi guardado em " + Program.loc + ".", "Download",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}

这就是我正在做的。我正在后台工作人员上进行下载。 首先我在流上写下我正在做的事情,然后我打开文件的流,然后开始读取流并写入文件。


@Ňuf 我试过你说的还是不行 代码长这样,qtdDownsize的字节不相等。抱歉,如果有些部分是葡萄牙语,我的母语是葡萄牙语。

    btnAct.Enabled = false;
    btnBro.Enabled = false;
    btnDown.Enabled = false;
    btnSend.Enabled = false;
    menuStrip1.Enabled = false;
    pBar.Value = 0;
    clientSocket = new TcpClient(Program.host, Program.port);
    NetworkStream networkStream = clientSocket.GetStream();
    StreamWriter write = new StreamWriter(networkStream);
    write.WriteLine(need);
    write.Flush();
    write.WriteLine(loca);
    write.Flush();
    int blockSize = 1024;
    byte[] fileSizeBytes = new byte[blockSize];
    networkStream.Read(fileSizeBytes, 0, blockSize);
    string fileSizeString = Encoding.ASCII.GetString(fileSizeBytes, 0, fileSizeBytes.Length);
    fileSize = Convert.ToInt64(fileSizeString);
    qtdDown = 0;
    try
    {
        string fileName = string.Empty;
        int qtd = 0;
        double progress = 0;
        Byte[] dataByte = new Byte[blockSize];
        bool download = true;
        lock (this)
        {
            networkStream.Read(dataByte, 0, dataByte.Length);
            int fileNameLen = BitConverter.ToInt32(dataByte, 0);
            fileName = Encoding.ASCII.GetString(dataByte, 4, fileNameLen);
            if (File.Exists(Program.loc + fileName))
                switch (MessageBox.Show("Ficheiro já existente!\r\nDeseja Substituir?", "Aviso", MessageBoxButtons.YesNo,
                    MessageBoxIcon.Warning))
                {
                    case DialogResult.Yes:
                        File.Delete(Program.loc + fileName);
                        download = true;
                        break;
                    case DialogResult.No:
                        download = false;
                        break;
                }
            if (download)
            {
                Stream fileStream = File.OpenWrite(Program.loc + fileName);
                fileStream.Write(dataByte, 4 + fileNameLen, (1024 - (4 + fileNameLen)));
                networkStream.ReadTimeout = 60;
                backWork.WorkerReportsProgress = true;
                double progAnt = 0;
                while (true)
                {
                    qtd = networkStream.Read(dataByte, 0, blockSize);
                    qtdDown += qtd;
                    progress = (double)qtdDown * (double)100 / (double)fileSize;
                    if (Math.Round(progress) > Math.Round(progAnt))
                    {
                        progAnt = progress;
                        backWork.ReportProgress(((int)Math.Round(progress)));
                    }
                    fileStream.Write(dataByte, 0, qtd);
                    if (qtdDown == fileSize)
                    {
                        backWork.ReportProgress(100);
                        fileStream.Close();
                        networkStream.Close();
                        break;
                    }
                }
                MessageBox.Show("O ficheiro " + fileName + " foi guardado em " + Program.loc + ".", "Download",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }

    catch (Exception ex)
    {
        menuStrip1.Enabled = true;
        btnAct.Enabled = true;
        btnBro.Enabled = true;
        btnDown.Enabled = true;
        btnSend.Enabled = true;
        MessageBox.Show("Ocorreu um erro!" + "\r\nBytes Downloaded: "
            + qtdDown.ToString() + "\\" + fileSize.ToString() + "\r\nDetalhes do Erro: " + ex.Message, "Download",
            MessageBoxButtons.OK, MessageBoxIcon.Error);
    }

    menuStrip1.Enabled = true;
    btnAct.Enabled = true;
    btnBro.Enabled = true;
    btnDown.Enabled = true;
    btnSend.Enabled = true;

【问题讨论】:

  • 是什么让您相信流中缺少字节?
  • @Ramhound 在下载文件之前,我获取了文件大小来更改进度条的值,并且我还有另一个名为 qtdDown 的变量,它代表已经进行的下载。从流中读取所有内容后,我比较它们,但它们永远不相等。

标签: c# file upload download share


【解决方案1】:

调用 read.ReadLine() 会丢失字节。尽管此函数只返回一行的数据,但它在内部从网络流中读取更多数据到内部缓冲区,并保留剩余数据以供后续 read.Read() 调用,这在您的代码中永远不会发生。

使用 StreamReader 读取数据或直接从 NetworkStrem 读取数据,但不要将两者的读数混合在一起。

【讨论】:

    【解决方案2】:

    我在最后的if中添加了这一行,* || (fileSize - qtdDown)

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      相关资源
      最近更新 更多