• ベストアンサー

固定長レコードの取り扱い

ファイルから固定長のレコードを読み込んで、そのレコードから、ある項目をとりだしたいのですが・・・ レコードのフォーマット   名前 : Ch (8byte)   金額1: Int(4byte)   金額2: Int(4byte)   金額3: Int(4byte) ここから、金額2を取り出すには、どうしたら?・・・ $kingaku2 = substr($rec, 12, 4); と、やると、うまくいかない($kingaku2 の Length が 0 になってしまうような・・・)のですが・・・

  • Perl
  • 回答数2
  • ありがとう数1

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

  • ベストアンサー
  • sssohei
  • ベストアンサー率33% (33/98)
回答No.2

Windowsだったら、バイナリモードで開く必要があります。 http://tohoho.wakusei.ne.jp/wwwperl1.htm#Binary 開いた後の分解ですが、unpack 関数はどうでしょう? http://tohoho.wakusei.ne.jp/wwwperl2.htm#unpack ($namae, $kingaku1, $kingaku2, $kingaku3) = unpack ("a8iii", $rec); とすればOKだと思います。 確認を取ったコードを記しておきます。 $rec = "NameABC\0\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00"; ($namae, $kingaku1, $kingaku2, $kingaku3) = unpack ("a8iii", $rec); print $namae, "\n"; print $kingaku1, "\n"; print $kingaku2, "\n"; print $kingaku3, "\n";

参考URL:
http://tohoho.wakusei.ne.jp/wwwperl1.htm#Binary, http://tohoho.wakusei.ne.jp/wwwperl2.htm#unpack

その他の回答 (1)

  • kokucho81
  • ベストアンサー率61% (157/255)
回答No.1

shinsa14 さん、こんにちわ :-)。 $rec にちゃんとデータが入っているのであれば、 ($namae, $kingaku1, $kingaku2, $kingaku3) = $rec =~ m/(.{8})(.{4})(.{4})(.{4})/; で、一気に全部抽出することが出来ます。 これで抽出できないのであれば、$recの中にデータが入っていないか、 データが上述の形(8,4,4,4)になっていないかのどちらかになります。 制作の参考にしてください。

shinsa14
質問者

お礼

ありがとうございます。 ファイルをBinmodeで読み込んででなかったため、レコードが読み込めてなかったようでした。 Binmode を指定したら、教えていただいたやり方で出来ました。 ありがとうございます。

