我正在将 jpeg 图像插入到我的 UTF-8 编码的 Postgres 数据库中的 bytea 列中。我正在使用准备好的 sql 语句来插入图像。在语句中,我在 Java 中创建了一个 jpeg 图像的文件对象,然后将其作为 FileInputStream 传递给 setBinaryStream 方法。但是,一旦执行语句,我的 Java 应用程序就会时不时地抛出异常,指出:
“错误:编码“UTF8”的无效字节序列:0x84”
这种情况发生在少数几张奇怪的图片上。这些图像是从先前的一组图像中提取的,所有先前的图像都插入得很好,只有少数提取的图像似乎会导致错误。那么我该如何解决这样的问题呢?可以以某种方式将字节流编码为 UTF-8 吗?还是数据库有问题?
顺便说一句,如果我用新图像替换提取的图像并将它们另存为 jpeg,则会发生相同的错误。感谢您的帮助!
代码如下...
缺少一些代码,否则这会很长,但基本上我对路径和目录名称进行了一些检查,以确保它们符合文件系统规则。这是在遍历所有子目录并添加所有 这些子目录中的 jpeg 文件。然后我转到下一个目录,其中包含带有图像的子目录,直到那里没有图像。我还没有添加 try-catches 和日志记录部分。
String imgStr = image.toString();
int age = getAgeFromDir(imgStr);
String gender = getSexFromDir(imgStr);
String table = "";
switch(validIdx){
case 0: table = "carpals";
break;
case 1: table = "d_phalanges";
break;
case 2: table = "p_phalanges";
break;
case 3: table = "i_phalanges";
break;
case 4: table = "epiphyses";
break;
case 5: table = "sesamoids";
break;
case 6: table = "metacarpals ";
break;
}
PreparedStatement ps = con.prepareCall("INSERT INTO " + table +
" VALUES( (SELECT hands.hand_id FROM hands WHERE hands.age = " + age + " AND hands.gender = '" + gender + "' AND hands.location = '" + path + directory + imageNames[i] + "' )," +
" (SELECT COUNT(" + table + ".location) FROM " + table + " ), " +
" ?, ? )" );
//go through each sub-directory which contains jpeg images and add them to
//the database
File sublist = new File(image + "\\" + subdir[j]);
String[] files = sublist.list();
String[] pics = sublist.list(new JpegFilter());
if(files.length > pics.length){
//WRITE TO LOG
//WARNING UNEXPECTED FILES OR DIRECTORIES FOUND IN....
}
for(int r = 0; r < pics.length; r++ ){
String location = image + "\\" + subdir[j] + "\\" + pics[r];
System.out.println(i + "\t" + r + " location : " + location);
File f = new File(location);
FileInputStream pic = new FileInputStream(f);
if(f.isFile()){
ps.setString(2, location);
ps.setBinaryStream(1, pic, (int)f.length());
ps.execute();
pic.close();
}
}
ps.close();
抛出的 SQLException 如下所示,它是在 ps.execute() 处抛出的:
线程“main”中的异常 org.postgresql.util.PSQLException:错误:编码“UTF8”的字节序列无效:0x84 在 org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1608) 在 org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1343) 在 org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:194) 在 org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:451) 在 org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:350) 在 org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:343) 在 nuffielddb.HandDB.addExtractedImages(HandDB.java:406) 在 nuffielddb.Main.main(Main.java:37) Java 结果:1
最佳答案
嗯,0x84 不是有效的 utf8 字符:
=> perl -e 'print "\x84"' | iconv -f utf8 -t utf8
iconv: illegal input sequence at position 0
通常 - bytea 可以处理任何字节,但 INSERT 语句是文本字符串,因此必须符合客户端的编码!
插入数据的简单方法:
- 将应用程序中的数据编码为 Base64 格式(还有其他选项,但我最容易展示这个)
- 插入:INSERT INTO q (x) VALUES (decode(?, 'base64'))
Perl 示例(抱歉,我不会写 Java):
#!/usr/bin/perl
use MIME::Base64;
use DBI;
my $dbh = DBI->connect( "dbi:Pg:dbname=depesz;port=5840", "depesz" );
my $blob = "\x84";
my $encoded = encode_base64( $blob );
$dbh->do("INSERT INTO q (x) VALUES (decode(?, 'base64'))", undef, $encoded );
q 表是:
Table "public.q"
Column | Type | Modifiers
--------+-------+-----------
x | bytea |
数据(插入后)如下所示:
# select x, octet_length(x) from q;
x | octet_length
------+--------------
\x84 | 1
(1 row)
关于java - 通过 Java 插入图像时 Postgres 编码 "UTF8"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1266707/