反向数据编码是啥

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反向数据编码是啥相关的知识,希望对你有一定的参考价值。

反向地理编码是使用经纬度坐标来查找特定地理特征或街道地址的过程。这个过程与更常见的地理编码方法相反。在标准地理编码中,首先绘制地物和街道,然后指定一个坐标。反向地理编码填补了标准地理编码坐标信息的空白,因此只需要几个点就可以找到一个位置。手持地球仪的人标准地理编码和反向地理编码的过程是同时进行的。使用标准地理编码技术,街道的起点和终点有精确的经纬度坐标。地理编码软件在地图程序中绘制街道,用户输入该区域的第一个和最后一个街道地址。使用反向地理编码,该程序利用坐标和相对位置推断出地图上房屋的街道编号。逆向地理编码被认为是许多导航技术中的重要步骤。车载导航和增强型911服务等都依赖于反向地理编码来估计目的地的位置。非常很少有地区对每条街道上的每家每户都进行了地理编码,因此服务依赖于反向信息来定位车辆的目的地。反向位置可能与实际位置相差几英尺,但它通常足够近,一个人可以用正常的方法找到真正的位置。这个过程对户外的人也很有用。他们可以找到自己的坐标,并将其作为基点。关于该点附近已知地点的信息会被转发回给他们。这使得找到已知地点变得容易,例如已经用标准地理编码找到的钓鱼点或徒步旅行小道。有了完整的地理信息系统,也可以找到附近的其他感兴趣的地点,如高速公路或河流与许多地理信息系统一样,反向地理编码也存在争议。通过使用预先存在的地图,可以定位出不被发现的人或区域。许多形式的机密研究和实验依赖于主题之间的相对距离或中心点。在这些研究中,发布地图显示受试者的位置并不少见。这些地图故意没有什么特征,但通过反向地理编码过程,就有可能定位目标的位置。当这种能力与其他地理系统相结合时,问题变得更加明显。匿名的人和地方的位置相对容易找到;然后,从公共信息中推断出的信息可以找到更多关于这个主题的信息。这可以让人们很容易地跟踪他人,学习购物或驾驶习惯 参考技术A 定点数的表示方法。
1、在计算机内,定点数有3种表示法:原码、反向码和补码。
2、由于补码更能有效表现数字在计算机中的形式,所以多数计算机都不采用反向码表示数。

在 Java 中为 XML 编码文本数据的最佳方法是啥?

【中文标题】在 Java 中为 XML 编码文本数据的最佳方法是啥?【英文标题】:Best way to encode text data for XML in Java?在 Java 中为 XML 编码文本数据的最佳方法是什么? 【发布时间】:2010-10-01 03:47:08 【问题描述】:

与this question 非常相似,Java 除外。

在 Java 中为 XML 输出编码字符串的推荐方法是什么。字符串可能包含“&”、“

【问题讨论】:

【参考方案1】:

正如其他人所提到的,使用 XML 库是最简单的方法。如果您确实想逃避自己,可以查看Apache Commons Lang 库中的StringEscapeUtils

【讨论】:

如果您不关心绝对正确性,例如,如果您正在组装一个原型,这可能是您要走的路。 使用来自commons-langStringEscapeUtils.escapeXml(str)。我在 App Engine 应用程序中使用它 - 像魅力一样工作。这是此功能的Java Doc: StringEscapeUtils 的 escapeXml 方法好像有点贵。有没有更有效的方法来操作 StringBuffer 而不是 String? 此方法是否适用于 XML 内容和属性?对我来说,它似乎不适用于属性。它似乎无法逃脱\t\n\r 注意它已经从commons-lang移动到commons-text【参考方案2】:

非常简单:使用 XML 库。这样一来,它实际上是正确,而不需要详细了解 XML 规范。

【讨论】:

