将文件或byte []转换为JAVA中的BLOB

Abl*_*lia 2 java arrays sqlite blob file

我正在将一个文件从客户端发送到服务器并像这样接收它:

            //Receive File:
            FileOutputStream fis = new FileOutputStream("receivedTest");
            DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
            int count;
            byte[] buffer = new byte[4096];
            while ((count = dis.read(buffer)) > 0)
            {
              fis.write(buffer, 0, count);
            }
            fis.close();
Run Code Online (Sandbox Code Playgroud)

就像它在这个主题中解释的那样.它运作良好.但事实是,我真的不想收到文件本身; 我想要一个BLOB.我已经读过BLOB就像一个byte [].

在我的数据库类(我使用SQLite)中,我有下表:

    String sqlFile = "CREATE TABLE IF NOT EXISTS files (\n"
            + " id integer PRIMARY KEY,\n"
            + " shorthash byte[],\n"
            + " filename text NOT NULL,\n"
            + " file blob,\n"
            + " owner text\n"
            + ");";
Run Code Online (Sandbox Code Playgroud)

和以下函数插入一个新的"文件":

public void insertFile(byte[] shorthash, String filename, byte[] file, String owner) {
    String sql = "INSERT INTO files(shorthash,filename, file, owner) VALUES(?,?,?,?)";

    try (Connection conn = DriverManager.getConnection(url);
            PreparedStatement pstmt = conn.prepareStatement(sql)) {
        pstmt.setBytes(1, shorthash);
        pstmt.setString(2, filename);
        pstmt.setBytes(3, file);
        pstmt.setString(4, owner);
        pstmt.executeUpdate();
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,有4列,文件本身位于第3列.在表中,它被声明为BLOB,但是当我插入它时,我只是在做一个setBytes.我不确定这是不对的,这正是我在互联网上发现的.

所以,我在我的服务器上收到这个文件,我想将它存储在我的数据库中.如果可能的话,我想避免在服务器端创建文件(行FileOutputStream fis = new FileOutputStream("receivedTest");在我的第一个代码中).我想将它直接存储在数据库中,因为我将其作为字节数组接收,我认为这样会更容易.

但我不知道该怎么做.可能是因为我并不真正理解Blob和byte []之间的联系.我的意思是,一个字节数组可能太小而无法容纳整个文件; 但是blob还可以.但是,要在数据库中插入文件,我插入一个字节数组.这让我不知所措.

编辑:

所以,我尝试了两件事:首先,在数据库中添加文件就像在这里完成的那样(几乎在我看来的任何地方,它总是以这种方式完成):

//Receive encrypted File:
            FileOutputStream fos = new FileOutputStream("receivedTest");
            DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
            int count;
            byte[] buffer = new byte[4096];
            while ((count = dis.read(buffer)) > 0)
            {
              fos.write(buffer, 0, count);
            }
            fos.close();

            DB.insertFile(shorthash, "test", "receivedTest", user);

//Insert file in DB:
public void insertFile(byte[] shorthash, String filename, String filepath, String owner) throws FileNotFoundException {
    String sql = "INSERT INTO files(shorthash, filename, file, owner) VALUES(?, ?, ?, ?)";
    try (Connection conn = DriverManager.getConnection(url);
            PreparedStatement pstmt = conn.prepareStatement(sql)) {
        pstmt.setBytes(1, shorthash);
        pstmt.setString(2, filename);

        File file = new File(filepath);
        FileInputStream   fis = new FileInputStream(file);
        pstmt.setBinaryStream(3, fis, (int) file.length());
        pstmt.execute();
        pstmt.setString(4, owner);
        pstmt.executeUpdate();
        fis.close()
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    }
}
Run Code Online (Sandbox Code Playgroud)

其次,将文件作为字节数组插入(但不适用于大文件),如SQLite教程中所述:

//Insert file in DB:
public void insertFile(byte[] shorthash, String filename, String filepath, String owner) throws FileNotFoundException {
    String sql = "INSERT INTO files(shorthash, filename, file, owner) VALUES(?, ?, ?, ?)";
    try (Connection conn = DriverManager.getConnection(url);
            PreparedStatement pstmt = conn.prepareStatement(sql)) {
        pstmt.setBytes(1, shorthash);
        pstmt.setString(2, filename);

        File file = new File(filepath);
        FileInputStream   fis = new FileInputStream(file);    
        byte[] buffer = new byte[1024];
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        for (int len; (len = fis.read(buffer)) != -1;)
            bos.write(buffer, 0, len);
        fis.close()
        pstmt.setBytes(3, bos.toByteArray());
        pstmt.execute();
        pstmt.setString(4, owner);
        pstmt.executeUpdate();
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,当我打印我的数据库时,其中没有文件.如果我尝试使用数据库浏览器打开数据库,则相同.控制台只说:

Connection to SQLite has been established. 
ouverture du server
Clients:

1   admin   admin

Files:
Run Code Online (Sandbox Code Playgroud)

Joe*_*e W 6

A byte[]和BLOB只是讨论任意二进制数据集的两种不同方式.在Java中,a byte[]是二进制数据的集合.在数据库中,BLOB代表二进制大对象,并且是相同的.只是二进制数据的集合.

因此,根据参考框架,它们具有不同的名称是相同的.因此,当您将其存储byte[]在blob列中时,您只是将这些字节从Java推送到数据库中.然后当你读回它们时,如果你愿意,可以将它们变回一个对象,因为数据库没有改变它们.它只是直接存储二进制信息.

您会发现,如果您从其他地方编写了一个blob,除非您知道存储的二进制数据的编码和字节顺序,否则您可能无法将其转换为对象.

如果您的文件太大而无法存储在单个文件中,byte[]或者您希望优化使用内存进行存储的方式,则可以使用a Stream将数据发送到数据库,而无需同时将其全部保存在内存中.

最后,如果你需要将你FileInputStream变成字节,你可以像这样使用Apache Commons IO:

byte[] bytes = IOUtils.toByteArray(fis);

然后存储您的文件.