使用java获取存在SQL server数据库中的image类型的二进制数据,出现有的文件乱码有的文件正常?

**使用java获取存在SQL server数据库中的image类型的二进制数据,出现有的文件乱码有的文件正常?


请大家把我描述的问题,还有相关内容 和代码都看一遍,再回答

这个数据库中字段的属性

img

java代码

img

指定字符集的方法,我已经把这里的所有字符编码全部试了一遍了,还是一样的有问题

img

数据库版本sqlserver2001版本的
能解决我再打赏66

编码问题:在将二进制数据转换为字符串时,需要确保使用正确的字符编码。常见的字符编码包括 UTF-8、ISO-8859-1 等。请确保使用与存储数据时相同的编码进行解码。

数据格式问题:image 类型存储的是二进制数据,可能包含任意字节。如果你尝试将其直接转换为字符串,可能会导致乱码或丢失部分数据。应该将其作为字节数组处理,而不是字符串。

二进制文件里有乱码是很正常的,关键是,你读取后还原成图片流或者写入文件,是否和原始数据一样,图片能不能显示,二进制文件能不能打开

这篇博客介绍了几种处理乱码的方法:

第一种方法应该是没问题的
可以先找个正常的文件,上传到数据库之后再用java输出乱码文件,比较两个文件的大小,
或者比较它们的二进制内容(如Beyond Compare),看看有没有什么特征。

你试试这样转化呢?

img


// 使用适当的字符编码进行转换
String encodedImageData = new String(imageData, "UTF-8");

// 进一步处理转换后的数据
。。。。

这是从一个类似问题的实例上跑通的代码示例,你看看对你有没有帮助:

import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.sql.Connection;  
import java.sql.DriverManager;  
import java.sql.PreparedStatement;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
  
public class SQLServerImageBinaryData {  
  
    public static void main(String[] args) {  
        String url = "jdbc:sqlserver://localhost:1433;databaseName=yourDatabaseName";  
        String username = "yourUsername";  
        String password = "yourPassword";  
  
        try (Connection conn = DriverManager.getConnection(url, username, password)) {  
            String sql = "SELECT ImageColumn FROM YourTable WHERE ID = ?";  
            PreparedStatement statement = conn.prepareStatement(sql);  
            statement.setInt(1, 1); // Set parameter for ID  
  
            ResultSet result = statement.executeQuery();  
            if (result.next()) {  
                InputStream inputStream = result.getBinaryStream("ImageColumn");  
                byte[] imageData = new byte[inputStream.available()];  
                inputStream.read(imageData);  
  
                // Save the binary data to a file  
                try (FileOutputStream outputStream = new FileOutputStream("output.bin")) {  
                    outputStream.write(imageData);  
                }  
            }  
        } catch (SQLException | IOException e) {  
            e.printStackTrace();  
        }  
    }  
}

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答由chatgpt基于相关博客总结生成:

    解决方案

    1. 从SQL Server数据库中获取二进制数据的方法是使用ResultSet对象的getBinaryStream方法。通过此方法可以获取一个InputStream对象,然后可以将其转换为字节数组并保存到文件中。下面是一个示例代码:

    ```java // 连接数据库并执行查询 Connection connection = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=mydatabase", "username", "password"); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT file_data FROM mytable WHERE id = 1");

    // 获取二进制数据流 if (resultSet.next()) { InputStream inputStream = resultSet.getBinaryStream("file_data"); byte[] buffer = new byte[1024]; int length; FileOutputStream outputStream = new FileOutputStream("file.jpg"); while ((length = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, length); } outputStream.close(); inputStream.close(); }

    // 关闭数据库连接 resultSet.close(); statement.close(); connection.close(); ```

    在上面的代码中,首先建立与数据库的连接,并执行查询语句。然后使用getBinaryStream方法获取二进制数据的输入流。接下来,将二进制数据写入文件中。最后,关闭输入流、输出流和数据库连接。

    1. 如果上述的方法仍然出现乱码问题,可以尝试使用字符编码来解决。在读取二进制数据之前,将数据库连接的字符编码设置为正确的编码。以下是示例代码:

    ```java // 连接数据库并设置字符编码 Connection connection = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=mydatabase;characterEncoding=utf8", "username", "password"); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT file_data FROM mytable WHERE id = 1");

    // 获取二进制数据流 // ...

    // 关闭数据库连接 resultSet.close(); statement.close(); connection.close(); ```

    在上面的代码中,在连接数据库时通过在URL中加入characterEncoding=utf8参数将字符编码设置为UTF-8。这样可以确保在获取二进制数据时不会出现乱码问题。

    1. 如果你使用的是SQL Server 2001版本的数据库,并且无法通过上述方法解决乱码问题,可以尝试使用getBytes方法将二进制数据转换为字节数组,然后使用String的构造函数将字节数组转换为字符串。以下是示例代码:

    ```java // 连接数据库并执行查询 Connection connection = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=mydatabase", "username", "password"); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT file_data FROM mytable WHERE id = 1");

    // 获取二进制数据,并转换为字符串 if (resultSet.next()) { byte[] fileData = resultSet.getBytes("file_data"); String content = new String(fileData, "UTF-8"); System.out.println(content); }

    // 关闭数据库连接 resultSet.close(); statement.close(); connection.close(); ```

    在上面的代码中,首先建立与数据库的连接,并执行查询语句。然后使用getBytes方法将二进制数据转换为字节数组,再使用String的构造函数将字节数组转换为字符串。

    以上是解决问题的几种可能方案,请根据具体情况选择合适的方法。希望能够帮助你解决问题。如果还有其他问题,请随时提问。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

