xml 输出中的非拉丁字符

Posted

技术标签:

【中文标题】xml 输出中的非拉丁字符【英文标题】:nolatin characters in xml output 【发布时间】:2010-12-12 02:06:10 【问题描述】:

编辑:我硬编码了字符并使用repsonse writer来编写它,它仍然是 克尼斯堡

response.setCharacterEncoding("UTF-8"); response.setContentType(contentType); //if(contentType!=null)response.setHeader("Content-Type",contentType); Writer writer = response.getWriter();//new OutputStreamWriter(response.getOutputStream(),"UTF-8"); System.err.println("字符编码为"+response.getCharacterEncoding()); writer.write("柯尼斯堡"); writer.flush();

编辑: 我在调用 getWriter() 之前尝试了 setContentType 和 setContentEncoding,输出仍然没有区别:

如果(res.length()> 0) //pw.write(res); response.setCharacterEncoding("UTF-8"); response.setContentType(contentType); //if(contentType!=null)response.setHeader("Content-Type",contentType); Writer writer = response.getWriter();//new OutputStreamWriter(response.getOutputStream(),"UTF-8"); System.err.println("字符编码为"+response.getCharacterEncoding()); writer.write(res); writer.flush();

我正在阅读一些德语字符,然后从 java servlet 以 xml 格式输出它们, 这是我用 UTF8 读取它们的方式:

国际长度=0; 字节[]缓冲区=新字节[1024]; 输出流 os = sock.getOutputStream(); InputStream 是 = sock.getInputStream(); 查询 += "\r\n"; os.write(query.getBytes("UTF8"));//iso8859_1")); 做 len = is.read(buffer); 如果(长度> 0) if(outstring==null)outstring=new StringBuffer(); outstring.append(new String(buffer,0,len, "UTF8")); while(len>0); System.out.println(outstring);

System.out 正确输出字符串: 柯尼斯堡

但是,当我也使用 charset=UTF-8 从我的 servletResponse 重新传输此字符串时 它变得狼吞虎咽:K�nigsberger

private void outputResponse(String res, HttpServletRequest 请求, HttpServletResponse 响应)抛出 IOException 字符串 outputFormat = getOutputFormat(request); 字符串内容类型=空; PrintWriter pw = response.getWriter(); //response.setCharacterEncoding("UTF-8"); System.err.println("输出"+res); 内容类型=“文本/xml;字符集=UTF-8”; res="" + res; if(contentType!=null)response.setHeader("Content-Type",contentType); 如果(res.length()> 0) pw.write(res); pw.flush();

【问题讨论】:

指定操作系统/平台。什么是“repipe”以及如何“repipe”? os 是窗口。通过 repipe 我只是指从 Servlet 输出它 【参考方案1】:
do
  len = is.read(buffer);
  if (len>0)  
    if(outstring==null) outstring=new StringBuffer();
    outstring.append(new String(buffer,0,len, "UTF8"));
  
while(len>0);

这不是解码 UTF-8 的好方法,因为字符可能会在缓冲区边界上损坏 (details here)。 UTF-8 是一种可变宽度编码,因此字符需要一到四个字节来存储。如果它起作用了,那你就走运了。最好使用 Reader/Writer 类 (details here) 进行编码和解码。

我相信您需要先致电setContentType 或setCharacterEncoding,然后再致电getWriter。我觉得直接打电话给setHeader是不够的。


此 servlet 代码将正确编码示例字符串并将其作为 UTF-8 数据传输:

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException 
    response.setContentType("text/xml; charset=UTF-8");
    PrintWriter pw = response.getWriter();
    pw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    pw.write("<data>K\u00F6nigsberger</data>");
    pw.flush();
    pw.close();
  

请注意,我使用转义序列 \u00F6 来发出字符 U+00F6 (ö) 以确保我不会在我的文本编辑器中或在编译过程中损坏字符( see here for more details)。

数据是否可能在客户端被误解?使用十六进制编辑器检查输出。

编码为UTF-8,"K\u00F6nigsberger"应该变成字节序列:

4b c3 b6 6e 69 67 73 62 65 72 67 65 72

...字符 U+00F6 (ö) 变为 c3 b6。您可以使用这样的代码来检查您的值:

  public static void main(String[] args) throws IOException 
    String konigsberger = "K\u00F6nigsberger";
    dumpHex(System.out, konigsberger.getBytes("UTF-8"));
  

  private static void dumpHex(PrintStream out, byte[] data) 
    for (byte b : data) 
      out.format("%02x ", b);
    
    out.println();
  

【讨论】:

我怀疑这是一个 xml 格式问题,而不是 unicode 编码。我使用了代码 pw.write("K\u00F6nigsberger");当我在浏览器中查看它时,字符仍然被损坏......【参考方案2】:

您应该按照示例并让 servlet response 了解要遵循的结束编码:

response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("UTF-8");
ServletOutputStream out =response.getOutputStream();
out.write(output.getBytes("UTF-8"));    

【讨论】:

【参考方案3】:

你总是可以使用这样的实体:

<test>
&#228;
&#252;
&#229;
</test>

得到:

<test>
ä
ü
å
</test>

也许不完全是你想要的,但一个很好的解决方法。您可以使用utf8-chartable.de 之类的网站来查找所需的值。

【讨论】:

这输出de字符很好,有没有办法将这些de字符转换成这些xml代码? 我的意思是有一个java api可以直接在java中进行转换吗? @unknown (google):没有 Java API 可以自动创建这些实体。有关如何执行此操作的示例,请参见此答案:***.com/questions/1273986/… 我不确定,是否有图书馆。 Commons lang StringEscapeUtils 怎么样。有一个 escapeXml 方法,看起来很有希望:commons.apache.org/lang/api/org/apache/commons/lang/…【参考方案4】:

我也遇到了同样的问题。我刚刚做了以下事情,它工作正常:

byte[] k =xml.getBytes(UTF8_CHARSET); // xml is the string with unicode content.  getBytes("UTF-16") encodes given String into a sequence of bytes and returns an array of bytes. you can use xml.getBytes(UTF-16); for utf-16 encoding

response.setContentType("text/xml");
response.setContentLength(k.length);
response.getOutputStream().write(k);
response.getOutputStream().flush();
response.getOutputStream().close();

【讨论】:

以上是关于xml 输出中的非拉丁字符的主要内容,如果未能解决你的问题,请参考以下文章

P3649 [APIO2014]回文串(回文树)

[APIO2014]回文串

bzoj3676[Apio2014]回文串 回文自动机

bzoj 3676: [Apio2014]回文串

BZOJ3676: [Apio2014]回文串

bzoj3676 [Apio2014]回文串