データファイルの値がlinuxとMacで異なる理由と解決方法

このQ&Aのポイント
  • 質問者は、職場でlinux、自宅でMacを使用しているが、同じバイナリデータファイルから読み出した値が異なることに困っている。
  • 1byteのバイナリデータなのでエンディアンは関係ないと思うが、他に原因があるのか疑問を抱いている。
  • プログラムの一部を示し、linuxとMacでの出力結果を比較しているが、3,8,11番目の値が異なることに気付いている。
回答を見る
  • ベストアンサー

同じデータファイルなのに、linuxとMacで値が違ってしまうのはなぜ?

職場でlinux(初心者です), 自宅でMacを使っています。 同じCプログラムを使って、同じバイナリデータファイルから数値を読み出したところ、職場のlinuxでやった場合と自宅のMacでやった場合では、違う値が出てきてしまいます。読み込むデータは1byteのバイナリなので、エンディアンは関係ないと思うのですが、ほかに原因があるのでしょうか?そばに詳しい人がおらず、困っています。どうしてこういうことが起きるのか、また、どうやったら解決できるのか、どなたか詳しい方、ぜひアドバイスをお願いします。 以下、プログラムの説明とプログラムの一部です。 バイナリデータファイルから、dposition[i]番目の1byteのデータをそれぞれ読み込み、それぞれ別の出力ファイルfo[i]に書き込みます。dposition[i]はPOSITION_NUM個あり、従って、出力ファイルもPOSITION_NUM個用意しています。dposition[i]で指定した場所はとびとびの不連続な場所です。データを読み込むときは、0番目から、一番大きいdposition[i]番目(=maxnum番目)のデータまで、すべてをarray[datanum]に読み込み、書き出すときにdposition[i]番目のデータのみを書き出すよう指定しています。読み込むバイナリファイルはFILE_NUM個あり、すべて同じ形式です。順次開いて読み込み出力を繰り返します。以下プログラムの一部です。 for (j = 0; j < FILE_NUM; j++) { if(NULL == (fi = fopen(fn_in[j],"rb"))) { printf("Cannot open input BISE File\n"); exit(1); } for (datanum = 0; datanum < maxnum+1; datanum++) { array[datanum] = fgetc(fi); } for (i = 0; i < POSITION_NUM; i++) { fprintf(fo[i],"%d\n",array[dposition[i]]); } fclose (fi); } 以下、linuxでやった場合の出力を左、Maxでやった場合の出力を右に並べて書きます。 104 104 100 100 74  22 83  83 60  60 0   0 106 106 79  33 167 167 182 182 180 0 188 188 ... ... 3,8,11番目が違う数字が出力されます。繰り返しますが、プログラムと入力ファイルは同じものです。 linuxでもMacでもターミナルでコンパイル、実行しています。 コンパイラのバージョンは、gccで検索したらなんだかたくさん出てきてしまって、どれが使っているコンパイラのバージョンなのかよくわかりませんでした。 ちなみに、MacはIntel系の方です。 ほか、アドバイスいただくにあたって、何か必要な情報があればご指摘ください。 ぜひよろしくおねがいします。

質問者が選んだベストアンサー

  • ベストアンサー
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.1

バイナリファイルの実際の内容はどうなっているのでしょうか? macとlinuxで結果が異なるということよりも、どちらが間違っているのか、あるいは両方とも間違っているのか、どうなんでしょう。

chari_07
質問者

お礼

odというコマンドでバイナリの中身が直接みられることがわかり、確かめてみました。すると、macとlinuxでは、そもそもインプットファイルの該当部分の値が違ってることがわかりました。。。 全く同じファイルをコピーして使ったはずなんですが。。。 インプットファイルをコピーし直してやり直したら、どちらのPCでもちゃんと同じ値がでてきました。 しょうもない理由ですみませんっっ 皆さん、いろいろとお返事どうもありがとうございましたm(_ _)m

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

大前提として「Mac と Linux で同じ内容として読み込めている」のであれば, #2 にあるように dposition の値があやしいような気がします. ちなみに gcc のバージョンは gcc -v と実行したときの最後の行にあります.

chari_07
質問者

お礼