你能推荐这样一个库吗? (令我惊讶的是,这不是 Java 版本 5 的标准部分……如此常见的任务)。 XML 标准 Java 框架的一部分 - 查看 org.w3c.sax 和 org.w3c.dom。但是,也有一些更易于使用的框架,例如 JDom。请注意,可能没有“为 XML 输出编码字符串”的方法——我更建议整个 XML 任务应该使用库来完成,而不是一次只做一些字符串操作。 在输出 XHTML 时,这不是很有用的建议——FlyingSaucer 需要 XML,但我不可能通过 XML 库进行模板化:)。谢天谢地 StringTemplate 让我可以快速转义所有 String 对象。 @mice:这个问题被标记为 Java,Java 有 很多 个 XML 库。确实,Java 中已经嵌入了 XML API,因此无需添加 anything 其他...但即使您这样做了,如今在移动设备之外,几百 K 也很少成为问题。即使不是 Java,我也会非常警惕在没有任何 XML API 的平台上进行开发... @mice:DOM API 完全能够生成 XML。或者有相当小的第三方库。 (例如 JDom 的 jar 文件为 114K。)使用 XML API 仍然是创建 XML 的推荐方式。【参考方案3】:

随便用。

<![CDATA[ your text here ]]>

这将允许除结尾之外的任何字符

]]>

因此您可以包含非法字符,例如 & 和 >。例如。

<element><![CDATA[ characters such as & and > are allowed ]]></element>

但是,属性需要转义,因为 CDATA 块不能用于它们。

【讨论】:

在大多数情况下,这不是您应该做的。太多人滥用 CDATA 标签。 CDATA 的目的是告诉处理器不要将其作为 XML 处理,而只是将其传递。如果您尝试创建 XML 文件,那么您应该创建 XML,而不仅仅是通过某些包装元素传递字节。 @Mads,使用 CDATA 会生成一个有效的 XML 文件,因此它与以“正确的方式”执行它一样好。如果你不喜欢它,然后解析它,进行身份转换,然后打印它。 如果您将文本包装在 CDATA 元素中,则必须转义 CDATA 结束标记:“]]>”...除非您无法转义。因此,您必须将代码分成几部分,将一半数据放在一个 CDATA 元素中,另一半放在一秒钟内:" 这就是为什么它必须被拆分的原因。]]> ... 最后,转义 '' 和 '&' 可能要简单得多。当然,许多应用程序忽略了数据中 CDATA 关闭标记的潜在问题。我想无知是幸福的。 :) @StijndeWitt 是绝对正确的。 CDATA 不是转义特殊字符的灵丹妙药。 这是个坏主意。 CDATA 不允许 XML 编码之外的任何字符。【参考方案4】:

试试这个:

String xmlEscapeText(String t) 
   StringBuilder sb = new StringBuilder();
   for(int i = 0; i < t.length(); i++)
      char c = t.charAt(i);
      switch(c)
      case '<': sb.append("&lt;"); break;
      case '>': sb.append("&gt;"); break;
      case '\"': sb.append("&quot;"); break;
      case '&': sb.append("&amp;"); break;
      case '\'': sb.append("&apos;"); break;
      default:
         if(c>0x7e) 
            sb.append("&#"+((int)c)+";");
         else
            sb.append(c);
      
   
   return sb.toString();

【讨论】:

您至少有两个我可以看到的错误。一个是微妙的,另一个不是。我不会有这样的错误 - 因为我一开始就不会重新发明***。 遍历 Unicode 字符串有点复杂。见这里:***.com/q/1527856/402322 不确定是不是微妙,但最好考虑t==null的情况。 @user1003916:XML 转义旨在将任何 & 出现转换为 &所以它必须这样工作。如果你 excape 已经转义的字符串,那是你的错。 我对最终版本很满意。 Java SE 紧凑、快速且高效。在我看来,只做需要做的事情,而不是下载另外 100 MB 的英国媒体报道软件总是更好。【参考方案5】:

这对我来说很好地提供了文本字符串的转义版本:

public class XMLHelper 

/**
 * Returns the string where all non-ascii and <, &, > are encoded as numeric entities. I.e. "&lt;A &amp; B &gt;"
 * .... (insert result here). The result is safe to include anywhere in a text field in an XML-string. If there was
 * no characters to protect, the original string is returned.
 * 
 * @param originalUnprotectedString
 *            original string which may contain characters either reserved in XML or with different representation
 *            in different encodings (like 8859-1 and UFT-8)
 * @return
 */
