Ruby 1.9, force_encoding, mas verifique

Eu tenho uma string que li de algum tipo de entrada.

Para o melhor do meu conhecimento, é UTF8. OK:

<code>string.force_encoding("utf8")
</code>

Mas se essa string tiver bytes nela que não sejam de fato UTF8 legais, quero saber agora e agir.

Ordinariamente, o force_encoding ("utf8") será criado se encontrar tais bytes? Euacreditam não vai.

Se eu estivesse fazendo uma#codificar Eu poderia escolher entre as opções úteis com o que fazer com caracteres inválidos na codificação de origem (ou codificação de destino).

Mas eu não estou fazendo um #encode, estou fazendo um #force_encoding. Não tem essas opções.

Faz sentido

<code>string.force_encoding("utf8").encode("utf8")
</code>

obter uma exceção imediatamente? Normalmente codificaçãode utf8para utf8 não faz qualquer sentido. Mas talvez esta seja a maneira de aumentar imediatamente se houver bytes inválidos? Ou use o:replace opção etc para fazer algo diferente com bytes inválidos?

Mas não, parece que isso não funciona.

Ninguem sabe?

<code>1.9.3-p0 :032 > a = "bad: \xc3\x28 okay".force_encoding("utf-8")
=> "bad: \xC3( okay"
1.9.3-p0 :033 > a.valid_encoding?
=> false
</code>

Ok, mas como eu encontro e elimino esses bytes ruins? Estranhamente, isso não aumenta:

<code>1.9.3-p0 :035 > a.encode("utf-8")
 => "bad: \xC3( okay"
</code>

Se eu estivesse convertendo para uma codificação diferente, seria!

<code>1.9.3-p0 :039 > a.encode("ISO-8859-1")
Encoding::InvalidByteSequenceError: "\xC3" followed by "(" on UTF-8
</code>

Ou, se eu contasse, substituiria por um "?" =>

<code>1.9.3-p0 :040 > a.encode("ISO-8859-1", :invalid => :replace)
=> "bad: ?( okay"
</code>

Então, o ruby ​​tem inteligência para saber o que são bytes ruins no utf-8 e substituí-los por algo mais - ao converter para uma codificação diferente. Mas eu nãoquer para converter para uma codificação diferente, eu quero ficar utf8 - mas eu poderia querer aumentar se houver um byte inválido lá, ou eu poderia querer substituir bytes inválidos com caracteres de substituição.

Não há alguma maneira de obter ruby ​​para fazer isso?

atualizar Eu acredito que isso finalmente foi adicionado ao ruby ​​em 2.1, com o String # scrub presente na versão 2.1 para fazer isso. Então olhe para isso!

questionAnswers(9)

yourAnswerToTheQuestion