2

为了通过套接字发送,我一直在努力反对首先将文件分成块。我可以轻松地读取/写入文件,而无需将其拆分为块。下面的代码运行,工作,有点。它将写入一个文本文件并具有一个垃圾字符。如果这只是用于txt,没问题。Jpegs 不能处理上述垃圾。

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

我已经看到了很多漂亮的例子。(没有一个对我有用 jpgs) 主要是一些类似于 while(file) 的东西......我订阅了,如果你知道大小,使用 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));
    }
}
4

3 回答 3

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);
    }
}
于 2012-09-29T03:49:56.903 回答
1
 myFile.write(*it,strlen(*it));

在二进制数据上使用字符串长度。我怀疑那是你的罪魁祸首。如果不是,那肯定是代码气味

于 2012-09-29T03:36:20.150 回答
0

你不应该这样做:

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

关于二进制数据。strlen计数字节,直到它遇到一个包含 0 的字节(NUL正如我们喜欢说的,但它是一个诚实的 0)。如果你读了足够多的二进制数据,你会碰到一个 NUL,你会得到一个简短的计数。但实际上情况可能更糟,因为您没有将 NUL 存储在任何地方以供 strlen 查找。您只是指望在您获取的数据块末尾之外有一个可以将文件读入。

所以不要那样做。记住每个块中的字节数(您可以使用向量>,但还有更多类似 C++ 的可能性)并使用它来写入数据。

于 2012-09-29T03:37:03.290 回答