0
0

More than 5 years have passed since last update.

lseek関数とwrite関数でテキストデータからバイナリデータを作る(Windowsでうまくいかない)

Last updated at Posted at 2018-10-23

テキストデータを読み込んで、バイナリとして吐くプログラムを書きました。
実行すると、Windowsでは失敗しましたが、Linuxではうまくいきました。原因は不明です。

Windows:Windows10、Eclipse、MingWG
Linux:CentOS7、Eclipse、CrossCompiler(VMWare Workstation上)

rawData.txtには1000~3000くらいの4桁の整数が適当に入っています。

Windowsで実行すると、17~18個目のデータを入れるときに、今まで「下位 上位」で書き込まれていたものが「下位 0D 上位」になって、それ以降のデータがおかしくなりました。後半の読み込みも、エラーで止まります。
(原因不明ですが、バイナリファイルが手に入ったので、個人的には完結しました)

【備考】
テキストデータをバイナリにした、という話をしたら「俺はfprintfで書く」と言われました。
手元にファイルディスクリプタでバイナリデータを読み書きするコードがあったから流用してしまったけれど、確かに普通はそうするなと思いました。

以下、コードです。
(includeとかもろもろそのまま)

main.cpp

#include <iostream>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>

using namespace std;

int main(){
        cout << "start processing." << endl;
        string in_path = "rawdata.txt";
        string out_path = "binaryData";

        ifstream ifs(in_path.c_str());
        int fd;

        if(ifs.fail()){
                cout << "cannot read file." << endl;
                return 0;
        }

        string str;
        int ret;
        unsigned short writeData;
        int offset = 0;

        while(getline(ifs, str)){
                writeData = (unsigned short)stoi(str); // 65,535以下の場合、普通にキャストしても大丈夫

                cout << "writedata:" << writeData << endl;

                fd = open(out_path.c_str(), O_RDWR);
                ret = lseek(fd, offset, SEEK_SET); // 書き込む位置を調整
                if(ret < 0){
                        cout << "cannot seek data." << endl; // writeエラー
                        break;
                }
                ret = write(fd, &writeData, sizeof(unsigned short));

                if(ret < 0){
                        cout << "cannot write data." << endl; // writeエラー
                        break;
                }
                if(ret == 0){
                        cout << "failed to write data." << endl;
                }
                close(fd);
                offset += sizeof(unsigned short);
        }
        ifs.close();

        cout << "finished writing data to binary file." << endl;
        cout << "read binary." << endl;

        int fd2;
        unsigned short data;
        int dataLen;

        fd2 = open(out_path.c_str(), O_RDONLY);
        dataLen = sizeof(data);

        while(true){
                ret = read(fd2, &data, dataLen);
                if(ret < 0){
                        cout << "memory read error" << endl;
                        break;
                }
                if(ret == 0){
                        cout << "finish reading." << endl;
                        break;
                }
                cout << "read:" << data << endl;
        }
        close(fd2);
        return 0;
}

以上です。

0
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0