2013-12-05 3 views
9

Я получаю это на json.Marshal из списка строк:Удалить недопустимые символы UTF-8 символов из строки (Go языки)

json: invalid UTF-8 in string: "...ole\xc5\" 

Причина очевидна, но как я могу удалить/заменить такие строки в Го? Я читал docst по unicode и unicode/utf8 пакетам, и, похоже, нет очевидного/быстрого способа сделать это.

В Python, например, у вас есть методы для него, где недопустимые символы могут быть удалены, заменены заданным символом или строгим параметром, что вызывает исключение на недопустимых символах. Как я могу сделать эквивалентную вещь в Go?

UPDATE: Я имел в виду причину получения исключения (паника?) - незаконный символ в json.Marshal ожидает быть допустимой строкой UTF-8.

(как нелегальная последовательность байт попала в эту строка не важна, обычный способ - ошибки, файл с коррупцией, другие программы, которые не соответствуют юникоду и т.д.)

+1

Как причина очевидна? Я бы предположил, что у вас есть строка latin1 (или какой-то другой вариант ISO8859), в этом случае вы не хотите, чтобы функция проглатывала эти символы, а вместо этого конвертировала их в UTF-8, прежде чем продолжить ... – filmor

+0

@filmor: см. Обновить. – LetMeSOThat4U

+1

В Go 1.2 парсер json примет неверный UTF-8. Он заменит неверные байты с помощью замещающего глифа. – fuz

ответ

15

Например,

package main 

import (
    "fmt" 
    "unicode/utf8" 
) 

func main() { 
    s := "a\xc5z" 
    fmt.Printf("%q\n", s) 
    if !utf8.ValidString(s) { 
     v := make([]rune, 0, len(s)) 
     for i, r := range s { 
      if r == utf8.RuneError { 
       _, size := utf8.DecodeRuneInString(s[i:]) 
       if size == 1 { 
        continue 
       } 
      } 
      v = append(v, r) 
     } 
     s = string(v) 
    } 
    fmt.Printf("%q\n", s) 
} 

Выход:

"a\xc5z" 
"az" 

Unicode Standard

FAQ - UTF-8, UTF-16, UTF-32 & BOM

Q: Are there any byte sequences that are not generated by a UTF? How should I interpret them?

A: None of the UTFs can generate every arbitrary byte sequence. For example, in UTF-8 every byte of the form 110xxxxx2 must be followed with a byte of the form 10xxxxxx2. A sequence such as <110xxxxx2 0xxxxxxx2> is illegal, and must never be generated. When faced with this illegal byte sequence while transforming or interpreting, a UTF-8 conformant process must treat the first byte 110xxxxx2 as an illegal termination error: for example, either signaling an error, filtering the byte out, or representing the byte with a marker such as FFFD (REPLACEMENT CHARACTER). In the latter two cases, it will continue processing at the second byte 0xxxxxxx2.

A conformant process must not interpret illegal or ill-formed byte sequences as characters, however, it may take error recovery actions. No conformant process may use irregular byte sequences to encode out-of-band information.

+0

Хотя, скорее всего, совершенно не имеет значения, ваш пример может полностью исключить закодированные * Unicode Replacement Characters * ('" \ xef \ xbf \ xbd "'), если строка также содержит разбитые последовательности UTF8. – ANisus

+0

@ANisus: Предполагается, что люди прочитали стандарт Unicode. – peterSO

+0

Мой комментарий был просто пустяком. Моя функция также удалит заменяющие символы вместе с незаконными последовательностями (это все мои +1;)). Я только что сказал, что законная последовательность байтов «\ xef \ xbf \ xbd», которую примет json.Marshal, также будет удалена. Не знаете, как Unicode Standard не согласится с этим. – ANisus

Смежные вопросы