Java 数据库中的编码问题

Java 数据库中的编码问题,java,postgresql,jdbc,encoding,Java,Postgresql,Jdbc,Encoding,我有一个Postgres9.2数据库,编码是UTF-8。 我有一个应用程序(用java编写)来更新这个数据库,读取.sql文件并在数据库中执行它们。 但我发现了一个问题: 在其中一个.sql文件中,我有以下说明: insert into usuario(nome) values('Usuário Padrão'); 执行此操作后,当我转到表数据时,插入的内容是:“UsuÃrio PadrÃo” 如果我直接从pgAdmin执行此命令,它将正确创建。 所以我不知道这是数据库中的问题,还是执行脚本的

我有一个Postgres9.2数据库,编码是UTF-8。 我有一个应用程序(用java编写)来更新这个数据库,读取.sql文件并在数据库中执行它们。 但我发现了一个问题: 在其中一个.sql文件中,我有以下说明:

insert into usuario(nome)
values('Usuário Padrão');
执行此操作后,当我转到表数据时,插入的内容是:
“UsuÃrio PadrÃo”

如果我直接从pgAdmin执行此命令,它将正确创建。 所以我不知道这是数据库中的问题,还是执行脚本的程序中的问题

---编辑---

以下是如何获得JDBC连接:

public static Connection getConnection() throws SQLException{
    Connection connection;
    String url="jdbc:postgresql://"+servidor+":"+porta+"/"+nomeBanco;
    Properties props = new Properties();  
    props.put("user", usuario);  
    props.put("password", senha);
    connection=DriverManager.getConnection(url,props);
    connection.setAutoCommit(false);
    return connection;
}
这是我用来读取文件的代码,但这看起来是正确的,因为如果我打印从文件读取的字符串,它会显示正确的字符串

public static String lerArquivo(File arquivo){
    StringBuilder conteudo=new StringBuilder();
    BufferedReader br = null;
    try {
        br=new BufferedReader(new FileReader(arquivo));
        String linha;
        while((linha=br.readLine())!=null){
            conteudo.append(linha).append("\n");
        }
    } catch (IOException e) {
        FrameErroBasico f=new FrameErroBasico(null, true);
        f.setText("Erro ao ler arquivo.",e);
        f.setVisible(true);
    }finally{
        try{br.close();}catch(Exception e){}
    }
    return conteudo.toString();
}

为了确保我需要查看读取中SQL文件的代码,但是(正如jtahlborn所指出的)我要说的是,您读取的文件使用的是一种编码,而不是它实际使用的编码

PgJDBC在Java端使用Unicode,并通过始终以utf-8与服务器通信来处理客户机/服务器编码差异,从而允许服务器执行任何所需的编码转换。因此,除非您通过PgJDBC连接设置
client_encoding
(PgJDBC试图检测并警告您的内容),否则问题不会出现在PostgreSQL/PgJDBC端,而是错误读取文件

具体地说,该文件看起来是utf-8编码的,但您正在读取它,就好像它是拉丁语-1(ISO-8859-1)编码的一样。见证Python中的这个简单演示,通过将本地Unicode字符串转换为utf-8,然后像解码拉丁语-1一样对其进行解码,来复制您得到的结果:

>>> print u'Usuário Padrão'.encode("utf-8").decode("latin-1");
Usuário Padrão
您的应用程序很可能将文件读入
字符串
,执行不适当的文本编码转换,将文件编码转换为Java内部使用的unicode文本。没有可靠的方法“自动检测”文件编码,因此在读取文件时必须指定输入的文本编码。如果您知道文件的编码,您应该


您没有显示读取文件的代码,因此很难更具体地说明,但这实际上是Java方面的问题,而不是PostgreSQL方面的问题。如果您
System.out.println
您的SQL文件来自Java,您将看到它在发送到数据库服务器之前已经在Java字符串中损坏了。

为了确保我需要查看读取SQL文件的代码,但是(正如jtahlborn所指出的)我想说你是在用一种编码读取文件,而不是它真正的编码

PgJDBC在Java端使用Unicode,并通过始终以utf-8与服务器通信来处理客户机/服务器编码差异,从而允许服务器执行任何所需的编码转换。因此,除非您通过PgJDBC连接设置
client_encoding
(PgJDBC试图检测并警告您的内容),否则问题不会出现在PostgreSQL/PgJDBC端,而是错误读取文件

具体地说,该文件看起来是utf-8编码的,但您正在读取它,就好像它是拉丁语-1(ISO-8859-1)编码的一样。见证Python中的这个简单演示,通过将本地Unicode字符串转换为utf-8,然后像解码拉丁语-1一样对其进行解码,来复制您得到的结果:

>>> print u'Usuário Padrão'.encode("utf-8").decode("latin-1");
Usuário Padrão
您的应用程序很可能将文件读入
字符串
,执行不适当的文本编码转换,将文件编码转换为Java内部使用的unicode文本。没有可靠的方法“自动检测”文件编码,因此在读取文件时必须指定输入的文本编码。如果您知道文件的编码,您应该


您没有显示读取文件的代码,因此很难更具体地说明,但这实际上是Java方面的问题,而不是PostgreSQL方面的问题。如果您
System.out.println
您的SQL文件来自Java,您将看到它在发送到数据库服务器之前已经在Java字符串中损坏了。

这很可能是有问题的一行:

    br=new BufferedReader(new InputStreamReader(new FileInputStream(arquivo), "UTF-8"));

(看起来我的水晶球仍然工作正常!)

这很可能是有问题的一行:

    br=new BufferedReader(new InputStreamReader(new FileInputStream(arquivo), "UTF-8"));

(看起来我的水晶球仍然工作正常!)

正如jtahlborn所说,读取文件的正确方法如下:

br=new BufferedReader(new InputStreamReader(new FileInputStream(arquivo),"UTF-8"));

这就是我的问题,像这样做,它就像一个符咒。

正如jtahlborn所说,正确的读取文件的方法如下:

br=new BufferedReader(new InputStreamReader(new FileInputStream(arquivo),"UTF-8"));

这是我的问题,像这样做,效果很好。

我们怎么知道?我们应该猜猜您的java代码是什么样子吗?盯着我的水晶球,我敢打赌你的java代码没有使用显式字符编码打开sql脚本文件。检查你的应用程序在创建DB会话时设置了什么客户端编码。对不起,我忘了水晶球的事情了。。。我用我用来获取连接的代码更新了我的问题。在同一个会话中显示从哪里读取sql脚本的代码运行
show client_encoding
,以获得有关实际设置的确切信息。我们怎么知道?我们应该猜猜您的java代码是什么样子吗?盯着我的水晶球,我敢打赌你的java代码没有使用显式字符编码打开sql脚本文件。检查你的应用程序在创建DB会话时设置了什么客户端编码。对不起,我忘了水晶球的事情了。。。我用我用来获取连接的代码更新了我的问题。显示在同一会话中阅读sql脚本的代码运行
show client_encoding
,以获得有关实际设置的明确信息。非常详细的描述,基本上与我的第一条评论相同。不幸的是,OP没有显示相关的代码。@jtahlborn向不理解他们的人解释事情是这个网站的重要组成部分,不是吗?确实如此。我的评论不一定是批评,但是,这一切都只是一个在黑暗中没有rele的镜头