2

コードを実行しようとすると、java.lang.OutOfMemoryError:Javaヒープスペースが発生します。ただし、特定のインスタンスでストリームを閉じるとエラーはなくなりますが、ストリームが途中で閉じられるため、データが失われます。

私はJavaに非常に慣れていないので、ストリームの管理方法をはっきりと理解していません。ストリームをいつどのように閉じる必要がありますか?

private void handleFile(File source)
{
    FileInputStream fis = null;

    try
    {
        if(source.isFile())
        {
            fis = new FileInputStream(source);
            handleFile(source.getAbsolutePath(), fis);
        }
        else if(source.isDirectory())
        {
            for(File file:source.listFiles())
            {
               if(file.isFile())
               {
                   fis = new FileInputStream(file);
                   handleFile(file, fis);
               }
               else
               {
                   handleFile(file);
               }
            }
         }
     }
     catch(IOException ioe)
     {
         ioe.printStackTrace();
     }
     finally
     {
         try
         {
             if(fis != null) { fis.close(); }
         }
         catch(IOException ioe) { ioe.printStackTrace(); }
     }
}

private handleFile(String fileName, InputStream inputStream)
{
    try
    {
       byte[] initialBytes = isToByteArray(inputStream);
       byte[] finalBytes = initialBytes;

       if(initialBytes.length == 0) return;

       if(isBytesTypeB(initialBytes))
       {
          finalBytes = getBytesTypeB(startingBytes);
       }
       // Other similar method checks
       // .....

       map.put(fileName, finalBytes);
     }
     catch(IOException ioe)
     {
         ioe.printStackTrace();
     }
}

private byte[] isToByteArray(InputStream inputStream)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];

    int nRead;
    while((nRead = inputStream.read(buffer)) != -1)
    {
        baos.write(buffer, 0, nRead);
    }
    return baos.toByteArray();
 }

 private boolean isBytesTypeB(byte[] fileBytes)
 {
     // Checks if these bytes match a particular type
     if(BytesMatcher.matches(fileBytes, fileBytes.length))
     {
         return true;
     }
     return false;
 }

 private byte[] getBytesTypeB(byte[] fileBytes)
 {
     //decompress bytes

     return decompressedBytes;
 }
4

1 に答える 1

2

まず、メモリ内のストリーム全体を読み取らないでください。読み取りおよび書き込み時にバッファーを使用します。

ByteArrayInputStreamandByteArrayInputStreamは、非常に小さなストリーム (一部の操作でデータを再利用する必要がある) を読み取ることが確実であり、データをメモリに保持することが本当に理にかなっている場合にのみ使用してください。そうしないと、すぐに (または予期せずに) メモリ不足になります。

try-catch ブロックの外側でストリームを定義し、finally ブロックでそれらを閉じます (null でない場合)。例えば:

void doSomeIOStuff() throws IOException
{
    InputStream is = null;

    try
    {
        is = new MyInputStream(...);
        // Do stuff
    }
    catch (IOException ioExc)
    {
        // Either just inform (poor decision, but good for illustration):
        ioExc.printStackTrace();
        // Or re-throw to delegate further on:
        throw new IOException(ioExc);
    }
    finally
    {
        if (is != null)
        {
            is.close();
        }
    }
}

このようにして、リソースは使用後に常に適切に閉じられます。

好奇心から、handleFile(...)メソッドは実際に何をすべきでしょうか?

于 2013-02-27T16:07:14.350 に答える