二进制正常情况下就是乱码的

img

import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.*;

public class ImageDataRetrieve {

    public static void main(String[] args) {
        String connectionUrl = "jdbc:sqlserver://your_server_name:1433;databaseName=your_database_name;user=your_username;password=your_password";

        try (Connection connection = DriverManager.getConnection(connectionUrl);
             Statement statement = connection.createStatement()) {

            // 查询语句获取二进制数据
            String sql = "SELECT image_column FROM your_table_name WHERE your_condition";
            try (ResultSet resultSet = statement.executeQuery(sql)) {
                while (resultSet.next()) {
                    // 从结果集中获取二进制数据
                    byte[] imageData = resultSet.getBytes("image_column");

                    // 将二进制数据写入文件
                    String filePath = "path/to/your/file.jpg";
                    try (FileOutputStream fos = new FileOutputStream(filePath)) {
                        fos.write(imageData);
                    }

                    System.out.println("Image data written to file: " + filePath);
                }
            }
        } catch (SQLException | IOException e) {
            e.printStackTrace();
        }
    }
}

上述代码中使用 resultSet.getBytes("image_column") 方法从结果集中获取二进制数据,并使用字节流 FileOutputStream 将数据写入到文件中,确保数据不会被错误地编码或解码。

如果上述方法仍然导致某些文件出现乱码,可能需要进一步检查数据的存储和读取方式,确保数据在存储和读取过程中没有被修改或破坏。

两个问题

第一个是别用输入流,用getBytes取代getBinaryStream

第二个是用FileOutputStream取代DataOutputStream

DataOutputStream是用来处理文本数据的,有可能会对二进制数据有影响

参考
(1) java对sqlserver的image字段读取和存储 https://blog.csdn.net/weixin_43882190/article/details/114750288
(2) 怎么用JAVA向sqlserver写入image类型 https://blog.csdn.net/erhuo_594/article/details/121792160

参考gpt:
结合自己分析给你如下建议:
下几种方法来获取image类型的数据:
使用JDBC来连接SQL server数据库并读取image数据,然后使用ImageIO类将image数据写入到文件中。例如:

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection conn = DriverManager.getConnection("数据库连接字符串", "用户名", "密码");
String sql = "select image字段名 from 表名 where 条件";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
  byte[] content = rs.getBytes("image字段名");
  ImageIO.write(ImageIO.read(new ByteArrayInputStream(content)), "jpg", new File("文件路径"));
}

使用Spring框架中的JdbcTemplate类来连接SQL server数据库并读取image数据,然后使用FileOutputStream类将image数据写入到文件中。例如:

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql = "select image字段名 from 表名 where 条件";
byte[] content = jdbcTemplate.queryForObject(sql, byte[].class);
FileOutputStream fos = new FileOutputStream("文件路径");
fos.write(content);
fos.close();
使用SQL server自带的函数模块GUI_UPLOAD和ZBC_FM_FILE_DOWNLOAD来上传和下载image数据,然后使用FileInputStream和FileOutputStream类来读写文件。例如:
//上传文件
Connection conn = DriverManager.getConnection("数据库连接字符串", "用户名", "密码");
String sql = "update 表名 set image字段名 = ? where 条件";
PreparedStatement ps = conn.prepareStatement(sql);
File file = new File("文件路径");
FileInputStream input = new FileInputStream(file);
ps.setBinaryStream(1, input, (int) file.length());
ps.executeUpdate();
ps.close();
input.close();

//下载文件
Connection conn = DriverManager.getConnection("数据库连接字符串", "用户名", "密码");
Statement stmt = conn.createStatement();
ResultSet rs;
String sql = "select image字段名 from 表名 where 条件";
InputStream in = null;
rs = stmt.executeQuery(sql);
while (rs.next()) {
  DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("文件路径")));
  in = rs.getBinaryStream("image字段名");
  int len = 0;
  byte[] b = new byte[1024];
  while ((len = in.read(b)) != -1) {
    dos.write(b, 0, len);
  }
  dos.close();
  in.close();
}
rs.close();