首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在不使用BOM的情况下识别不同的编码?

如何在不使用BOM的情况下识别不同的编码?
EN

Stack Overflow用户
提问于 2009-08-28 00:31:57
回答 2查看 1.1K关注 0票数 0

我有一个文件观察器,它从一个用utf-16LE编码的不断增长的文件中获取内容。写入它的第一位数据有可用的BOM --我用它来识别UTF-8的编码(我传入的大多数文件都是用它编码的)。我捕获BOM并将其重新编码到UTF-8,这样我的解析器就不会崩溃。问题是,由于它是一个不断增长的文件,并不是所有的数据都包含BOM。

下面是我的问题--不需要在我拥有的每一组数据中先于BOM字节(,因为我没有对源的控制),我可以只查找UTF-16000中固有的空字节,然后使用它作为我的标识符而不是BOM吗?这会让我头痛吗?

我的架构涉及一个ruby应用程序,当我的解析器用java编写时,将接收到的数据记录到一个临时文件中。

现在编写我的识别/重新编码代码如下:

代码语言:javascript
复制
  // 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();
  }

更新

我想支持的东西,如欧元,em-破折号,和其他字符的这类。我修改了上面的代码,如下所示,它似乎通过了对这些字符的所有测试:

代码语言:javascript
复制
  // 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();
  }

你们都怎么想?

EN

回答 2

Stack Overflow用户

发布于 2009-08-28 00:50:13

通常,您无法100%准确地识别数据流的字符编码。您所能做的最好是使用一组有限的期望编码来解码,然后对解码的结果应用一些启发式方法,看看它在预期语言中是否“看起来像”文本。(但任何启发都会对某些数据流产生假阳性和假阴性。)或者,让一个人在循环中决定哪种解码最有意义。

更好的解决方案是重新设计您的协议,以便提供数据的任何内容都必须提供用于数据的编码方案。(如果你不能,那就怪谁负责设计/实现无法给出编码方案的系统!)

编辑:从您对这个问题的评论来看,数据文件是通过HTTP传递的。在这种情况下,您应该安排您的HTTP服务器对发送数据的POST请求的“内容类型”报头进行咆哮,从标题中提取字符集/编码,并以文件解析器可以处理的方式/位置保存它。

票数 6
EN

Stack Overflow用户

发布于 2009-08-28 00:50:56

毫无疑问,这会让你头疼。对于简单的情况,您可以检查交替的零字节(仅ASCII,UTF-16,任一个字节顺序),但是当您开始在0x7f代码点上获得字符流时,该方法就变得毫无用处。

如果您有文件句柄,最好的选择是保存当前的文件指针,查找开始,读取BOM,然后查找回原来的位置。

或者想办法记住BOM。

依赖数据内容是个坏主意,除非您完全确定所有输入的字符范围都会受到限制。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1344452

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档