Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

ファイルの交互出力(条件付)で悩んでいます。。

はじめまして、java実装経験が浅い者です。。

下記のような条件のプログラム作成で悩んでいます。
どなたかアドバイスがあればお願い致します。

【I/O情報】
input:Aファイル、Bファイル
(両ファイル共に、データレコードが複数入っていて、1レコードにつき必ずナンバーと言う項目を持っています。両ファイル共にナンバーでソート済み。)

output:Cファイル
(同じナンバー毎にAファイル⇒Bファイル⇒Aファイル・・のように交互に出力する。)


【条件】
?基本的にAファイル⇒Bファイル⇒Aファイル・・のように交互に出力するが、Aファイル.ナンバーとBファイル.ナンバーを比べて、小さいナンバーを持ったレコードの出力の方が、交互に出力する条件より優先。

【出力イメージ】
Cファイル
・Aファイル.ナンバー(1)を持ったレコード 
・Aファイル.ナンバー(1)を持ったレコード 
・Bファイル.ナンバー(1)を持ったレコード 
・Bファイル.ナンバー(1)を持ったレコード 
・Aファイル.ナンバー(2)を持ったレコード 
・Bファイル.ナンバー(2)を持ったレコード 
・Bファイル.ナンバー(3)を持ったレコード 
・Bファイル.ナンバー(4)を持ったレコード 
・Aファイル.ナンバー(5)を持ったレコード 
・Bファイル.ナンバー(5)を持ったレコード 
          ・
          ・

■現在思考中の実装イメージが下記になります。
日本語が混じっていてすみません。。

//ファイルを読み込み、存在したらtrue
boolean x = Aファイルのレコード読込み(bean1に読込み)
boolean y = Bファイルのレコード読込み(bean2に読込み)


