2

文字列である「名前」(文字の配列)とバイト配列である「データ」(C++での文字の配列)を含むファイルを作成する必要がありますが、最初に直面した問題は「名前」を分離する方法です「データ」から?この場合、改行文字は機能しますが (名前に「\n」が含まれていないと仮定します)、「データ」部分に特殊文字を含めることができるため、いつ終了するかを知る方法がないため、 「データ」のサイズを持つデータの前のファイルの int 値! 私は次のようなコードでこれをやろうとしました:

if((fp = fopen("file.bin","wb")) == NULL)
{
    return false;
}
char buffer[] = "first data\n";
fwrite( buffer ,1,sizeof(buffer),fp );
int number[1];
number[0]=10;
fwrite( number ,1,1, fp );
char data[] = "1234567890";
fwrite( data , 1, number[0], fp );
fclose(fp);

しかし、「int」の部分が正しいかどうかわからなかったので、これを含む他の多くのコードを試しました:

char buffer[] = "first data\n";
fwrite( buffer ,1,sizeof(buffer),fp );
int size=10;
fwrite( &size ,sizeof size,1, fp );
char data[] = "1234567890";
fwrite( data , 1, number[0], fp );

ファイルを開くと、整数ではなく 4 つの「NULL」文字が表示されます。それは正常ですか?私が直面している他の問題は、ファイルから再度読み取ることです! 私が読み取ろうとしたコードはまったく機能しませんでした:( 「fread」で試しましたが、「fseek」を使用する必要があるのか​​ 、それともその後の他の文字を読み取るだけなのかわかりません.

クラスを次のように使用してから、それを書き込んで読み返すことを考えました:

class Sign
{
public:
char* name;
int size;
char* data;
};

しかし、それはC++では簡単なことではありませんでした!!

私も次のことを試しました:

void saveData(char* filename) {

    fstream filestr;
    int n;
    n=10;
    char* data= "1234567890";

    filestr.open (filename, fstream::out | fstream::binary);
    for (int j = 0; j<5 ; j++)
    {
       filestr << n;

       for (int i = 0; i < n; i++) {
            filestr << data[i];
       }
    }
    filestr.close();
}

void readData(char* filename) {
    fstream filestr;
    int n =0;

    filestr.open (filename, fstream::in | fstream::binary);
    int m =0;
    //while(!filestr.eof())
    while(m<5)
    {
        filestr >> n;

        char *data = new char[n];
        for (int i = 0; i < n; i++) {
            filestr >> data[i];
        }
        printf("data is %s\n",data);
        m++;
    }
    filestr.close();
}

しかし、読み取りもうまくいきませんでした。

読んでいると、奇妙な文字が表示されます。


これまでのところ、私のために機能するコードは次のとおりです。

void saveData(char* filename) {
    fstream filestr;
    char * name = "first data\n";
    int n;
    n=10;
    char* data= "asdfghjkl;";

    filestr.open (filename, fstream::out | fstream::binary);
    for (int j = 0; j<5 ; j++)
    {
        filestr << name;
        filestr << strlen(data);
        filestr << data;
    }
    filestr.close();
}


void readData(char* filename) {
    fstream filestr;
    int n =0;

    filestr.open (filename, fstream::in | fstream::binary);
    while(!filestr.eof())
    {
        string name;
        getline(filestr,name,'\n');
        printf("name is %s\n",name.c_str());

        filestr >> n;

        char *data = new char[n];
        for (int i = 0; i < n; i++) {
            filestr >> data[i];
        }
        printf("n is%d\ndata is %s\n",n,data);
    }
    filestr.close();
}

しかし、読書の問題は次のとおりです。

1-(実際の問​​題ではないと思います)実際のデータに加えて他の文字を出力します。2-readData関数で出力を6回取得します(前回はすべてのフィールドを空のフィールドとして取得しました)が、5回しか書き込みませんでした!それがなぜなのか、誰もが知っていますか?それは関係ありますwhile(!filestr.eof())か??

手伝ってくれてありがとう

4

2 に答える 2

3

まず、バイナリ形式での書き込み/読み取りは次のように機能するはずです (ここでは、この読み取りシーケンスの後read_numに含まれます)。10

   FILE* fp = fopen("file.bin", "wb");
   int num = 10;
   fwrite(&num, sizeof(int), 1, fp);
   fclose(fp);

   FILE* fp2 = fopen("file.bin", "rb");
   int read_num;
   fread(&read_num, sizeof(int), 1, fp2);
   fclose(fp2);

また、この書き方は C++ 流ではなく、C 流です。ファイル操作の C++ の方法は、ストリームを意味します。次のサンプルを参照してください。

#include <fstream>
#include <string>

struct data_structure {
   std::string name;
   std::string description;
   int number;

   void save(const std::string& filename) {
      std::ofstream file(filename.c_str());
      file << name.c_str() << std::endl
           << description.c_str() << std::endl
           << number;
   }
   void load(const std::string& filename) {
      std::ifstream file(filename.c_str());

      getline(file, name);
      getline(file, description);
      file >> number;
   }
};

int main() {
   data_structure d, loaded_d;
   d.name = "Name";
   d.description = "Description";
   d.number = 5;

   d.save("file.out");
   loaded_d.load("file.out");

   return 0;
}
于 2010-05-01T16:24:47.637 に答える
0

さて、あなたのコードにはいくつかの問題があります:

fwrite( buffer ,1,sizeof(buffer),fp );

関数は次のように定義されます。

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

つまり、サイズが 1 で、count が sizeof(buffer) であると言って、バッファに情報を送信しています。それはいくつかの場合にはうまくいくかもしれませんが、一般的には逆です。使用してみてください:

fwrite(buffer, sizeof(char), strlen(buffer), fp);

これは文字幅に依存せず、心配する必要のある定数値もありません (基本的にはどの文字列でも機能します)。

これに関する別の小さなこと:

 int number[1];

単一の整数があるため、使用する必要があるのは次のとおりです。

 int number;

変更後にエラーが発生した場合はfwrite、次の呼び出しを使用します。

fwrite( &number, sizeof(int), 1, fp);

これにより、1 つの整数の値がファイルに書き込まれます。

修正したら、コードが機能するかどうかを確認します。これらの呼び出しを修正することで、トラブルシューティングが容易になります。:)

また、フィールド長 (ファイルに int として書き込まれる) を使用する予定がある場合は、長さ、次にデータを読み取る何らかのシステムをセットアップする必要があり、おそらくそれぞれの長さを持っている必要があります。分野。クラスを使用することは、間違いなくそれを処理する最も簡単な方法です。

編集: クラスの代わりに構造体と関数を使用するか、メソッドでクラスを使用することができます。どちらも非常に単純です。構造体/関数:

struct Record
{
    std::string name, data;
};

void writeRecord(Record thisRecord, std::string filename, size_t offset)
{
    if ( ( fp = fopen(filename.c_str(), "wb") ) == NULL ) { return NULL; }

    fwrite( thisRecord.size(), sizeof(unsigned int), 1, fp); // assuming size() return uint
    fwrite( thisRecord.name.c_str(), sizeof(char), name.size(), fp);

    // repeat for data or other fields
    fclose(fp);
}
于 2010-05-01T16:09:40.727 に答える