odというコマンドでバイナリの中身が直接みられることがわかったので、インプットファイルの中身を確かめてみたら、そもそも両PCでインプットファイルの該当部分が違ってることがわかりました。。。 同じファイルをコピーしたはずなんですが。。。 しょうもない理由ですみませんっ! gcc -v の情報、ありがとうございます。 一つ勉強になりました。 お返事どうもありがとうございましたm(_ _)m

  • shred
  • ベストアンサー率35% (25/70)
回答No.3

>linuxでやった場合の出力を左、Maxでやった場合の出力 これはエディタで閲覧したものか、10進数表記したものどちら? あなたはバイナリファイルと言っている。そしてrbモードでオープンしている。しかし読み書きはfgetc,fprintfを用いている。

chari_07
質問者

お礼

odというコマンドでバイナリの中身が直接みられることがわかったので、インプットファイルの該当部分の値を確かめてみたところ、両PCでそもそもインプットファイルの該当部分の値が違ってることがわかりました。。。 全く同じファイルをコピーして使ったはずなんですが。。。 しょうもない理由ですみませんっっ ちなみに、インプットはバイナリ、アウトプットは10進数表示のテキストで、表示した値はテキストのアウトプットファイルの中身でした。 お返事どうもありがとうございましたm(_ _)m

  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

dposition[ ] 配列の中身がlinuxとMacで違うとしか思えません fprintf(fo[i],"%d\n",array[dposition[i]]); を fprintf(fo[i],"dposition=%d:%d\n", dposition[i], array[dposition[i]]); にして確認してみては

chari_07
質問者

お礼

odというコマンドでバイナリの中身が直接みられることがわかったので、アドバイスいただいた方法でdpositionの中身を確かめ、インプットファイルの該当部分の値を確かめてみました。すると、macとlinuxでは、そもそもインプットファイルの該当部分の値が違ってることがわかりました。。。 全く同じファイルをコピーして使ったはずなんですが。。。 しょうもない理由ですみませんっっ お返事どうもありがとうございましたm(_ _)m