関連するQ&A

  • PLPGSQL レコードセットを列数で取得したい

    Postgresで関数(ストアドプロシージャ)を作成するのに PLPGSQLを使用しています。 レコードセットを取得し、1列目~40列目までを順次値を判定し、特定の値がある場合は、41列~80列のそれぞれ対応する(1列目なら41列目、13列目なら53列目…)列から数値を取得する動きを実現したいと考えています。 上記条件は下記プログラムで実現してますが、再帰処理で同じことが実現できないでしょうか? ※商品マスタを作成して、クエリを作成するのが当たり前と思いますが、よんどころのない事情でこのテーブル形式をを崩せません。(外部システムの汎用データから取り込むためです) ------------------- 以下現状のプログラム ------------------- declare rec record; int1 integer; begin int1:=0; for rec in select * from kudamonouriage where syainid=$1 and kppw=$2 loop if substr(rec.kate1,1,3)='りんご' then int1:=int1+rec.kingaku1; end if; if substr(rec.kate2,1,3)='りんごthen int1:=int1+rec.kingaku2; end if; if substr(rec.kate3,1,3)='りんご' then int1:=int1+rec.kingaku3; end if; … … if substr(rec.kate39,1,3)='りんご' then int1:=int1+rec.kingaku39; end if; if substr(rec.kate40,1,3)='りんご' then int1:=int1+rec.kingaku40; end if; end loop; return int1; end; ---------------- 以上現状のプログラム --------------------- これを ------------------- 希望するプログラム ------------------- declare rec record; int1 integer; begin int1:=0; for rec in select * from kudamonouriage where syainid=$1 and kppw=$2 loop for i 1..40 loop if substr(rec.(i),1,3)='りんご' then int1:=int1+rec.(40+i); end if; end loop; end loop; return int1; end; ---------------- 以上希望のプログラム --------------------- このようにしたいと思っています。 サイト上で色々と検索していますが、解決に至っていません。お力を貸していただけると大変助かります。宜しくお願いいたします。

  • 1レコードからなるファイルを複数レコードに分割

    可変長の1レコードのみのファイル(固定長のレコードが改行コードなくつながっている)をもとにして、固定長のcsvファイルを作成する方法をお教えください。 具体的には、 項目A(10バイト)、項目B(5バイト)、項目C(20バイト)からなる35バイトのデータが改行コードなくつながっている50000バイトくらいの1レコードを入力して、項目A,B,Cから1レコードが構成されるcsvファイルを作成したいと思います。 よろしくお願いします。

  • COBOLで入力レコードフォーマットが可変の場合

    COBOLのプログラミングの質問です。 基本的な質問かもしれませんが。。。 入力となるレコードのフォーマットが可変である場合、 DATA DIVISIONをどのように定義をすれば必要な項目を得られるでしょうか? たとえば以下の場合です。  入力レコード:1024バイト  レコード内容:開始4バイトは固定。          以降は、A(10バイト)、B(20バイト)、C(30バイト)のいずれかのパターンが来る。          ※AからCの先頭1バイトのフラグでA,B,Cのどれかがわかる          Aのフォーマット            1バイト目:フラグ、2~4バイト目:レコード長、5~10バイト目:会社名          Bのフォーマット            1バイト目:フラグ、2~4バイト目:レコード長、5~10バイト目:会社名、            11~20バイト目:会社の従業員数          Cのフォーマット            1バイト目:フラグ、2~4バイト目:レコード長、5~10バイト目:会社名、            11~20バイト目:会社の従業員数、21~30バイト目:会社の売上金額      [レコードの例]      1レコード目:固定部,C,B,A,B,B・・・B,B      2レコード目:固定部,A,C,C,A,B・・・B,C      上記のレコードから、会社名や会社の売上金額を取り出すようにしたいです。  入力レコードのフォーマットが決まっていれば、その項目にそって定義すればよいと思いますが  決まっていない場合の方法がわかりません。  また、読み込んでから判断する必要があるため、どうしてよいかわかりません。  質問内容がわかりにくくてすみませんが、わかる方がいましたらよろしくおねがいします。

  • fopenのモードによりfgetsするレングスが異なるのは何故ですか?

    ファイルを読み、そのレングスをチェックしています。 $file = @fopen($_FILES['fl']['tmp_name'],"r"); if ($file) {  while (!feof($file)) {   $rec = fgets($file);   print("レングス".strlen($rec)."<br>");   (後略) 例えば1500バイトの固定長ファイルを読んだ場合、 fopenモード"r"だと以下の通りです。  レングス1502(改行が含まれるので1500+2?)  レングス1502 これをモード"r+"にすると以下のようになります。    レングス1502  レングス1499 両者の差はどこから来ているのでしょうか? ご教示いただけると幸いです。

    • 締切済み
    • PHP
  • 文字列分割方法

    フォームから入力されたデーターを文字数により4分割したい場合、 シングルバイトとマルチバイト文字列が混在していると、文字化けが起こってしまいます。 私が考えた方法は <?php $test="あああああいいいいいうううううえええええ"; $length = strlen($test); $length2 = (int)$length/4 $quarter[] = substr($test,0,$length2); $quarter[] = substr($test,$length2,$length2); $quarter[] = substr($test,$length2*2,$length2); $quarter[] = substr($test,$length2*3,$length2); echo $quarter[0]."<BR><BR>"; echo $quarter[1]."<BR><BR>"; echo $quarter[2]."<BR><BR>"; echo $quarter[3]."<BR><BR>"; ?> というものだったんですが、この場合$testに半角文字のaなどが入ると 文字化けしてしまいます。 上手く、マルチバイト・シングルバイト複合文字列を文字数により4分割する方法はないでしょうか? ご教授ください

    • ベストアンサー
    • PHP
  • Accessでレポート内の繰り返しレコードの行数を固定したいです。

    Accessでレポート内の繰り返しレコードの行数を固定したいです。 Access2007を使っています。 社内のフォーマットに合わせた物品購入申請書のようなものを Accessのレポート機能を使って印刷したいと思っています。 大きく2つのテーブルから構成されます。  (申請書テーブル)   1文書に1レコードが該当するもの   書類番号、申請日や申請者名、購入目的等が入ります。  (購入物品テーブル)   1文書に複数のレコードが該当するもの   購入する物品の名前や金額等が入ります。   書類番号を外部キーとして申請書テーブルとリンクします。 レポート機能で、この二つのテーブルを対象として、 (正確には、申請書テーブルはフォーム上で開いているレコードのみを対象と  するために、クエリを仲介して) 購入物品は繰り返しにするようにすることで、ひととおり形にはなったのですが、 1つうまくいかないことがあります。 社内のもともとの手書き用フォーマットには、購入物品の記入枠が20行あります。 これは多めにつくってあるので、当然購入物品数が20以下の場合は、残りの行は 空白になっています。 しかし、Accessのレポートで作ったものは空白行がなく、おかげで購入物品件数 により「詳細」と「フッタ」の間の不自然な空白が広くなったりします。 フッタと言っても、内容的には、「上記物品の購入云々~、お願い致します。」 とかサインするエリアとかですので、繰り返しが終わったらすぐに開始をして ほしいのです。 購入物品の数に関わらず全体の行数を20に固定する方法はありますでしょうか?

  • 重複レコードのチェックができなくて困っています。

    UNIX / Cシェル ファイルが以下の条件のときにエラーとなるようにしたいのですが、どのような処理にすればよいかわかりません。 ファイルは各項目固定長(1つ目5バイト、2つ目6バイト、3つ目7バイト) AAAAABBBBBBDDDDDDD・・・(1) AAAAABBBBBBCCCCCCC・・・(2) EEEEEFFFFFFGGGGGGG・・・(3) EEEEEHHHHHHJJJJJJJ・・・(4) KKKKKLLLLLLMMMMMMM・・・(5) (1)と(2)のように頭2つの項目((1)でいえばAAAAAとBBBBBB)が一致している場合はエラーではないが、(3)と(4)のように頭1つの項目は一致しているが、2つ目の項目が違うものはエラーとなるように処理。 (5)のように1つ目の項目が一致するものがなければエラーではない。 初めての質問のため至らない点もあるかと思いますが、よろしくお願いします。

  • 固定長テキストファイルの読み込みについて

    初めて質問します。 VC++6を使用して、以下のことを行おうと思っていますがどのようにすればよいのかわかりません。 固定長テキストファイル数千レコードのデータを、データベース風にSQL文を発行して該当のレコードのみを抽出するようなことは出来ないのでしょうか? その固定長テキストファイルには、キーとなる項目が存在します。 もし抽出が可能であるならば、追加や更新の方法もご教授していただけたらお願いいたします。

  • 「,」区切りについて・・・。

    以下のようなものを作りドリームウィーバーで使用しています。 (作り方は前回ここで教わりました。) <!-- function Format(int) { var res = ""; int = int + ""; for ( cnt = 1; cnt <= int.length; cnt++) { res = int.slice((int.length - cnt),(int.length - cnt + 1)) + res; if ( cnt/3 == Math.floor(cnt/3) ) { res = "," + res; } } return res; } a = (108000); // b = (1450); // d = a + (b * 8) + (2100 * 8); // 合計金額 document.writeln(Format(d)); // // --> 桁区切りの事を教えていただいたのですが、 これでは、dの値が100000になると ,100,000となってしまいます。 上位3桁に「,」が入らないように dの値の表示が100,000とたいのですが、 どなたか御教授お願いいたします。

  • 【SQL*Loader】固定長データのロードについて

    SQL*Loaderで固定長データを項目を指定してDBへロードしたいのですが・・・ 10件の項目があって例えば、 「A,B,C,D,E,F,G,H,I,J」とします。(全部6ビットでCHAR型とします。) このうち、「A,B,C,F,G,H」を指定してロードしたいとき、 おそらく「POSION」を使って制御ファイルを作成すると思います。 実際制御ファイルを作ってロードを試みたところ、 確かにDやEをすっ飛ばして、ロードできたました。 ところが、指定しなかった項目で残りの最後の項目であるIやJが 次のレコードとして認識されてしまうのです。 つまり、「A,B,C,F,G,H」を最初のレコードとして認識し、 続いて「I,J」をレコードとして認識しているのだと思います。 たぶん、IやJも指定してロードするとうまくいく気がします・・ でもI,Jはロードしたくない項目なのです・・・ このI,Jの前、つまり指定項目の最後のHでレコードを切って ここで一つのレコードとして終わらせるようにするような方法がないか 探しております。 どなたかご教示いただければと思います。 よろしくお願いします。

専門家に質問してみよう