java - 多字节字符 - 模式匹配

标签 java

我正在读取 Shift-JIS 编码的 XML 文件并将其存储在 ByteBuffer 中,然后将其转换为字符串,并尝试通过 Pattern 和 Matcher 查找字符串的开头和结尾。我尝试从这两个位置将缓冲区写入文件。当没有多字节字符时它可以工作。如果有一个多字节字符,我会错过末尾的一些文本,因为 end 的值有点偏离

static final Pattern startPattern = Pattern.compile("<\\?xml ");
static final Pattern endPattern = Pattern.compile("</doc>\n");

 public static void main(String[] args) throws Exception {
    File f = new File("20121114000606JA.xml");
    FileInputStream fis = new FileInputStream(f);
    FileChannel fci = fis.getChannel();
    ByteBuffer data_buffer = ByteBuffer.allocate(65536);
    while (true) {
      int read = fci.read(data_buffer);
      if (read == -1)
        break;
    }

    ByteBuffer cbytes = data_buffer.duplicate();
    cbytes.flip();
    Charset data_charset = Charset.forName("UTF-8");
    String request = data_charset.decode(cbytes).toString();

    Matcher start = startPattern.matcher(request);
    if (start.find()) {
      Matcher end = endPattern.matcher(request);

      if (end.find()) {

        int i0 = start.start();
        int i1 = end.end();

        String str = request.substring(i0, i1);

        String filename = "test.xml";
        FileChannel fc = new FileOutputStream(new File(filename), false).getChannel();

        data_buffer.position(i0);
        data_buffer.limit(i1 - i0);

        long offset = fc.position();
        long sz = fc.write(data_buffer);

        fc.close();
      }
    }
    System.out.println("OK");
  }

最佳答案

使用字符串索引 i0 和 i1 来表示字节位置:

data_buffer.position(i0);
data_buffer.limit(i1 - i0);

是错误的。由于 UTF-8 没有给出唯一的编码,ĉ 被写成两个字符 c + 组合变音标记 ^,之间来回翻译字符和字节不仅昂贵而且容易出错(在特定数据的 rand 情况下)。

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
        new File(filename)), "UTF-8"));

或者使用 CharBuffer,它实现了 CharSequence。

<小时/>

而不是写入 FileChannel fc:

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
        new File(filename)), "UTF-8"));
try {
    out.write(str);
} finally {
    out.close();
}

CharBuffer 版本需要更多重写,还涉及模式匹配。

关于java - 多字节字符 - 模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13400370/

相关文章:

java - 忽略测试本身中运行的unitTest

java - JUnit 黑盒测试与白盒测试

java - 将 Java 类结构转换为 Python 类

java - 在STS上运行Spring项目出现ServletException错误

java - 如何为 Log4j 创建文件配置

java - 生产者消费者问题

java - 关于TestNG的问题

java - AspectJ - 实现给定接口(interface)的类的静态类型间声明

java - 未使用 tomcat jndi ldap userSearchAsUser

java - 我们可以将包含父类(super class)对象的 vector 转换为包含子类对象的 vector 吗?