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

标签 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;
 }

最佳答案

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

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

在 try-catch block 外部定义流并在 finally block 中关闭它们(如果它们不为 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(...) 应该做什么?方法到底是做什么的?

关于java - 如何管理字节流以及何时关闭流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15116424/

相关文章:

java - 基于输入字段的微调器

c# - File.ReadAllText 线程安全吗?

Java:输入流/输出流的默认值?

java - 使用 java 在 sqlite SELECT 中的列之间添加逗号和空格

java - 如何在 JBoss7.1 中使用 Infinispan 查询

java - 从 Java Swing 读取文件

java - 是否可以在 Java 中生成动态 InputStream?

java - 为什么 android HttpURLConnection 缓存输入流结果?

Java 结构 - 是否需要嵌套 try 语句?

c# - 如何有效地使用内存附加到 C# 中的大型 XML 文件