while( x || y ){

    if( x && y ) {    
  
        if( bean1.ナンバー <= bean2.ナンバー ){
            int zenNo =  bean1.ナンバー //前レコードのナンバーのバックアップ
        
            while( x && zenNo = bean1.ナンバー) {
            
           Aファイルの出力

                x = Aファイルのレコード読込み(bean1に読込み)
            }  

            if( bean1.ナンバー = bean2.ナンバー ){       

                int zenNo =  bean2.ナンバー //前レコードのナンバーのバックアップ
        
                while( y && zenNo = bean2.ナンバー) {
            
               Bファイルの出力

                   y = Bファイルのレコード読込み(bean2に読込み)
            }

        }else if (bean1.ナンバー > bean2.ナンバー  ) {

            int zenNo =  bean2.ナンバー //前レコードのナンバーのバックアップ
        
            while( y && zenNo = bean2.ナンバー) {
            
          Bファイルの出力

                y = Bファイルのレコード読込み(bean2に読込み)
            }
        }

    }else if( !y ){
        Aファイルのみ出力
    }else if( !x ){
        Bファイルのみ出力
    }

}


7

回答

3442

閲覧

7件の回答

評価

0

zenさんの示されたコードでは
意図した結果が得られない気がします。


良し悪しはわかりませんが、私はこんな感じで書きそうです。

x = Aファイルのレコード読込み(bean1に読込み)
y = Bファイルのレコード読込み(bean2に読込み)

while( x || y ){
  if( x && y ){
    if( bean1.number <= bean2.number){
      Aファイルの出力
      x = Aファイルのレコード読込み(bean1に読込み)
    }else{
      Bファイルの出力
      y = Bファイルの...
    }
  }else if( x ){
    Aファイルの出力
    x = Aファイルの...
  }else if( y ){
    Bファイルの出力
    y = Bファイルの...
  }
}

評価

0

staccさん、ご回答有難うございます。

私も、staccさんのソースの方がシンプルで期待している出力ファイルが得られると思います。
私の方は無駄なコードが多く、あやしいですよね。

勉強になりました。ご指導有難うございます。

評価

0

その昔はCOBOLなんかが得意としていた処理ですが、マッチングと呼ばれるものですね。
それで調べてみても良いでしょう。

評価

0

ソート条件が理解できていないから微妙に違うかも
しれないが。
[A.txt]
サンマ,2,秋刀魚
アジ,3,鯵
イワシ,4,鰯
タイ,5,鯛
ヒラメ,6,平目

[B.txt]
バラ,1,薔薇
ユリ,2,百合
サクラ,3,桜
モモ,4,桃
イチジク,5,無花果

上記のマージ結果は、
[C.txt]
バラ,1,薔薇
サンマ,2,秋刀魚
ユリ,2,百合
アジ,3,鯵
サクラ,3,桜
イワシ,4,鰯
モモ,4,桃
タイ,5,鯛
イチジク,5,無花果
ヒラメ,6,平目

----------------- となるんで良い?
1カラム目:名称
2カラム目:ナンバー
3カラム目:漢字名称
という A,B 2つのテキストファイルを
ナンバーに昇順で、A>B となるように
複合条件でソートした結果を C ファイル
に保存する。

----------------- で、認識合ってる??

評価

0

Java1.4 構文のみ利用
J2SDK1.5 でコンパイル実行結果は上の通り。
仮にこのコードが希望のモノだったとして、
コピペで済ませちゃう後で修正する、となった
時に泣きを見るので心してコピペするなりして
ください。
聞きたいことがあればどうぞ。

[CombiFileReaderWriter.java]
import java.io.*;
import java.util.*;

public class CombiFileReaderWriter {

    private Reader _aIsr, _bIsr;
    private Writer _cOsw;
    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            CombiFileReaderWriter fr = new CombiFileReaderWriter(
                    new FileReader(new File("A.txt")),
                    new FileReader(new File("B.txt")),
                    new FileWriter(new File("C.txt"))
                );
            fr.read();
            fr.sort();
            fr.write();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    
    public CombiFileReaderWriter(Reader aIs, Reader bIs, Writer cOs) {
        _aIsr = aIs;
        _bIsr = bIs;
        _cOsw = cOs;
    }
    
    private static final int A_FILE = 0, B_FILE = 1;

    //ここを A,B 専用 Bean に置き換える?
    //
    private class LineManager implements Comparable {
        private int kind; //A=0,B=1
        private int number;//0,1,2,3...N
        private final int column = 3;//CSV カラム数
        private final int numberColumn = 1;
        private String ss;
        public LineManager(int kind, String s) {
            //A,B で number の位置が違うなら変更する必要あり
            //独自の Bean があるなら、Bean に Comparable 
            //インターフェースを実装すること。
            //
            String[] as = s.split(",", column);
            this.kind = kind;
            this.number = Integer.parseInt(as[numberColumn]);
            this.ss = s;
        }
        public String toString() {
            return this.ss;
        }
        //Comparable インターフェースのメソッド
        //Arrays.sort() が比較するために使います。
        public int compareTo(Object o) {
            LineManager od = (LineManager)o;
            //以下4つの戻り値を反転すると降順ソート
            if (this.number < od.number) return -1;
            else if (this.number > od.number) return 1;
            else if (this.kind < od.kind) return -1;
            else if (this.kind > od.kind) return 1;
            return 0;
        }
    }

    private Object[] lineBuffer; //要素は LineManager

    
    public void read() throws IOException {
        List list = new ArrayList();
        BufferedReader aBr = new BufferedReader(_aIsr);
        BufferedReader bBr = new BufferedReader(_bIsr);
        String line;
        while ((line = aBr.readLine()) != null) {
            if (line.equals("")) continue;
            list.add(new LineManager(A_FILE, line));
        }
        while ((line = bBr.readLine()) != null) {
            if (line.equals("")) continue;
            list.add(new LineManager(B_FILE, line));
        }
        aBr.close();
        bBr.close();
        
        lineBuffer = list.toArray();
    }
    public void sort() {
        Arrays.sort(lineBuffer);
    }
    public void write() throws IOException {
        BufferedWriter cBw = new BufferedWriter(_cOsw);
        for (int i=0;i < lineBuffer.length;i++) {
            cBw.write(((LineManager)lineBuffer[i]).toString());
            cBw.newLine();
        }
        cBw.close();
    }
}

評価

0

mioさん、ご回答有難うございます。

mioさんの言う通り、javaでのマッチング処理です。
調べてみます。

評価

0

??さん、ご回答有難うございます。

ソート条件の認識は、合っています。
しかも、私の条件説明より簡潔で分かりやすいです。。

ソースの方は、ちょっと私には難しいので調べながら見させて頂きます。
一度、A.txtとB.txtを読んだ後にソートする方法ですよね。
勉強になります。有難うございます。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。