BufferedInputStream 到 byte[] 以通过 Socket 发送到数据库

Posted

技术标签:

【中文标题】BufferedInputStream 到 byte[] 以通过 Socket 发送到数据库【英文标题】:BufferedInputStream into byte[] to be send over a Socket to a Database 【发布时间】:2012-05-25 10:50:14 【问题描述】:

我一直在寻找这个问题的答案,但实际上找不到任何东西。今天早些时候,我问我如何通过字节数组将文件变成字符串,然后再返回,以便稍后检索。

人们告诉我,我必须只存储字节数组,以避免讨厌的编码问题。所以现在我已经开始着手解决这个问题了,但我现在碰壁了。

基本上,我以前使用无缓冲流将文件转换为字节数组。这在理论上很有效,但它会占用大量内存,最终会抛出堆大小异常。我应该改用缓冲流(或者我被告知),我现在遇到的问题是从 BufferedInputStream 到 byte[]。我尝试复制和使用本文档中的方法

http://docs.guava-libraries.googlecode.com/git/javadoc/index.html?com/google/common/io/package-summary.html

我将无缓冲流交换为缓冲流。唯一的问题是,我不能直接将缓冲的输出流转换为字节数组,就像使用无缓冲的流一样。

帮助? :)

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public final class BufferedByteStream 

    private static final int BUF_SIZE = 1024000;

    public static long copy(BufferedInputStream from, BufferedOutputStream to) throws IOException  
        byte[] buf = new byte[BUF_SIZE];
        long total = 0;
        while(true) 
            int r = from.read(buf);
            if(r == -1) 
                break;
            
            to.write(buf, 0, r);
            total += r;
        
        return total;
    

    public static byte[] toByteArray(BufferedInputStream in) throws IOException 
        BufferedOutputStream out = new BufferedOutputStream(new ByteArrayOutputStream());
        copy(in, out);
        return out. // <--- Problem is here
    

编辑:

我仍然收到堆空间错误。所以我现在将发布所有代码:

main.java

import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import jserver.io.BufferedByteStream;
/**
*
* @author Vipar
*/
public class main 
    public static void main(String[] args) 
    File f = new File("<doesn't matter>");
        try 
            byte[] buf;
            try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f))) 
                buf = BufferedByteStream.toByteArray(bis);
                bis.close();
            
            File f2 = new File("<doesn't matter>");
            try (FileOutputStream fos = new FileOutputStream(f2)) 
                fos.write(buf);
                fos.close();
            
         catch (FileNotFoundException ex) 
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
         catch (IOException ex) 
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
        
    

BufferedByteStream.java

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public final class BufferedByteStream 

    private static final int BUF_SIZE = 1024000;

    public static long copy(BufferedInputStream from, BufferedOutputStream to) throws IOException  
        byte[] buf = new byte[BUF_SIZE];
        long total = 0;
        while(true) 
            int r = from.read(buf);
            if(r == -1) 
                break;
            
            to.write(buf, 0, r);
            total += r;
        
        return total;
    

    public static byte[] toByteArray(BufferedInputStream in) throws IOException 
        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
        BufferedOutputStream out = new BufferedOutputStream(bytesOut);
        copy(in, out);
        return bytesOut.toByteArray();
    

【问题讨论】:

你为什么不告诉我们你想解决什么问题,而不是问一半的解决方案有什么问题? 我本来应该现在意识到的,但我会在一个适当的问题中这样做,我只是简单地提出我想要实现的目标。 【参考方案1】:

看看 ByteArrayOutputStream: Java 7 API java.io.ByteArrayOutputStream

bytesOut = new ByteArrayOutputStream();
byte[] bytes = bytesOut.toByteArray();

更新: 如果您坚持做您正在做的事情,您可以将中间 ByteArrayOutputStream 分配给一个变量并以这种方式获取数组:

ByteArrayOutputStream bytesOut = new ByteArrayOutputStream()
BufferedOutputStream out = new BufferedOutputStream(bytesOut);
copy(in, out);
return bytesOut.toByteArray();

更新 2: 真正的问题似乎是如何在不先将文件全部读入内存的情况下复制文件:

1) 手动:

    byte[] buff = new byte[64*1024]; //or some size, can try out different sizes for performance
    BufferedInputStream in = new BufferedInputStream(new FileInputStream("fromFile"));
    BufferedOutputStream out = new BufferedOutputStream(new FileoutputStream("toFile"));
    int n = 0;
    while ((n = in.read(buff)) >= 0) 
        out.write(buff, 0, n);
    
    in.close();
    out.close();

2) 由操作系统有效且无循环等:

FileChannel from = new FileInputStream(sourceFile).getChannel();
FileChanngel to = new FileOutputStream(destFile).getChannel();
to.transferFrom(from, 0, from.size());
//or from.transferTo(0, from.size(), to);
from.close();
to.close();

3) 如果你有 Java 7,你可以简化异常和流关闭,或者只使用 java 7 中的新 API i 复制文件:

java.nio.file.Files.copy(...);

see java.nio.file.Files

【讨论】:

你不再需要缓冲了...它正在内存中构建一个数组。没有比这更缓冲的了。 但是,如果您不相信我的话(无论如何您都应该自己衡量),无论如何您都可以使用它,但将其分配给它自己的变量。我将更新示例。 我尝试通过无缓冲的流在我的计算机上制作 1.39 GB 文件的副本。它给了我“内存不足”的异常。有人告诉我缓冲流,可以解决这个问题。 我想你或对方误会了,如果是这样,那也无济于事。 您需要的是不要先将所有内容读入内存然后再写入,只需边写边写即可。意思是,不要使用 ByteArray 流。【参考方案2】:

DataFetcher 非常适合:

http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/DataFetcher.java?revision=34&view=markup

如果内存不足,可以使用 clearBuffer 清除读取之间的缓冲区

您还需要 Timeout 类 - 它位于同一个项目的同一个包中。

【讨论】:

以上是关于BufferedInputStream 到 byte[] 以通过 Socket 发送到数据库的主要内容,如果未能解决你的问题,请参考以下文章

java中讲讲BufferedInputStream的用法,举例?

文件流之字节缓冲流(BufferedInputStream BufferedOutputStream)

BufferedInputStream available() 吃 CPU

char类型数据位操作处理,清零设值取值

深入研究BufferedInputStream内幕

Java IO BufferedInputStream 和 BufferedOutputStream