我通过电线制作一个简单的文件传输发送方和接收方应用程序.我到目前为止,发送方将文件转换为字节数组,并将该数组的块发送到接收器.
这个文件最多可以达到256mb,但上面的任何一行都是这样的:
byte[] buffer = StreamFile(fileName); //This is where I convert the file Throws a System out of memory exception.
我正在寻找一种方式来读取文件中的块,然后写入该块,而不是将整个文件加载到一个字节.我如何使用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,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,bytesRead); writer.Close(); handler.BeginReceive(state.buffer,StateObject.BufferSize,new AsyncCallback(ReadCallback),state); } } else { Invoke(new MyDelegate(LabelWriter)); } }
我只是想知道如何以块的形式读取文件,以便我不需要将其转换为一个字节.
感谢您的答复,我想我开始得到它:D
解决方法
只需使用一个小缓冲区重复读取(我倾向于使用像16K这样的东西).请注意,对“读取”的调用可能会比您请求的数量少一些.如果您使用固定的块大小并且需要内存中的整个块,那么您可以使用一个大小的数组.
不知道如何发送文件,很难给出关于如何构建代码的很多建议,但它可能是这样的:
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,chunk.Length - index); if (bytesRead == 0) { break; } index += bytesRead; } return index; }