public static String protectSpecialCharacters(String originalUnprotectedString) 
    if (originalUnprotectedString == null) 
        return null;
    
    boolean anyCharactersProtected = false;

    StringBuffer stringBuffer = new StringBuffer();
    for (int i = 0; i < originalUnprotectedString.length(); i++) 
        char ch = originalUnprotectedString.charAt(i);

        boolean controlCharacter = ch < 32;
        boolean unicodeButNotAscii = ch > 126;
        boolean characterWithSpecialMeaningInXML = ch == '<' || ch == '&' || ch == '>';

        if (characterWithSpecialMeaningInXML || unicodeButNotAscii || controlCharacter) 
            stringBuffer.append("&#" + (int) ch + ";");
            anyCharactersProtected = true;
         else 
            stringBuffer.append(ch);
        
    
    if (anyCharactersProtected == false) 
        return originalUnprotectedString;
    

    return stringBuffer.toString();



【讨论】:

stringBuffer.append("" + (int) ch + ";");这不适用于多字节字符。我现在遇到了一个表情符号字符,UTF8 序列 F0 9F 98 8D。【参考方案6】:

这个问题已经八年了,仍然不是一个完全正确的答案!不,您不必导入整个第三方 API 来完成这个简单的任务。不好的建议。

以下方法将:

正确处理基本多语言平面之外的字符 XML 中需要转义字符 转义任何非 ASCII 字符,这是可选但常见的 用 Unicode 替换字符替换 XML 1.0 中的 非法 字符。这里没有最佳选择 - 删除它们同样有效。

我已尝试针对最常见的情况进行优化,同时仍确保您可以通过管道传输 /dev/random 并获得 XML 中的有效字符串。

public static String encodeXML(CharSequence s) 
    StringBuilder sb = new StringBuilder();
    int len = s.length();
    for (int i=0;i<len;i++) 
        int c = s.charAt(i);
        if (c >= 0xd800 && c <= 0xdbff && i + 1 < len) 
            c = ((c-0xd7c0)<<10) | (s.charAt(++i)&0x3ff);    // UTF16 decode
        
        if (c < 0x80)       // ASCII range: test most common case first
            if (c < 0x20 && (c != '\t' && c != '\r' && c != '\n')) 
                // Illegal XML character, even encoded. Skip or substitute
                sb.append("&#xfffd;");   // Unicode replacement character
             else 
                switch(c) 
                  case '&':  sb.append("&amp;"); break;
                  case '>':  sb.append("&gt;"); break;
                  case '<':  sb.append("&lt;"); break;
                  // Uncomment next two if encoding for an XML attribute
//                  case '\''  sb.append("&apos;"); break;
//                  case '\"'  sb.append("&quot;"); break;
                  // Uncomment next three if you prefer, but not required
//                  case '\n'  sb.append("&#10;"); break;
//                  case '\r'  sb.append("&#13;"); break;
//                  case '\t'  sb.append("&#9;"); break;

                  default:   sb.append((char)c);
                
            
         else if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) 
            // Illegal XML character, even encoded. Skip or substitute
            sb.append("&#xfffd;");   // Unicode replacement character
         else 
            sb.append("&#x");
            sb.append(Integer.toHexString(c));
            sb.append(';');
        
    
    return sb.toString();

编辑:对于那些继续坚持在有非常好的 Java API 来处理 XML 时为此编写自己的代码是愚蠢的人,您可能想知道 Oracle Java 8 中包含的 StAX API (我没有测试过其他人)未能正确编码 CDATA 内容:它不会转义 ]]> 内容中的序列。第三方库,即使是 Java 核心的一部分,也并不总是最好的选择。

【讨论】:

