【问题标题】:Google AppEngine - How to set default Charset / file-encoding (to UTF-8) for Google AppEngineGoogle AppEngine - 如何为 Google AppEngine 设置默认字符集/文件编码(到 UTF-8)
【发布时间】:2017-05-03 11:06:21
【问题描述】:

情况

我正在使用AppEngine Cloud Endpoints (Java) 作为我的 Android 应用程序的后端服务器。在 Cron-Job 中,服务器会定期下载新数据(字符串),过滤掉相关信息并通过 Firebase 云消息传递到不同的主题(通过将 HTTP-Request 发布到 https://fcm.googleapis.com/fcm/send)。

(该死的简单)问题

下载的文本是德语,包含 ä,ö,ü,ß 等字母和(没有著名的 ?s 代替这些字符)我想将编码更改为 UTF-8

部署到 AppEngine 时默认使用 US-ASCII 编码(为什么默认不是 UTF-8...)。在本地测试时,使用的是我计算机的默认编码,即 UTF-8,一切正常

所以我想要的只是Charset.getDefaultCharset() 返回UTF-8
我如何实现这一目标? 提前致谢,感谢所有帮助。

我的尝试

  • 将此添加到 appengine-web.xml:

    <env-variables> <env-var name="DEFAULT_ENCODING" value="UTF-8" /> </env-variables>

    在本地测试时,我得到了 IncorrectEnvironmentVariableException。部署时编码仍然是 ASCII。

  • 将此添加到 appengine-web.xml 中的&lt;system-properties&gt;-tag:

    <property name="file.encoding" value="UTF-8" /> <property name="DEFAULT_ENCODING" value="UTF-8" />

    什么都没改变,不仅是在部署时,而且当我尝试使用它在本地开发服务器上将编码设置为 US-ASCII 时,Charset.getDefaultCharset() 仍然返回 UTF-8

  • 甚至尝试使用反射:

    System.setProperty("file.encoding","UTF-8"); Field charset = Charset.class.getDeclaredField("defaultCharset"); charset.setAccessible(true); charset.set(null,null);

    (导致 IllegalAccessException)

  • 尝试使用 HTTP-post 将编码设置为内容类型属性(无效):

    connection.setRequestProperty("Content-Type", application/json; charset=UTF-8);

【问题讨论】:

  • 在过去的 7 年里,我从未设置任何系统变量,并且在 App Engine 上使用任何语言(德语、俄语等)都没有问题 :)
  • @AndreiVolgin 好吧,那你很幸运,我没有更改任何内容,默认字符集是 ASCII。这显然不是你的情况(我羡慕你......)但是关于改变编码的问题有几个问题,不仅我有这个问题。我尝试了这些问题的所有答案,即使是那些评分最低的,但没有任何效果。 AppEngine 有什么问题,这似乎不可能像设置一个偏好一样简单......
  • 这与运气或 App Engine 无关。您不应该依赖系统字符集——不应该依赖 App Engine,也不应该依赖其他任何地方。寻找有关如何为 HTTP 请求设置 UTF-8 编码的答案。
  • @AndreiVolgin 首先:看看我尝试过的最后一点。第二:问题发生在发布 HTTP 请求之前。我使用Reader r = new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8"); 进行下载。现在,当 for "Ä" r.read() 返回 196(不在 ASCII 表中)时,转换为 char 会创建一个 '?'。在这一点上,如果 AppEngine 的默认字符集是 UTF-8,一切都会好起来的。如果我不应该依赖系统字符集,我该如何规避呢?如果不创建“?”,我无法将“Ä”分配给字符串。
  • 你在哪里看到这个“?” ?如果您在某处的日志中看到它,则问题可能在于日志中的编码,而不是您正确读取字符串的代码。

标签: java android google-app-engine encoding character-encoding


【解决方案1】:

简答

如果您在编码(即 '?'s)方面遇到问题,并且 似乎 更改默认字符集可以解决问题,那么您真正要做的就是找到使用默认字符集进行编码的代码,并传递一个自定义字符集以代替使用

(就像@AndreiVolgin 评论的那样:你永远不应该依赖系统默认字符集。)

更详细的答案

字符集指定字符如何表示为数字(即字节)。 Java 中所有字符串的内部字符集实际上是 UTF-16,因此只有在将字符串转换为字节数组 (String.getBytes()) 或反之亦然 (new String(byte[]) 时自定义字符集才变得重要强>。
如果您不传递String.getBytes(Charset)new String(byte[], Charset) 之类的字符集,则使用默认字符集。

当不同的字符集用于编码 (String.getBytes()) 和解码 (new String(byte[]) 时,您会看到 '?'。

所以要摆脱 '?'s String.getBytes() 替换为 String.getBytes(Charset)(或者可能将 new String(byte[]) 替换为 new String(byte[], Charset),但不知道这是不是一件事)。


对我来说,通过互联网发送一些文本时出现编码问题,因为字符串需要转换为byte[] 才能使用HttpURLConnection.getOutputStream().write(byte[]) 发送。

准确地说:在类com.google.android.gcm.server.Sender,方法post(java.lang.String, java.lang.String, java.lang.String),第471行是byte[] bytes = body.getBytes();

我将其更改(覆盖)为byte[] bytes = body.getBytes("UTF-8"); - 为我解决了。

【讨论】:

    猜你喜欢
    • 2012-11-02
    • 2014-04-23
    • 2015-11-14
    • 2012-03-10
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    相关资源
    最近更新 更多