2011-04-14 112 views
11

我正在通過電線製作一個簡單的文件傳輸發送器和接收器應用程序。到目前爲止,我發送的是將文件轉換爲字節數組並將該數組的塊發送給接收方。如何在c#中將大文件拆分爲塊?

這適用於高達256mb的文件,但任何上述情況,行:

byte[] buffer = StreamFile(fileName); //This is where I convert the file 

Throws a System out of memory exception. 

我正在尋找一種方法來讀取數據塊的文件,然後寫該塊,而不是加載整個文件變成byte。我如何用FileStream來做到這一點?

編輯:

對不起,我的繼承人蹩腳的代碼至今:

private void btnSend(object sender, EventArgs e) 
    { 
     Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 


     byte[] fileName = Encoding.UTF8.GetBytes(fName); //file name 
     byte[] fileData = null; 
     try 
     { 
      fileData = StreamFile(textBox1.Text); //file 
     } 
     catch (OutOfMemoryException ex) 
     { 
      MessageBox.Show("Out of memory"); 
      return; 
     } 

     byte[] fileNameLen = BitConverter.GetBytes(fileName.Length); //length of file name 
     clientData = new byte[4 + fileName.Length + fileData.Length]; 
     fileNameLen.CopyTo(clientData, 0); 
     fileName.CopyTo(clientData, 4); 
     fileData.CopyTo(clientData, 4 + fileName.Length); 
     clientSock.Connect("172.16.12.91", 9050); 
     clientSock.Send(clientData, 0, 4 + fileName.Length, SocketFlags.None); 

     for (int i = 4 + fileName.Length; i < clientData.Length; i++) 
     { 
      clientSock.Send(clientData, i, 1 , SocketFlags.None); 
     } 

     clientSock.Close(); 
    } 

這裏就是我收到(代碼是從教程)

public void ReadCallback(IAsyncResult ar) 
    { 

     int fileNameLen = 1; 
     String content = String.Empty; 
     StateObject state = (StateObject)ar.AsyncState; 
     Socket handler = state.workSocket; 
     int bytesRead = handler.EndReceive(ar); 
     if (bytesRead > 0) 
     { 

      if (flag == 0) 
      { 
       Thread.Sleep(1000); 
       fileNameLen = BitConverter.ToInt32(state.buffer, 0); 
       string fileName = Encoding.UTF8.GetString(state.buffer, 4, fileNameLen); 
       receivedPath = fileName; 
       flag++; 
      } 
       if (flag >= 1) 
       { 
        BinaryWriter writer = new BinaryWriter(File.Open(receivedPath, FileMode.Append)); 
        if (flag == 1) 
        { 
         writer.Write(state.buffer, 4 + fileNameLen, bytesRead - (4 + fileNameLen)); 
         flag++; 
        } 
        else 
         writer.Write(state.buffer, 0, bytesRead); 
         writer.Close(); 
         handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
         new AsyncCallback(ReadCallback), state); 
       } 
     } 
     else 
     { 
      Invoke(new MyDelegate(LabelWriter)); 
     } 

    } 

我真的不想知道如何以塊的形式讀取文件,以便我不需要將其轉換爲字節。

感謝您的答覆,到目前爲止,我想我開始明白:d

+0

沒有找到這樣的方法** ** StreamFile,你能告訴我哪一個庫,我應該包括哪些內容? – AndroidLearner 2012-08-10 13:52:56

回答

12

只需撥打Read多次與小緩衝區(我傾向於使用像16K)。請注意,Read的電話號碼最終可能會比您請求的號碼小的。如果你使用的是固定的塊大小,並且需要整個內存塊,那麼你可以使用一個當然大小的數組。

不知道你怎麼是發送文件,很難提供有關如何構建你的代碼多的建議,但它可能是這樣的:

byte[] chunk = new byte[MaxChunkSize]; 
while (true) 
{ 
    int index = 0; 
    // There are various different ways of structuring this bit of code. 
    // Fundamentally we're trying to keep reading in to our chunk until 
    // either we reach the end of the stream, or we've read everything we need. 
    while (index < chunk.Length) 
    { 
     int bytesRead = stream.Read(chunk, index, chunk.Length - index); 
     if (bytesRead == 0) 
     { 
      break; 
     } 
     index += bytesRead; 
    } 
    if (index != 0) // Our previous chunk may have been the last one 
    { 
     SendChunk(chunk, index); // index is the number of bytes in the chunk 
    } 
    if (index != chunk.Length) // We didn't read a full chunk: we're done 
    { 
     return; 
    } 
} 

如果我是更清醒我'可能會找到一個更可讀的方式來寫這個,但它現在會做。一種選擇是從中間部分提取另一種方法:

// Attempts to read an entire chunk into the given array; returns the size of 
// chunk actually read. 
int ReadChunk(Stream stream, byte[] chunk) 
{ 
    int index = 0; 
    while (index < chunk.Length) 
    { 
     int bytesRead = stream.Read(chunk, index, chunk.Length - index); 
     if (bytesRead == 0) 
     { 
      break; 
     } 
     index += bytesRead; 
    } 
    return index; 
} 
+0

謝謝你 – Raphael 2011-04-14 07:39:39

2
var b = new byte[1<<15]; // 32k 
while((count = inStream.Read(b, 0, b.Length)) > 0) 
{ 
    outStream.Write(b, 0, count); 
} 
2

你看着WCF流?這是MSDN上的一篇很好的文章,它描述了WCF對數據流GB的功能。

Large Data and Streaming

相關問題