块文件成碎片

时间:2019-12-15 16:45:22

标签: c# tcp

我有学校作业,我必须制作一个程序,将不同的文件切成小块(txt文件,图像...)并通过tcp客户端发送,最后将它们重新加入文件并保存。 我在互联网上找到了一种解决方案,但它没有发送所有文件,但最后缺少一点点。 我找不到问题。有人可以帮忙吗?

剪切文件的代码:

      const int chunkSize = 1024; //1KB chunks
      int counter = 0;

      using (var file = File.OpenRead(filePath)) {
          int bytesRead;
          var buffer = new byte[chunkSize];
          while ((bytesRead = file.Read(buffer, 0, buffer.Length)) > 0) {
               Send(ns, buffer);
          }
      }

2 个答案:

答案 0 :(得分:2)

代码中有错误。

为说明起见,假设您要发送的文件的块长度为10,内容为:

 abcdefghijklmnopqrstuvwxyz

(出于说明目的,假定每个字符为1个字节。)

第一次调用file.Read(buffer, 0, buffer.Length)可以填充缓冲区。该调用将返回复制到缓冲区的字节数。由于可用的字符数超过了缓冲区长度,因此file.Read会将接下来的10个字节写入buffer并返回10:

buffer (before call): 0000000000 (where 0 represents \0)
buffer (after call):  abcdefghij
return value of File.read: 10

类似地,对file.Read的第二次调用可以在缓冲区中填充接下来的10个字节:

buffer (before call):  abcdefghij
buffer (after call) : klmnopqrst
return value of File.read: 10

对于第三次调用,文件中仅剩余6个字节。调用file.Read会将剩余的6个字节写入缓冲区,并返回6表示仅写入6个字节。缓冲区的剩余4个字节不会被写入并保留其先前的值:

buffer (before call) = klmnopqrst
buffer (after call)  = uvwxyzqrst
return value of File.read: 6

由于Send发送了整个缓冲区,因此buffer的以下值作为参数提供给Send

abcdefghij
klmnopqrst
uvwxyzqrst

您可能想要的位置是

abcdefghik
klmnopqrst
uvwxyz

那么您如何解决呢?

传统方法是将bytesRead作为参数传递给Send方法。您的Send方法将需要忽略(即不传输)buffer之后出现的bytesRead内容。

  using (var file = File.OpenRead(filePath)) {
      int bytesRead;
      var buffer = new byte[chunkSize];
      while ((bytesRead = file.Read(buffer, 0, buffer.Length)) > 0) {
           Send(ns, buffer, bytesRead);
      }

或者,在缓冲区未满的情况下,您可以将较小的缓冲区作为参数发送给Send

  using (var file = File.OpenRead(filePath)) {
      int bytesRead;
      var buffer = new byte[chunkSize];
      while ((bytesRead = file.Read(buffer, 0, buffer.Length)) > 0) {
           if (bytesRead < buffer.Length)
           {
               var smallBuffer = new byte[bytesRead];
               Array.Copy(buffer, 0, smallBuffer, 0, bytesRead);
               Send(ns, smallBuffer);
           }
           else
           {
               Send(ns, buffer);
           }
      }

答案 1 :(得分:0)

long chunkSize = 1024;
long sentBytes = 0;
byte[] fileBytes = File.ReadAllBytes();
byte[] fileChunk = new Byte[1024];
long fileLen = fileBytes.Length;

While (sentBytes < fileLen)
{
   if (sentBytes + chunkSize > fileLen)
       chunkSize = fileLen - sentBytes;

   Array.Copy(fileBytes, sentBytes, fileChunk, sentBytes, chunkSize);
   sentBytes += chunkSize;
   // HERE DO YOUR SENDING of fileChunk
}

免责声明:未经测试