将二进制文件拆分为块c ++

时间:2012-09-29 03:10:01

标签: c++ parsing file-io

为了通过套接字发送文件,我一直在试图将文件分成块。我可以轻松地读/写文件而不将其分成块。下面的代码运行,工作,有点。它将编写一个文本文件并具有垃圾字符。如果这只是为了txt,没问题。 Jpegs没有使用垃圾。

已经有几天了,所以我完成了我的研究,是时候得到一些帮助了。我确实想严格遵守二进制阅读器,因为这需要处理任何文件。

我见过很多光滑的例子。 (没有一个用jpgs为我工作)大多数情况下是while(文件)...我订阅了,如果你知道大小,使用for循环,而不是while循环阵营。

感谢您的帮助!!

vector<char*> readFile(const char* fn){
    vector<char*> v;
    ifstream::pos_type size;
    char * memblock;
    ifstream file;
    file.open(fn,ios::in|ios::binary|ios::ate);
    if (file.is_open()) {
        size = fileS(fn);
        file.seekg (0, ios::beg);
        int bs = size/3; // arbitrary. Actual program will use the socket send size
        int ws = 0;
        int i = 0;
        for(i = 0; i < size; i+=bs){
            if(i+bs > size)
                ws = size%bs;
            else
                ws = bs;
            memblock = new char [ws];
            file.read (memblock, ws);
            v.push_back(memblock);
        }
    }
    else{
        exit(-4);
    }
    return v;
}


int main(int argc, char **argv) {
    vector<char*> v = readFile("foo.txt");
    ofstream myFile ("bar.txt", ios::out | ios::binary);
    for(vector<char*>::iterator it = v.begin(); it!=v.end(); ++it ){
        myFile.write(*it,strlen(*it));
    }
}

3 个答案:

答案 0 :(得分:2)


问题是你使用strlen来计算要写入的数组的大小。一个0是二进制的一部分,你不会写出正确的大小。相反,使用一对char *,int,其中int指定要写入的大小,您将是黄金。 像:

#include <iostream>
#include <vector>
#include <fstream>
#include <stdlib.h>
#include <string.h>
using namespace std;

ifstream::pos_type fileS(const char* fn)
{
    ifstream file;
        file.open(fn,ios::in|ios::binary);
    file.seekg(0, ios::end);
    ifstream::pos_type ret= file.tellg();
    file.seekg(0,ios::beg);
    ret=ret-file.tellg();
    file.close();
    return ret;
}

vector< pair<char*,int> > readFile(const char* fn){
    vector< pair<char*,int> > v;
    ifstream::pos_type size;
    char * memblock;
    ifstream file;
    file.open(fn,ios::in|ios::binary|ios::ate);
    if (file.is_open()) {
    size = fileS(fn);
    file.seekg (0, ios::beg);
    int bs = size/3; // arbitrary. Actual program will use the socket send size
    int ws = 0;
    int i = 0;
    cout<<"size:"<<size<<" bs:"<<bs<<endl;
    for(i = 0; i < size; i+=bs){
        if(i+bs > size)
            ws = size%bs;
        else
            ws = bs;
        cout<<"read:"<<ws<<endl;
        memblock = new char [ws];
        file.read (memblock, ws);
        v.push_back(make_pair(memblock,ws));
    }
    }
    else{
    exit(-4);
    }
    return v;
}


int main(int argc, char **argv) {
    vector< pair<char*,int> > v = readFile("a.png");
    ofstream myFile ("out.png", ios::out | ios::binary);
    for(vector< pair<char*,int> >::iterator it = v.begin(); it!=v.end(); ++it ){
    pair<char*,int> p=*it;
    myFile.write(p.first,p.second);
    }
}

答案 1 :(得分:1)

 myFile.write(*it,strlen(*it));

在二进制数据上使用字符串长度。我怀疑那是你的罪魁祸首。如果没有,那肯定是code-smell

答案 2 :(得分:0)

你永远不应该这样做:

    myFile.write(*it,strlen(*it));

二进制数据。 strlen计算字节,直到它到达一个包含0的字节(我们想说的是NUL,但这是一个诚实的0)。如果您阅读了足够多的二进制数据,那么您将获得一个NUL,并且您将得到一个简短的计数。但实际情况可能会更糟糕,因为没有地方存储NUL for strlen来查找。你只是指望在数据块结束时有一个你读取文件到。

所以不要这样做。记住每个块中的字节数(您可以使用向量&gt;但是还有很多类似C ++的可能性)并使用它来编写数据。