如何拆分一个大文件到C#块? [英] How to split a large file into chunks in c#?

查看:270
本文介绍了如何拆分一个大文件到C#块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过导线的简单文件传输发送者和接收者应用程序。什么我迄今为止是发送器的文件转换成一个字节数组,并发送该阵列的块到接收器。

I'm making a simple file transfer sender and receiver app through the wire. What I have so far is that the sender converts the file into a byte array and sends chunks of that array to the receiver.

这适用于高达文件 256 ,但任何上述情况,行:

This works with file of up to 256mb, but anything above, the line:

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

Throws a System out of memory exception.

我正在寻找一种方法来读取数据块文件然后写,而不是整个文件加载到一个字节的块。我该怎么做了的FileStream

编辑:

对不起,我的继承人蹩脚code迄今:

Sorry, heres my crappy code so far:

    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();
    }

这就是我收到(在code是从一个教程)

And here's how I receive (the code was from a tutorial)

   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));
        }

    }

我真的想知道我怎么可以读取文件中的数据块,这样我不需要将其转换为一个字节。

I just really want to know how I can read the file in chunks so that I dont need to convert it to a byte.

感谢您的答复,到目前为止,我想我开始明白:D

Thanks for the responses so far, I think I'm starting to get it :D

推荐答案

就叫多次与小缓冲区(我倾向于使用像16K)。需要注意的是在调用最终可能会读的的金额超过你要求。如果您使用的是固定的块大小,需要在内存中的整个块,你可以只使用当然是大小的数组。

Just call Read repeatedly with a small buffer (I tend to use something like 16K). Note that the call to Read may end up reading a smaller amount than you request. If you're using a fixed chunk size and need the whole chunk in memory, you could just use an array of that size of course.

不知道你怎么是的发送的文件,很难提供有关如何构建code多的建议,但它可能是这样的:

Without knowing how you're sending the file, it's hard to give much advice about how to structure your code, but it could be something like this:

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;
    }
}

如果我更清醒,我可能会发现写这更可读的方式,但它会为现在要做的。一个选项是提取从中间部分的另一方法:

If I was more awake I'd probably find a more readable way of writing this, but it'll do for now. One option is to extract another method from the middle section:

// 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;
}

这篇关于如何拆分一个大文件到C#块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