- PR -

DataInputStreamでのカレント操作

投稿者投稿内容
かんぱち
ベテラン
会議室デビュー日: 2006/06/01
投稿数: 73
投稿日時: 2006-11-18 07:32
こんにちは。

DataInputStreamを使ってカレント操作ができないものかと
悩んでいます。

テキストファイルデータ
@AAAAAAAAAAAAAAAAAAAAA
ABBBBBBBBBBBBBBBBBBBBB
BCCCCCCCCCCCCCCCCCCCCC
CDDDDDDDDDDDDDDDDDDDDD

のデータで@のデータをチェック中Aのデータの内容を
見たいのですが、できなくて困っています。
と言いますのも、
FileInputStream fis = new FileInputStream(_filepath);
DataInputStream dis = new DataInputStream(fis);
boolean keyFlg = true;
 while (keyFlg) {
  line = dis.readLine();
  if (line == null) {
   keyFlg = false;
  } else {
   //次行チェック
   if (dis.readLine()==null) {

   }
  }
 }

この次行チェックの為、dis.readLine()してしまっているのですが、
チェックが終わったら前行にカレントを戻したいのですが、
何かいい方法はないでしょうか?

APIを見る限り無さそうですが・・。
dis.readLine()は非推奨を承知の上、あえてやってます。

よろしくお願いいたします。
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2006-11-20 02:33
「次のデータを見る必要がある」ような処理では、PushbackReader/PushbackInputStreamを
使うのが普通でしょう。
DataInputStream#readLine()を使っていると素直には行かないでしょうが、
似たようなpushback操作を実装すれば良いのでは?
(PushbackDataInputStream を作る)
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-11-20 03:28
引用:

かんぱちさんの書き込み (2006-11-18 07:32) より:
dis.readLine()は非推奨を承知の上、あえてやってます。



エンコーディングを扱えないから非推奨だと承知しているのですよね?
つまり、BufferedReaderでは扱えないバイナリ操作があるのが理由だと。

DataInputStreamは自身でバッファを一切行わないので、
BufferedInputStream#mark(int)、reset()で可能だと思います。

単にテキストを扱うだけなのであれば、

引用:

coasmさんの書き込み (2006-11-20 02:33) より:
「次のデータを見る必要がある」ような処理では、PushbackReader/PushbackInputStreamを
使うのが普通でしょう。



こちらが正解です。

もしくは、BufferedReader#mark(int)、reset()でも可能です。
びしばし
大ベテラン
会議室デビュー日: 2002/03/13
投稿数: 181
投稿日時: 2006-11-20 10:11
ロジックを工夫して「次行チェック」を「カレント行チェック」に書き換えられませんかね ? そうすれば「巻き戻す」処理がなくても問題ないわけですし。

この例だとkeyFlgを使わないようにできると思いますが...。
かんぱち
ベテラン
会議室デビュー日: 2006/06/01
投稿数: 73
投稿日時: 2006-11-21 13:26
ご回答ありがとうございます。

あしゅさんの教えてくださった、mark(int),reset()で
以前やってみたのですが、どうもmark取得できませんでした。
(mark(int)のint部は行数でセットしていましたが、
これが間違っていたのかも・・。)

その為、以下のような処理にしました。

byte[] b = new byte[1];
b[0] = dis.readByte();
dmmy = new String(b);

やりたいことが一行前が最終行である確認なので、
上ロジックで例外になったら最終行判断を行う。
ただ、1文字取り出し、ループ先頭で先頭文字としてデータに
セットしています(邪道ですね)。

line = dis.readLine();
if (line!=null) {
 line = dmmy + line;//dis.readByte()読込時破棄してしまう為
}

このように再セットすると言う汚いロジックになってしまいました。
readByte()で内容を切り取ってしまうというのは、DataInputStream
もあまり親切でないな〜と感じました・・(markが扱えない私が悪いのですが)。

あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-11-21 13:35
引用:

かんぱちさんの書き込み (2006-11-21 13:26) より:
あしゅさんの教えてくださった、mark(int),reset()で
以前やってみたのですが、どうもmark取得できませんでした。
(mark(int)のint部は行数でセットしていましたが、
これが間違っていたのかも・・。)



行数じゃないですよ。バイト数です。
BufferedReaderなら文字数です。

内部的な動きとしては、
バッファを少なくとも指定されたバイト数以上を蓄えられるように拡張して、
reset()するとmark()した時の読み込み位置までバッファ上で戻ります。

そのため、mark()後に指定サイズ以上読み込んだ場合はバッファから
mark()した位置のデータが無くなっている可能性があるため、
reset()に失敗する可能性があります。
かんぱち
ベテラン
会議室デビュー日: 2006/06/01
投稿数: 73
投稿日時: 2006-11-21 20:20
あしゅさん、ありがとうございます。

バイト数でしたか。
全データに対するバイト数ですと、
読み込み速度にも問題が出てきそうですね(?)。
このプログラムの仕様ですが、テキストファイルデータ
を最大400Mぐらいが要求されています。

単純なreadlineなら行を読むだけですので、
現行の速度で全く問題ないのですが・・。

ありがとうございます。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-11-21 22:15
引用:

かんぱちさんの書き込み (2006-11-21 20:20) より:
このプログラムの仕様ですが、テキストファイルデータ
を最大400Mぐらいが要求されています。



テキストファイルならBufferedReaderだと思うのですが・・・。

ファイル全体をreset()可能な範囲に指定する必要はないですよ。
次の行を判定する直前に毎回mark()すればよいわけです。

一行の最大長は明記されていないかもしれませんが、
一般的なバッファサイズ(4K〜8K)程度で十分でしょう。

また、次の行でどんな判定をしたいのか書いていないのでわかりませんが、
単に空行であるかを判定したいのなら、改行コード(CR+LF)の2バイト分
戻れるだけで十分です。

この場合はreadLine()は使えませんが、改行の判定程度ならすぐ作れます。

スキルアップ/キャリアアップ(JOB@IT)