You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过Native Messaging API读取希伯来文JSON写入文件显示异常求助

问题

使用Tcl代码通过浏览器扩展Native Messaging API接收消息时,能正常读取所有数据,但写入文件时希伯来文等多字节字符被拆分为单个字节显示(例如显示为×”Ö¸×ָֽרֶץ×)。

请问在写入[dict get $msg doc]($msg为HTML大字符串)前需要做什么处理?是stdin配置错误还是写入数据需要编码?

根据MDN文档说明,传入消息为:JSON序列化、UTF-8编码,前缀为本地字节序的无符号32位消息长度值。

附代码:

#!/usr/bin/env tclsh
package require json
proc coread {reqBytes} {
  set ::extMsg {}
  set remBytes $reqBytes
  while {![chan eof stdin]} {
    yield
    append ::extMsg [set data [read stdin $remBytes]]
    set remBytes [expr {$remBytes - [string length $data]}]
    if {$remBytes == 0} {
      return $reqBytes
    }
  }
  throw {COREAD EOF} "Unexpected EOF"
}

proc ExtRead {} {
  chan event stdin readable coro_stdin
  while {1} {
    set ::extMsg {}
    chan puts $::fp_log "starting coread 4"
    if { [coread 4] != 4 || [binary scan $::extMsg iu len] != 1 } {
      exit
    }
    if { [coread $len] != $len } {
      exit
    }
    set msg [::json::json2dict $::extMsg]
    set book [dict get $msg book]
    set path "../${book}.html"
    set fp [open $path w]
    chan puts $fp [dict get $msg doc]
    close $fp
  }
}

proc CloseConnect {} {
  set ::forever 0
}

proc Listen {} {
  # Listening on stdin
  set ::forever 1
  chan configure stdin -buffering full -blocking 0 -encoding iso8859-1 -translation crlf
  coroutine coro_stdin ExtRead
  vwait forever
}

set extMsg {}
Listen

解决方案

问题出在stdin的编码配置和文件写入时的编码处理两个环节:

  1. 修正stdin的编码配置
    当前stdin被设为iso8859-1编码,这是单字节编码,会直接拆分UTF-8多字节字符,导致后续解析出的字符串已损坏。Native Messaging传输的是二进制前缀+UTF-8 JSON的组合,需分阶段处理编码:

    • 读取4字节长度前缀时,将stdin设为二进制模式,避免编码干扰;
    • 读取JSON内容时,切换为utf-8编码,确保完整解析多字节字符;
    • 解析完成后切回二进制模式,准备下一次读取前缀。

    调整后的代码片段:

    proc Listen {} {
      set ::forever 1
      # 初始配置为二进制模式,用于读取长度前缀
      chan configure stdin -buffering full -blocking 0 -encoding binary -translation binary
      coroutine coro_stdin ExtRead
      vwait forever
    }
    
    proc ExtRead {} {
      chan event stdin readable coro_stdin
      while {1} {
        set ::extMsg {}
        chan puts $::fp_log "starting coread 4"
        # 读取二进制长度前缀
        if { [coread 4] != 4 || [binary scan $::extMsg iu len] != 1 } {
          exit
        }
        # 切换为UTF-8编码读取JSON内容
        chan configure stdin -encoding utf-8 -translation binary
        if { [coread $len] != $len } {
          exit
        }
        # 切回二进制模式,准备下一次循环
        chan configure stdin -encoding binary -translation binary
        set msg [::json::json2dict $::extMsg]
        set book [dict get $msg book]
        set path "../${book}.html"
        # 写入文件时指定UTF-8编码
        set fp [open $path w -encoding utf-8]
        chan puts $fp [dict get $msg doc]
        close $fp
      }
    }
    
  2. 文件写入时指定UTF-8编码
    打开文件时需显式添加-encoding utf-8参数,确保HTML内容以UTF-8编码保存,避免默认编码导致多字节字符异常。

总结:核心是保证UTF-8数据在读取和写入环节都不被编码转换破坏,分阶段处理stdin的编码模式,同时明确文件写入的编码格式。

内容的提问来源于stack exchange,提问作者Gary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 04:05:17