2011-07-02 35 views
6

私はJavaには比較的新しいので、簡単なアンドロイドアプリを作成しようとしています。アプリケーションのassetsフォルダに約3500行の大きなテキストファイルがあり、それを文字列に読み込む必要があります。私はこれを行う方法についての良い例を見つけましたが、バイト配列が1024に初期化される理由について質問があります。テキストファイルの長さに初期化したくないのですか?また、byteではなくcharを使用したいですか?コードは次のとおりです。このバイト配列を1024に初期化する理由

private void populateArray(){ 
    AssetManager assetManager = getAssets(); 
    InputStream inputStream = null; 
    try { 
     inputStream = assetManager.open("3500LineTextFile.txt"); 
    } catch (IOException e) { 
     Log.e("IOException populateArray", e.getMessage()); 
    } 
    String s = readTextFile(inputStream); 
    // Add more code here to populate array from string 
} 

private String readTextFile(InputStream inputStream) { 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    inputStream.length 
    byte buf[] = new byte[1024]; 
    int len; 
    try { 
     while ((len = inputStream.read(buf)) != -1) { 
      outputStream.write(buf, 0, len); 
     } 
     outputStream.close(); 
     inputStream.close(); 
    } catch (IOException e) { 
     Log.e("IOException readTextFile", e.getMessage()); 
    } 
    return outputStream.toString(); 
} 

EDIT:あなたの提案に基づいて、このアプローチを試しました。それはもっと良いですか?ありがとう。

private void populateArray(){ 
    AssetManager assetManager = getAssets(); 
    InputStream inputStream = null; 
    Reader iStreamReader = null; 
    try { 
     inputStream = assetManager.open("List.txt"); 
     iStreamReader = new InputStreamReader(inputStream, "UTF-8"); 
    } catch (IOException e) { 
     Log.e("IOException populateArray", e.getMessage()); 
    } 
    String String = readTextFile(iStreamReader); 
    // more code here 
} 

private String readTextFile(InputStreamReader inputStreamReader) { 
    StringBuilder sb = new StringBuilder(); 
    char buf[] = new char[2048]; 
    int read; 
    try { 
     do { 
      read = inputStreamReader.read(buf, 0, buf.length); 
      if (read>0) { 
       sb.append(buf, 0, read); 
      } 
     } while (read>=0); 
    } catch (IOException e) { 
     Log.e("IOException readTextFile", e.getMessage()); 
    } 
    return sb.toString(); 
} 

答えて

3

この例はあまり良くありません。それは悪い習慣(例外を隠すこと、最終ブロックでストリームを閉じること、明示的なエンコーディングを指定しないことなど)でいっぱいです。これは、入力ストリームの長さを知る方法がないため、1024バイトの長さのバッファを使用します。

ファイルからテキストを読み取る方法については、Java IO tutorialをお読みください。

+0

正確に。これについて考えてみましょう。バイト配列を入力ストリームの長さだけ長くし、ファイルのサイズが4GBであれば、そのファイルの4GBすべてをRAMにロードし、コンピュータの速度を落とし、潜在的にシステムクラッシュを引き起こす可能性があります。これは、一度に1024バイトを読み込んで、アレイで使用されているメモリの量を最小限に抑える理由です。 – OzzyTheGiant

1

ファイルを1024バイトのバッファに読み込んでいます。 これらの1024バイトがoutputStreamに書き込まれます。 このプロセスは、ファイル全体がoutputStreamに読み込まれるまで繰り返されます。 JB Nizetが言及したように、この例は悪い習慣でいっぱいです。

0

ファイルから読み込むには、スキャナとStringBuilderを使用してください。

 Scanner scan = new Scanner(new BufferedInputStream(new FileInputStream(filename)), "UTF-8"); 
     StringBuilder sb = new StringBuilder(); 
     while (scan.hasNextLine()) { 
      sb.append(scan.nextLine()); 
      sb.append("\n"); 
     } 
     scan.close 

     return sb.toString(); 

例外をスローするのではなく、スローするようにしてください。呼び出し元は、ファイルの読み込みに問題があったことを知る必要があります。

編集:また、BufferedInputStreamを使用することも重要です。それ以外の場合は、バイト単位で読み込みを試みますが、遅くなる可能性があります。

+0

これにより、\ r \ nが\ nに変換され、元の内容が破損する可能性があります。 –

+0

@JB Nizetはい、あなたは正しいです。これを実装するより良い方法をご存知ですか? – Lynch

+0

はい。入力ストリームをInputStreamReader内にラップし、その際に文字セットを指定します。-1が返されるまで、char []バッファに読み込むループを開始します(たとえば1024または2048の文字)。各繰り返しで、読み込まれた内容をcharバッファにStringBuilderに追加し、StringBuilderの内容を返します。 –

0

テキストファイルの長さに初期化しませんか?また、バイトではなく、charを使用したいのですか?

はい、はい...その他の回答によると、いくつかのエラーがある例を選択しました。

しかし、理論的な問題があります。バイト長バッファではなく文字バッファを使用して、バッファ長をファイル長に設定します。問題は、ファイルサイズがバイト単位で測定されますが、バッファーのサイズは文字単位で測定する必要があることです。これは正常ですが、理論的にはとなります。ファイルサイズよりも多くの文字が必要です。例えば入力ファイルが6ビット文字セットを使用し、4バイトを3バイトにパックした場合。

+0

JBNizetのリンクのCharacter Streamsに関するセクションを読んだが、assetstream.open( "3500LineTextFile.txt")がcharstreamではなくbytestreamを返すので、FileWriterを使用して入力ストリームを読むことができないようだ。それで、私は文字を使うことができないのですか? – b10hazard

+0

ファイルにテキストを書き込むためにFileWriterが使用されます。入力ストリームから文字を読み込みたいとします。これはInputStreamReaderのためのものです。 –