如何管理字节流以及何时关闭流

时间:2013-02-27 15:52:42

标签: java file-io inputstream out-of-memory

我遇到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;
 }

1 个答案:

答案 0 :(得分:2)

首先,不要读取内存中的整个流。在阅读和写作时使用缓冲区。

仅当您确定要阅读非常小的数据流(其数据需要重新用于某些操作)时才使用ByteArrayInputStreamByteArrayInputStream,并且确实有意义保留内存中的数据。否则,您将很快(或意外)耗尽内存。

在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(...)方法应该做什么?