+1 用于独立代码。只是将您的代码与guava implementation 进行比较,我想知道 '\t','\n','\r' 呢?另请参阅guava docs 的注释 没有必要转义\n、\r 和\t,它们是有效的,尽管它们确实使格式有点难看。我已经修改了代码以显示如果这是你想要的如何逃避它们。 CDATA 中没有 no 方法可以“转义]]>”。 然后它应该通过抛出 IllegalArgumentException 来拒绝内容。在任何情况下,它都不应声称成功但仍输出无效的 XML。 您可以在这里使用我的方法***.com/a/59475093/3882565,而不是用 Unicode 替换字符替换 XML 1.0 中的非法字符。【参考方案7】:

StringEscapeUtils.escapeXml() 不转义控制字符 (XStream.toXML() 会愉快地将 Java 对象的控制字符序列化为 XML,而 XML 1.0 解析器将拒绝。

要使用 Apache commons-lang 转义控制字符,请使用

NumericEntityEscaper.below(0x20).translate(StringEscapeUtils.escapeXml(str))

【讨论】:

【参考方案8】:
public String escapeXml(String s) 
    return s.replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");

【讨论】:

链接replaceAll 调用效率非常低,尤其是对于大字符串。每次调用都会创建一个新的 String 对象,该对象将一直存在,直到垃圾收集为止。此外,每次调用都需要再次循环字符串。这可以合并到一个手动循环中,并在每次迭代中与每个目标字符进行比较。 这应该是公认的答案,即使它效率低下。它在一行中解决了问题。 而且它有很多错误。见this comment above 要修复这些错误,您还可以在这里使用我的方法***.com/a/59475093/3882565。请注意,这不是替代品,但可以额外使用。【参考方案9】:

对于那些寻求最快编写解决方案的人:使用来自apache commons-lang的方法:

StringEscapeUtils.escapeXml10() 用于 xml 1.0 StringEscapeUtils.escapeXml11() 用于 xml 1.1 StringEscapeUtils.escapeXml() 现已弃用,但过去常用

记得包含依赖:

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.5</version> <!--check current version! -->
</dependency>

【讨论】:

请注意,它已从 commons-lang 移至 commons-text【参考方案10】:

虽然理想主义说使用 XML 库,但恕我直言,如果您对 XML 有基本概念,那么常识和性能一直都说是模板。它也可以说更具可读性。尽管使用库的转义例程可能是个好主意。

考虑一下:XML 应该由人类编写的。

当您将 XML 作为“对象”更好地模拟您的问题时,使用生成 XML 的库。例如,如果可插拔模块参与构建此 XML 的过程。

编辑:至于如何在模板中实际转义 XML,使用 JSTL 中的 CDATA 或 escapeXml(string) 是两个很好的解决方案,escapeXml(string) 可以这样使用:

<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

<item>$fn:escapeXml(value)</item>

【讨论】:

【参考方案11】:

StringEscapeUtils.escapeXml() 的行为已从 Commons Lang 2.5 更改为 3.0。 它现在不再转义大于 0x7f 的 Unicode 字符。

这是一件好事,旧方法有点急于逃避可以插入到 utf8 文档中的实体。

Google Guava 11.0 中包含的新转义器似乎也很有希望: http://code.google.com/p/guava-libraries/issues/detail?id=799

【讨论】:

这里是 Guava 的 XML 转义器:code.google.com/p/guava-libraries/source/browse/guava/src/com/…。总的来说,我发现 Guava 的架构比 Apache Commons 更好。 google.github.io/guava/releases/23.0/api/docs/com/google/common/…【参考方案12】:

注意:您的问题是关于转义,而不是编码。转义是使用

首先,就像其他人所说的那样,使用 XML 库。 XML 看起来很简单,但编码+转义的东西是黑暗的巫术(一旦你遇到变音符号和日语以及其他奇怪的东西,比如“full width digits”(FF11; 是 1),你就会注意到它)。保持 XML 可读性是西西弗斯的任务。

我建议永远不要试图在 XML 中的文本编码和转义方面变得聪明。但不要让这阻止你尝试;只要记住它咬你的时候(它会咬你的)。

也就是说,如果您只使用 UTF-8,为了使内容更具可读性,您可以考虑以下策略:

如果文本确实包含“”或“&”,则将其包裹在&lt;![CDATA[ ... ]]&gt; 如果文本不包含这三个字符,请不要扭曲它。

我在 SQL 编辑器中使用它,它允许开发人员将 SQL 从第三方 SQL 工具剪切和粘贴到 XML 中,而不必担心转义。这是可行的,因为在我们的例子中 SQL 不能包含变音符号,所以我很安全。

【讨论】:

【参考方案13】:

虽然我原则上同意 Jon Skeet,但有时我无法选择使用外部 XML 库。而且我发现在 Java 中包含的标准 XML 库中没有转义/取消转义一个简单值(属性或标签,不是完整文档)的两个函数很奇特。

因此,根据我在这里和其他地方看到的不同答案,这是我最终创建的解决方案(没有什么可以作为简单的复制/粘贴):

  public final static String ESCAPE_CHARS = "<>&\"\'";
  public final static List<String> ESCAPE_STRINGS = Collections.unmodifiableList(Arrays.asList(new String[] 
      "&lt;"
    , "&gt;"
    , "&amp;"
    , "&quot;"
    , "&apos;"
  ));

  private static String UNICODE_NULL = "" + ((char)0x00); //null
  private static String UNICODE_LOW =  "" + ((char)0x20); //space
  private static String UNICODE_HIGH = "" + ((char)0x7f);

  //should only be used for the content of an attribute or tag      
  public static String toEscaped(String content) 
    String result = content;
    
    if ((content != null) && (content.length() > 0)) 
      boolean modified = false;
      StringBuilder stringBuilder = new StringBuilder(content.length());
      for (int i = 0, count = content.length(); i < count; ++i) 
        String character = content.substring(i, i + 1);
        int pos = ESCAPE_CHARS.indexOf(character);
        if (pos > -1) 
          stringBuilder.append(ESCAPE_STRINGS.get(pos));
          modified = true;
        
        else 
          if (    (character.compareTo(UNICODE_LOW) > -1)
               && (character.compareTo(UNICODE_HIGH) < 1)
             ) 
            stringBuilder.append(character);
          
          else 
            //Per URL reference below, Unicode null character is always restricted from XML
            //URL: https://en.wikipedia.org/wiki/Valid_characters_in_XML
            if (character.compareTo(UNICODE_NULL) != 0) 
              stringBuilder.append("&#" + ((int)character.charAt(0)) + ";");
            
            modified = true;
          
        
      
      if (modified) 
        result = stringBuilder.toString();
      
    
    
    return result;
  

上面包含了几个不同的东西:

    避免使用基于字符的逻辑,直到它绝对必须 - 提高 unicode 兼容性 尝试尽可能高效,因为概率是第二个“如果”条件可能是最常用的途径 是一个纯函数;即是线程安全的 通过仅在实际发生更改时返回 StringBuilder 的内容来很好地优化垃圾收集器 - 否则,返回原始字符串

在某个时候,我会写这个函数的反转,toUnescaped()。我只是今天没有时间这样做。当我这样做时,我会用代码更新这个答案。 :)

