如何才能辨别不使用BOM的不同编码?(How can I identify different en

2019-10-29 18:51发布

我有一个抓住从UTF-16LE编码的文件越来越多内容的文件观察者。 写入数据的第一位拥有可用的BOM - 我就是用这个来确定对UTF-8(其中大部分我的文件进来的编码)的编码。 我赶上了BOM和重新编码成UTF-8,所以我的解析器不吓坏了。 问题是,因为它是一个不断增长的文件不是数据的每一位拥有它的BOM。

我的问题是-没有前面加上BOM字节到每一组数据我有( 因为我没有在源控制 )可我只能寻找那些在UTF-16 \ 000是固有的空字节,然后用作为我的标识,而不是BOM? 这会不会导致我头痛的道路?

我的架构涉及红宝石Web应用程序接收到的数据记录到一个临时文件时,我的解析器用Java编写的捡起来。

现在写我的鉴定/重新编码的代码如下所示:

  // guess encoding if utf-16 then
  // convert to UTF-8 first
  try {
    FileInputStream fis = new FileInputStream(args[args.length-1]);
    byte[] contents = new byte[fis.available()];
    fis.read(contents, 0, contents.length);

    if ( (contents[0] == (byte)0xFF) && (contents[1] == (byte)0xFE) ) {
      String asString = new String(contents, "UTF-16");
      byte[] newBytes = asString.getBytes("UTF8");
      FileOutputStream fos = new FileOutputStream(args[args.length-1]);
      fos.write(newBytes);
      fos.close();
    }

    fis.close();
    } catch(Exception e) {
      e.printStackTrace();
  }

UPDATE

我想支持的东西像欧元,长划线,这样其他字符。 我修改了上面的代码看起来像这样,它似乎把我的那些人物的所有测试:

  // guess encoding if utf-16 then
  // convert to UTF-8 first
  try {
    FileInputStream fis = new FileInputStream(args[args.length-1]);
    byte[] contents = new byte[fis.available()];
    fis.read(contents, 0, contents.length);
    byte[] real = null;

    int found = 0;

    // if found a BOM then skip out of here... we just need to convert it
    if ( (contents[0] == (byte)0xFF) && (contents[1] == (byte)0xFE) ) {
      found = 3;
      real = contents;

    // no BOM detected but still could be UTF-16
    } else {

      for(int cnt=0; cnt<10; cnt++) {
        if(contents[cnt] == (byte)0x00) { found++; };

        real = new byte[contents.length+2];
        real[0] = (byte)0xFF;
        real[1] = (byte)0xFE;

        // tack on BOM and copy over new array
        for(int ib=2; ib < real.length; ib++) {
          real[ib] = contents[ib-2];
        }
      }

    }

    if(found >= 2) {
      String asString = new String(real, "UTF-16");
      byte[] newBytes = asString.getBytes("UTF8");
      FileOutputStream fos = new FileOutputStream(args[args.length-1]);
      fos.write(newBytes);
      fos.close();
    }

    fis.close();
    } catch(Exception e) {
      e.printStackTrace();
  }

你怎么都认为?

Answer 1:

在一般情况下,你不能确定100%准确的数据流的字符编码。 你能做的最好是尝试使用有限的一组预期编码的解码,然后涂抹一些启发式的解码结果,看它是否“看起来像”在预期语言文字。 (但是,任何启发式会给误报和对某些数据流的假阴性)。此外,把一个人在回路中决定哪个解码是很有道理的。

一个更好的解决办法是重新设计你的协议,无论是提供数据必须也提供用于数据的编码方案。 (如果你不能,只能怪谁负责设计/实施不能给你一个编码方案的系统!)。

编辑:从这个问题您的意见,数据文件被通过HTTP递送。 在这种情况下,你应该安排你的HTTP服务器snarfs的POST请求传送数据的“内涵式”标题,提取标题字符集/编码,并将其保存在一个通道/地方,你的文件分析器能处理。



Answer 2:

这将导致你头痛的道路,这是毫无疑问的。 您可以检查交替的简单案件零个字节(ASCII只,UTF-16,无论是字节顺序),但是你开始的0x7F的代码点以上字符流分钟,该方法变得无用。

如果你有文件句柄,最好的办法是保存当前的文件指针,寻求启动,读取BOM进而寻求回到原来的位置。

如果不是这样,莫名其妙地记得BOM。

依托数据内容是一个主意,除非你是绝对肯定的字符范围将所有输入的限制。



Answer 3:

这个问题包含了不出现需要BOM字符检测几个选项。

我的项目是目前使用jCharDet但我可能需要看一些上市还有其他选项作为jCharDet是不是100%可靠。



文章来源: How can I identify different encodings without the use of a BOM?