2

ソケットを介して送信する目的で、最初にファイルをチャンクに分割しようとすることに頭を悩ませてきました。ファイルをチャンクに分割せずに簡単に読み書きできます。以下のコードは実行され、機能します。テキストファイルを書き込み、文字化けします。これがtxtのみの場合は問題ありません。JPEGは、上記のゴミでは機能しません。

数日間それを行っていたので、調査を行ったので、助けを求める時が来ました. これは任意のファイルを処理する必要があるため、バイナリリーダーに厳密に固執したいと思います。

私はそこに多くの洗練された例を見てきました。(それらのどれも jpg では機能しませんでした) ほとんどが while(file) の行に沿ったものです... サイズがわかっている場合は、while ループ キャンプではなく for ループを使用します。

お手伝いありがとう!!

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 は、正しいサイズを記述していません。代わりに、int が書き込まれるサイズを指定する char*,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));

バイナリデータについて。strlen0 を含むバイトに到達するまでバイトをカウントします (NUL言いたいのですが、これは正直な 0 です)。十分な数のバイナリ データを読み取ると、NUL にヒットし、短いカウントが得られます。しかし、strlen が見つけられるように NUL を格納する場所がないため、実際には状況はさらに悪化する可能性があります。ファイルを読み取るために取得したデータブロックの末尾に 1 つあることを期待しているだけです。

だから、それをしないでください。各ブロックのバイト数を覚えておいて (vector> を使用できますが、C++ のような可能性はもっとたくさんあります)、それを使用してデータを書き込みます。

于 2012-09-29T03:37:03.290 に答える