【讨论】:

对我来说看起来不错。我不想只为一种方法向我的项目添加另一个 jar。如果您允许,我可以复制粘贴您的代码吗? @SatishMotwani 当然,您可以使用上面的代码并随心所欲地使用它。我的理解是,在 *** 上发布的任何代码都被认为是无版权的(不包括全部作品)。另一方面,如果有人提出任何形式的版权主张并期望自己得到某种结果,那将是极其困难的。 感谢您的允许 :-) 我会使用它。 您忘记处理 NUL 字符。也许还有其他事情。 @chaotic3quilibrium NULL 在 XML 中是非法的(以及其他一些字符)。不管你如何编码。这是非法的。 (另外:实际上没有必要转义 Unicode 字符,它们在 XML 中得到很好的支持,除非 XML 文档本身具有非 Unicode 编码)【参考方案14】:

如果您正在寻找一个库来完成这项工作,请尝试:

    Guava 26.0 记录了here

    return XmlEscapers.xmlContentEscaper().escape(text);

    注意:还有一个xmlAttributeEscaper()

    Apache Commons Text 1.4 记录了here

    StringEscapeUtils.escapeXml11(text)

    注意:还有一个escapeXml10()方法

【讨论】:

【参考方案15】:

要转义 XML 字符,最简单的方法是使用 Apache Commons Lang 项目,JAR 可从以下位置下载:http://commons.apache.org/lang/

