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

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

0

BufferedReaderをメソッドを超えて共有する

ある小説サイトのURLを入力して、HTMLソースを取得しそこからテキストデータを抽出するプログラムを書いたのですが(下記は一部抜粋)、現在1つ目のwhile文でタイトルを抽出、2つ目のwhile文でタイトルから本文までを捨てる、3つ目のwhile文で本文を抽出するという処理を行っています。
ここで私はwhile文をやめ、タイトル抽出専用のメソッドを作成して1回の呼び出しでタイトルを返すメソッドを作りたいのです。そしてその方法としてタイトル抽出専用のメソッドから、bf.readLine()を行いたいのですが何かいい方法はないでしょうか?

私は初心者で拙いソースと説明になってしまうのですがどうかよろしくお願いします・・・

static StringBuffer fileGetContents( String url, String encode ) {
    StringBuffer buffer = new StringBuffer();
    String sep = System.getProperty( "line.separator" );

        try {
            InputStream is = new URL( url ).openStream();
            InputStreamReader isr = new InputStreamReader( is, encode );
            BufferedReader bf = new BufferedReader( isr );
            String s = bf.readLine();

            while( s != null ) {
                if( dc.begin_d( s , "<h2>" ) ) {
                    s = bf.readLine().trim();
                    s = s.substring( 0 , s.indexOf( "</h2>" ) ).trim();
                    buffer.append( "■■■■■■■■■■【"+ s + "】■■■■■■■■■■" + sep + sep);
                    break;
                }
                s = bf.readLine();
            }

            while( s != null ) {
                if( dc.begin_d( s , "<div class=\"text " ) ) {
                    break;
                }
                s = bf.readLine();
            }

            s = bf.readLine();
            while ( s != null ) {

                if( dc.end_d( s , "<br />" ) ) {
                    s = s.substring(0,s.indexOf( "<br />" ));
                    buffer.append( s + sep );
                    continue;
                }

                if( dc.end_d( s , "</div>" ) ) {
                    s = s.substring(0,s.indexOf( "</div>" ));
                    buffer.append( s + sep + sep );
                    break;
                }
                s = bf.readLine();

            }

        } catch ( Exception e ) {
            System.out.println( e.toString() );
            buffer = null;
        }
        return buffer;
    }
}

4

回答

3117

閲覧

4件の回答

評価

30

ごめんなさい、捕捉し忘れましたbegin_d(String1 , String2)およびend_d(String1 , String2)メソッドはString1中にString2が存在する場合はtrueをしない場合はfalseを返すメソッドです。両者の違いは、文字列の先頭から比較するか末尾から比較するかの違いだけです。

評価

30

今、君はレベルアップのためのチェックポイントに差し掛かっていると思っていい。

特定のメソッド中またはブロック中だけで使う変数…ローカル変数
複数のメソッドで使う変数…インスタンス変数
複数のインスタンスで使う変数…クラス変数

オブジェクト指向というのは、この2つ目がキーになる。
ある変数(データ)を複数のメソッドで操作するクラスを考える手法だ。
これを考られるようになるのが、オブジェクト指向プログラミングの第一歩だということだ。

ソース全般について、いくつかお節介しておこうか。

1。今は一般的に、StringBufferではなくJava5で登場したStringBuilderを用いる方がいい(参考書が古い?)。
「スレッド」という言葉が分からない段階なら、まずStringBuilderで問題ない。全般的に速い。

2。StringBufferは、複数の文字列を連結するために用いているはず。
>buffer.append( "■■■■■■■■■■【"+ s + "】■■■■■■■■■■" + sep + sep);
ここで + でやっていることもまた、文字列連結だ。
Javaはこのソースを、以下のように解釈する。
buffer.append(
    new StringBuilder( "■■■■■■■■■■【").append(s).append("】■■■■■■■■■■").append(sep).append(sep).toString()
);
bufferと同じ役割をするものを、もう一つ生成しているのが分かるだろうか。
StringBuffer/Builderを用いる意味が半減してしまう。
この場合は、自分でappend()を連続して書くようにすると良い。
buffer.append( "■■■■■■■■■■【").append(s).append("】■■■■■■■■■■").append(sep).append(sep);

3。System.out.println( e.toString() );という書き方はしない。
e.printStackTrace();としておこう。
先の書き方では、いざ問題が起こったときにその発生箇所が分からない。

4。InputStream/OutputStreamは最後にclose()を呼ぶことを忘れないこと。
通常、try~catch~finallyのfinally句で行う。
現在はJava7から追加されたtry with resourcesを使うのが一般的だが、finallyを覚えておく方が良いと思う。

盛りだくさんの回答になってしまったが、ずっと初心者に甘んじる気がないなら、少しずつ頑張って覚えていこう。

評価

60

おっと、今回BufferedReaderをインスタンス変数にするつもりなら、4は使えなくなるな。

ただ、今回のようなものは、
>タイトル抽出専用のメソッドを作成して1回の呼び出しでタイトルを返すメソッド
とは考えない方がいい。
例えばタイトルが2回、本文が1回欲しかったら、URLへのアクセスを3回行うだろうか?

まずは以下の3つのメソッドを持つクラスを作ってみよう。
1.URLからタイトルと本文を抽出するメソッド
2.1で抽出したタイトルを返すメソッド
3.1で抽出した本文を返すメソッド

個人的には、こういうクラスを作るほうが多いと思う。
1.URLを受け取るコンストラクタ
2.タイトルを返すメソッド(まだ取得していなかったら4を呼んでから返す)
3.本文を返すメソッド(まだ取得していなかったら4を呼んでから返す)
4.URLからタイトルと本文を抽出するprivateメソッド

ステップアップとして。

評価

0

丁寧で迅速で詳細な回答を本当にどうもありがとうございます!!
ご指摘項目3は、まさにその通りでエラー箇所が分からなくなって修正で大変な想いをしました・・・
また質問の他にも怪しい箇所にアドバイスを頂けたのは本当に嬉しいです!

回答者様の言葉を理解し、頑張ってソースコードを修正して行きたいと思います

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