関連するQ&A

  • データファイル中のデータをランダムに整列させる方法

    横70文字縦100文字のデータを横X文字のデータを縦にY行整列させ、その結果をもとのファイルに上書きするプログラムを作成しようとしています。横X文字のデータは最初のデータのどこをとってもよく、他の行の一部とかぶってもいいです。X、Yはランダムです。横にX文字ファイルに上書きしたら、またランダムなX文字を次の行に上書きします。かなり考えましたが、作成したプログラムがうまくいきません。どなたか教えてください。よろしくお願いします。 #! /usr/bin/perl my $filename = "reference.fasta"; open FILE, "+< $filename" or die "$!"; my $tmp; my $count = 0; while(my $c = getc FILE){ next if($c eq "\n"); $array[$count] = $c; $count++; } for($j=0;$j<50;$j++){ $var = int(rand 50); for($i=0;$i<$var;$i++){ # print FILE $array[$j][$i]; $tmp .= $array[$j][$i]; } print FILE $tmp, "\n"; } close FILE;

    • ベストアンサー
    • Perl
  • ファイル名を

    あるフォルダ内に、実行ファイルと入力ファイルがあり、プログラムを実行すると、 1. 実行ファイルと同じフォルダ内にあるファイル名を文字型配列に格納する。 2. さらに拡張子が.txtのファイルをさがし、一覧を表示する。 3. 一覧から入力するファイルを選択する。 という動作をするプログラムを作成していますが、上記「1」の方法が分かりません。 下のソースは、既にファイル名を文字型配列に格納した後(「2」と「3」の動作)のものです。 「1」はどのようなソースコードにすればできるのでしょうか。 大変お手数ですが、ご存知の方教えてください。よろしくお願いします。 OS: Windows2000, コンパイラ: Borland C++ 5.5.1 for Win32 #include <stdio.h> #include <stdlib.h> #define num_files 4 #define max_words 10 int main(void){ int i,j,k,check[num_files],num_candidate,select_no; char file_name[num_files][max_words]={"aaa.txt","bbbb.csv","ccc.txt","ddd.txt"}; char candidate[num_files][max_words],txt[]="txt",infile[max_words]; printf("フォルダ内のファイル一覧\n"); for(i=0;i<num_files;i++){ printf("%s\n",file_name[i]); } printf("\n"); printf("拡張子 *.txt のファイル一覧\n"); for(i=0;i<num_files;i++){ check[i]=0; for(j=0;j<max_words;j++){ if(file_name[i][j]=='.'){ if(file_name[i][j+1]==txt[0] && file_name[i][j+2]==txt[1] && file_name[i][j+3]==txt[2] && file_name[i][j+4]=='\0'){ check[i]++; } } } } num_candidate=0; for(i=0;i<num_files;i++){ if(check[i] != 0){ for(j=0;j<max_words;j++){ candidate[num_candidate][j]=file_name[i][j]; if(file_name[i][j] == '\0'){ break; } } num_candidate++; } } for(i=0;i<num_candidate;i++){ printf("%2d. %s\n",i+1,candidate[i]); } printf("\n"); printf("入力ファイルの番号を選択してください: "); scanf("%d",&select_no); if(select_no<1 || select_no>num_candidate){ printf("入力した数字が不適合です。\n"); exit(1); } for(i=0;i<max_words;i++){ infile[i]=candidate[select_no-1][i]; if(candidate[select_no-1][i] == '\0') { break; } } printf("%s を選択しました。\n",infile); return 0; }

  • 受け取ったデータを基にファイルを操作

    お世話になっております。 以下の内容に行き詰まっております。アドバイスのほど頂戴出来ればと投函しました。宜しくお願いいたします。 やりたいこと。 GETにて受け取ったデータ(URL)を基に、同じディレクトリ内のデータファイル(data.txt)に登録のあるデータから、受け取ったURLを削除した内容で書き換えたい。 ※data.txtは、行単位で各データがタブ区切りで以下のように登録されている。 URL 日付 メール … URL 日付 メール …   現状の報告 以下のスクリプトが実際に作成したものですが、現在、受け取っただけではファイル内容を書き換えることが出来ず、リロードしないと駄目な状況となっています。 アドバイス頂きたいこと。 1.スクリプト自体におかしなところ、見直すべきところがあるか? 2.data.txtを書き換えるスクリプトで、もっと効率のよいものはあるか? 以下がその現在のスクリプトです。 <?php $url = $_GET["url"]; $addfname = "./data.txt"; @$data_array = file($addfname); $data_cnt = count($data_array); $data_array2 = $data_array; $s=0; for($i=0; $i<$data_cnt; $i++){  $data_text = explode("<>", $data_array[$i]);  if($url == $data_text[0]){//GETデータと同じURLだったら配列から削除   $s++;   $key = $i - $s + 1;   array_splice($data_array2, $key, 1);  } } //data.txtのデータ上書き $file=fopen("$addfname", "w") or die("OPENエラー $file_name"); flock($file, LOCK_EX); for($i=0; $i<count($data_array2); $i++){ $new_data = $data_array2[$i]; fputs($file, "$new_data"); } flock($file,LOCK_UN); fclose($file); ?> 先にも述べましたが、現状ではこのスクリプトを実行した後、リロードしなければファイル(data.txt)の書き換えが出来ない状況となっています。どんな些細なことでも構いません。ご意見、アドバイスを頂戴できれば幸いです。お忙しい中恐縮ですが宜しくお願いいたします。

    • ベストアンサー
    • PHP
  • テキストファイルのデータからバイナリを作りたい

    現在、テキストデータとしてCSVファイル1つあたり8バイトのデータが1000個ほどのデータが書かれているファイルがあります。このデータをバイナリファイルへ数値も変換して行きたいと思っています。 たとえば1個目のデータ”12345678”というテキストデータをバイナリの"12345678"に変換したらそれを0x00番地に並べて、そして2個目のデータ”87654321”というデータをバイナリにしたらそれを0x90離れた場所に置いていき、それを1000回繰り返して、結果をバイナリファイルで出力したいのですが、何か簡単にできるフリーソフトなどありませんでしょうか? また、プログラムとかでも簡単にできるのならそうしたいのですが、どうしたらよいか教えていただけないでしょうか?

  • CSVデータのn番目だけの値を取得したい

    次のCsvファイルがあります。この2番目の列の値(つまり20,35,58・・・)だけを取得(1次元配列に入れる)したいのです。 ,cosmos,himawari 710,20,106 725,35,131 805,58,175 820,97,180 903,110,180 次のようにしましたが、2番目の値だけの抽出が出来ません。どのように直せば良いでしょうか? <?php $TextData = file("./cosmos.csv"); for($i=0; $i<10; $i++){ $cosmos = $TextData[i][cosmos]; } return $cosmos print_r($cosmos); ?> 出力結果 Array ( [0] => ,cosmos,himawari [1] => 710,20,106 [2] => 725,35,131 [3] => 805,58,175 [4] => 820,97,180 [5] => 903,110,180 )

    • ベストアンサー
    • PHP
  • 複数ファイルの出力

    質問があります。1600個のデータを読み込んで(16個ずつの組で100組)、1番目、3番目、5番目、7番目のデータをss[1].txtとして出力し、同様に2番目、4番目、6番目、8番目のデータをsk[1].txt、9番目、11番目、13番目、15番目のデータをks[1].txt、10番目、12番目、14番目、16番目のデータをkk[1].txtとして出力させます。以下、ss[2].txt,sk[2].txt,ks[2].txt,kk[2].txt・・・に関してはそれぞれ直前のファイルに16を足したデータ(例えばss[2].txtなら、17番目、19番目、21番目、23番目のデータを出力)を出力させるというプログラムです。 以下に自分で作ったプログラムを掲載します。 void ecg_rr(fp,data_max) FILE *fp; { int i,j=0; int c=1; char fname[64]; data[0][i]=trend_data[0][i]; for(i,j=0;i<100,j<100;i++,j++) { sprintf(fname,"ss[%d].txt",1+i); fp = fopen(fname,"w"); fprintf(fp,"%4d\n",c); fprintf(fp,"%8.8f\n",data[0][0+j*16]); fprintf(fp,"%8.8f\n",data[0][2+j*16]); fprintf(fp,"%8.8f\n",data[0][4+j*16]); fprintf(fp,"%8.8f\n",data[0][6+j*16]); sprintf(fname,"sk[%d].txt",1+i); fp = fopen(fname,"w"); fprintf(fp,"%4d\n",c); fprintf(fp,"%8.8f\n",data[0][1+j*16]); fprintf(fp,"%8.8f\n",data[0][3+j*16]); fprintf(fp,"%8.8f\n",data[0][5+j*16]); fprintf(fp,"%8.8f\n",data[0][9+j*16]); fclose(fp); /*ks,kkに関しても同様*/ } } これだと100個ずつファイルを出力できるのですが、データが全て0として出力されてしまいます。

  • fopenしてくれない。。。

    こんにちは。PHP初級者です。 postgresqlに入れたデータをCSVファイルに書き込んで、出力してみたいと思って以下のプログラムを作ってみました。 $file_name ="insatu.csv"; //データベースから呼び出し以下の$arrayへいれるデータは省略します。 //今回は1行のみのデータを入力プログラムになってますが、本当は何行もやるプログラムとなってます。 $array = compact("a","b","c","d","e","f","g","h","i","j","k","l"); $string = implode("," , $array); $file = fopen($file_name, "a") or die ("openエラー $file_name"); flock($file, LOCK_EX); fputs($file, $string."\n"); flock($file, LOCK_UN); fclose($file); $file = fopen($file_name, "r"); while($array = fgetcsv($file, 1000, ",")){ echo "<hr> \n"; for($i=0; $i< count($array); $i++){ echo $array[$i]."<br>"; } } fclose($file); なぜか最初の fopenで dieの方へ行って OPENエラーメッセージが出てきます。 この作業をするためには何かあらかじめ入れなくてはいけない構文とかあるんでしょうか?何か間違っていますでしょうか? それともphp.iniを設定するとかしなくてはいけないんでしょうか? php5を使用してますが、php.iniやphp.ini-distはともに見つからず。 困り果ててます。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • 標準入力からデータを受け取ってランダムファイル処理させたい

    LINUXでCを使っています。 catでデータを標準出力させ、データ解析プログラムで標準入力から受け取り、そのデータをfseek関数を使ってランダム処理させようとしているのですが、うまくいきません。 具体的には、入力データをfseek関数でファイルポジションを一字分戻らせる処理をさせようとしています。でも、標準入力からデータを受け取るとfseekでファイルポジションを戻してやろうとしても戻りません。 fseekを使うには、一度データをファイルに落とし、fopenで開けてやるしか方法がないのでしょうか?

  • 急にプログラムが正しく動かなくなってしまった

    Macのターミナルでcのプログラムを動かしています。 今まで使えていたプログラムが、突然うまく動かなくなりました。 原因が分からないのですが、どなたかアドバイスいただけないでしょうか? プログラムは、 1)ファイル名のリストを読み込んで、 2)読み込んだ名前のバイナリファイルを全て開き 3)それらのファイルからデータを読み込んで処理 というものです。 このプログラムは同じパソコン上でもともと正しく動いていたのですが、あるとき突然、2)の段階で一部のファイルが開けなくなってしまいました。 原因を探るために、ファイルを開いて閉じるだけのプログラムに削ってみましたが、やはり症状は変わりませんでした。 同じプログラムを、別のパソコン(windows+cygwin)にコピーしてみると、ちゃんと動きます。使用中のMacに何か問題があるのかなとおもうのですが、原因が分かりません。 詳しい状況と、開いて閉じるだけの状態に削ったプログラムを以下にのせておきます。どなたか原因が分かる方、ぜひアドバイスをお願いします。 [状況] ・上記2で開きたいバイナリファイルは332個あるのですが、253個しか開けず、それ以降はCannot open (ファイル名)のメッセージが出ます(そういうメッセージを出すようなプログラムにしてあります) ・上記2でfopenの前に、これから開くファイル名を表示させてみると、ファイル名は全て正しく読み込めています。 ・開きたいバイナリデータファイルが壊れていることを想定し、バックアップからコピーし直してみましたが、やはり症状はかわりません。 ・ for (i = 0; i < FILE_NUM; i++) をつかって複数ファイルを開いていますが、最初をi=0とすると1個目から253個目までしかファイルが開けず、最初をi=1とすると、2個目から254個目のファイルまで開けますが、それ以降のファイルはやはり開けません。どういう訳か、253個だけしかファイルが開けないのです。 [プログラム] #include <stdio.h> #include <stdlib.h> #include <string.h> #define FILE_NUM 332 #define DataDir "../N2913S5601W2689E4705" #define FileList "list_BISE3.txt" #define BUFFER 256 main() { char fn[FILE_NUM][BUFFER]; FILE *fp[FILE_NUM], *fi; char buffer[BUFFER]; unsigned short i; char *p; fi = fopen(FileList, "r"); if (!fi) { printf("Cannot Open %s\n",FileList); exit(1); } for (i = 0; i < FILE_NUM; i++) { p = fgets(buffer, BUFFER, fi); if (!p) { break; } p = strchr(buffer,'\n'); if(p != NULL) { *p = '\0'; } sprintf(fn[i], "%s/%s", DataDir, buffer); printf("%s_\n",fn[i]); fp[i] = fopen(fn[i], "rb"); if (!fp[i]) { printf("Cannot Open %s\n", fn[i]); continue; } } fclose(fi); for (i = 0 ; i < FILE_NUM; i++) { fclose(fp[i]); } }

  • CSVファイルの文字コード変換について

    CSVファイルをアップロードし、文字コードをSJISからEUC-JPに変換したいのですが、文字化けが発生します。 ソースは以下のようになっています。 $i=0; $file = fopen($file_path,"r"); while ($data = fgetcsv($file, $file_size, ',')) { for ($j=0; $j < count($data); $j++) { $Array[$i][$j] = mb_convert_encoding($data$j], "EUC", "auto"); }$i++; } PHP5を使用しており、エクセルとテキストエディターでCSVファイルを作成してみましたが結果はどちらも同じでした。 どなたかご教授願います。

    • 締切済み
    • PHP

専門家に質問してみよう