类是这样的:org.apache.commons.lang3.StringEscapeUtils;

它有一个名为“escapeXml”的方法,它将返回一个适当转义的字符串。

【讨论】:

更新:escapeXml 现已弃用 - 使用 escapeXml10。参考commons.apache.org/proper/commons-lang/javadocs/api-3.3/org/…【参考方案16】:

您可以使用Enterprise Security API (ESAPI) library,它提供了encodeForXMLencodeForXMLAttribute 等方法。看一下Encoder接口的文档;它还包含如何创建DefaultEncoder 实例的示例。

【讨论】:

【参考方案17】:

这是一个简单的解决方案,它也非常适合编码重音字符!

String in = "Hi Lârry & Môe!";

StringBuilder out = new StringBuilder();
for(int i = 0; i < in.length(); i++) 
    char c = in.charAt(i);
    if(c < 31 || c > 126 || "<>\"'\\&".indexOf(c) >= 0) 
        out.append("&#" + (int) c + ";");
     else 
        out.append(c);
    


System.out.printf("%s%n", out);

输出

Hi L&#226;rry &#38; M&#244;e!

【讨论】:

“if”第一行的“31”不应该是“32”吗?即小于空格字符?如果必须保留“31”,那么不应该将其更正为“if (c 【参考方案18】:

使用JAXP 并忘记文本处理,它将自动为您完成。

【讨论】:

您的链接是西班牙语的,这对我们大多数人来说并没有太大帮助。更好的是this one。【参考方案19】:

尝试使用 Apache XML 序列化器对 XML 进行编码

//Serialize DOM
OutputFormat format    = new OutputFormat (doc); 
// as a String
StringWriter stringOut = new StringWriter ();    
XMLSerializer serial   = new XMLSerializer (stringOut, 
                                          format);
serial.serialize(doc);
// Display the XML
System.out.println(stringOut.toString());

【讨论】:

【参考方案20】:

只需替换

 & with &amp;

对于其他角色:

> with &gt;
< with &lt;
\" with &quot;
' with &apos;

【讨论】:

【参考方案21】:

这是我在到处寻找解决方案后发现的:

获取 Jsoup 库:

<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.12.1</version>
</dependency>

然后:

import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Entities
import org.jsoup.parser.Parser

String xml = '''<?xml version = "1.0"?>
<SOAP-ENV:Envelope
   xmlns:SOAP-ENV = "http://www.w3.org/2001/12/soap-envelope"
   SOAP-ENV:encodingStyle = "http://www.w3.org/2001/12/soap-encoding">

   <SOAP-ENV:Body xmlns:m = "http://www.example.org/quotations">
      <m:GetQuotation>
         <m:QuotationsName> MiscroSoft@G>>gle.com </m:QuotationsName>
      </m:GetQuotation>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''



Document doc = Jsoup.parse(new ByteArrayInputStream(xml.getBytes("UTF-8")), "UTF-8", "", Parser.xmlParser())
doc.outputSettings().charset("UTF-8")
doc.outputSettings().escapeMode(Entities.EscapeMode.base)

println doc.toString()

希望这对某人有所帮助

【讨论】:

【参考方案22】:

我在这里创建了我的包装器,希望对你有很大帮助,Click here你可以根据你的要求进行修改

【讨论】:

以上是关于反向数据编码是啥的主要内容,如果未能解决你的问题,请参考以下文章

无需手动输入即可自动完成反向地理编码的数据

反向标签编码给出错误

Android 反向地理编码需要 Internet 连接或后端数据提供程序

正向搜索查询和反向搜索查询的区别是啥?

谁能解释一下nginx反向代理是啥意思?

使用 Google Maps Javascript API V3 反向地理编码检索邮政编码