たとえば、次のようなテキスト ファイルがあります。この作品の思い出を残したい。
4 に答える
JME が削減された方法のため、これを行うことはできません。ファイル全体を読み取る必要があります。他の唯一の方法ですが、適切ではないかもしれませんが、ファイルを読み取り、行ごとにレコードストアの新しいエントリに保存することですが、本当に価値があります...
文字と行番号のマッピングを必要とせずに、文字を読み取る問題をさらに単純化したいと思います。
...
Form form=new Form("filename");
InputStream fin=fconn.openDataInputStream();
StringBuffer buf =new StringBuffer();
int c;
int counter=-1;
while((c=fin.read())!=-1)
{
counter++;
if(counter==23)
{
form.append(buf.toString());
buf=null;counter=0;
continue;
}
buf.append((char)c);
}
if(counter<23 && counter>=0) // write the skipped chars between the last number read and the end of file
{
form.append(buf.toString());
buf=null;counter=0;
}
fin.close();
...
これが他の人に役立つことを願っています。
可能だと思いますが、ヒープの使用量が増える可能性のあるハッシュテーブルを使用する必要があります。
とにかく、まず、テキスト ファイルの内容を char 配列に格納する必要があります。次に、char 配列の内容をハッシュテーブルに移動する必要があります。
テキスト ファイルの各行は改行で区切られます。char 配列では、改行 (おそらく) は '\n' に変換されます。改行文字に到達するまで、配列内の文字を連結します。連結された文字 (マイナス '\n') は、最初の行の文字列を形成します。ここには、0 (または任意の 1) に初期化されているはずのカウンターもあるはずです。テキストをハッシュテーブルに保存します。値は作成された文字列になり、キーはカウンターになります。その後、カウンターをインクリメントします。ファイルの終わりに達するまで、配列の残りの部分に対してこのプロセスを繰り返します。
ハッシュテーブルを使用すると、他の行を経由せずに 7 行目の文字列を取得できるようになりました。基本的に、各行は 1 回読み取られています。ただし、少なくとも、ハッシュテーブルに格納された後は、各行をトラバースする必要はありません。
前述したように、これを行うと、特にテキスト ファイルが非常に大きい場合に、ヒープの使用量が増加する可能性があります。
【ところで、お返事が大変遅くなってしまい申し訳ありません。ここに来るのは初めてです(つまり、登録してこの質問に答えたところです):D ]
共通コード
private String readLine(InputStream _inStream, int lineNum)
throws IOException {
if (null == _inStream) {
throw new IOException("Inputstream null.");
}
if (lineNum < 0) {
return ("Cannot read line a number " + lineNum);
}
final StringBuffer buf = new StringBuffer();
byte c;
int curLine = 1;
while (((c = (byte) _inStream.read()) != -1)) {
//System.out.println((char)c);
if (c == '\n') {
++curLine;
if (curLine > lineNum) {
break;
} else if (curLine < lineNum) {
continue;
}
} else if (curLine != lineNum) {
continue;
}
buf.append((char) c);
}
if (0 == buf.length()) {
return null;
} else {
return buf.toString().trim();
}
}
.
private String readLineWithSkip(InputStream _inStream, long skipCharacters)
throws IOException {
if (null == _inStream) {
throw new IOException("Inputstream null.");
}
if (skipCharacters < 1) {
return ("Cannot skip stream of " + skipCharacters + " characters");
}
final StringBuffer buf = new StringBuffer();
byte c;
_inStream.skip(skipCharacters);
while ((c = (byte) _inStream.read()) != '\n') {
//System.out.println((char)c);
buf.append((char) c);
}
if (0 == buf.length()) {
return null;
} else {
return buf.toString().trim();
}
}
.
InputStream inStream = null;
int fileLength = 39;
int skipCharacters = 10;
int lineNumber = 3;
String myLine = "No line read.";
try {
inStream = Class.class.getResourceAsStream("/test.txt");
if (null != inStream) {
inStream.mark(fileLength);
//For Approach II
myLine = readLine(inStream, lineNumber);
inStream.reset();
//For Approach I
myLine = readLineWithSkip(inStream, skipCharacters);
}
} catch (SecurityException se) {
se.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
try {
inStream.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
inStream = null;
System.out.println(myLine);
}
.
アプローチ I: 行番号を累積文字数なしでマップする
- ファイルの 0 番目の位置 (skip() 値として使用される) からその行の文字の最後の行番号をマップするコードを通してファイルを実行します。ライン。このマッピング テーブルは、同じファイルの先頭または末尾に格納できます。
- メソッド readLineWithSkip(inStream, skipCharacters); を使用して上記の共通コードを実行します。他のメソッド呼び出しのみを慎重にコメントしてください。
考慮すべき点:
- 入力ストリームの目的の位置にスキップします
- ファイルの解析とマッピング テーブルの格納のオーバーヘッドがあります。
.
アプローチ II: N 番目の行が読み取られるまで各行を読み取る
- メソッド readLine(inStream, lineNumber); を使用して上記の共通コードを実行します。他のメソッド呼び出しのみを慎重にコメントしてください。
考慮すべき点:
- 目的の行に到達するまで各文字を読み取る必要があるため遅い
- ファイルの解析のオーバーヘッドも、マッピング テーブルの保存もありません。