Как использовать Ruby для замены текста в файле ресурсов VC ++, когда кодировка полностью отключена? - PullRequest
5 голосов
/ 09 марта 2012

У меня есть простой управляемый проект VC ++ в решении.Он содержит файл ресурсов app.rc, который используется для хранения информации о сборке (версия, продукт, авторские права и т. Д.).Если я открою файл в моем текстовом редакторе , он скажет, что это Unicode (UTF-16 LE BOM) .И Visual Studio отображает его правильно, только если я выберу Юникод - кодовая страница 1200 .

VS_VERSION_INFO VERSIONINFO
 FILEVERSION 0,0,0,0
 PRODUCTVERSION 0,0,0,0
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x40004L
 FILETYPE 0x2L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "CompanyName", "My Company, LLC"
            VALUE "FileVersion", "0.0.0.0"
            VALUE "InternalName", "myassembly.dll"
            VALUE "LegalCopyright", "Copyright (C) 2011 My Company, LLC"
            VALUE "OriginalFilename", "myassembly.dll"
            VALUE "ProductName", "The Product"
            VALUE "ProductVersion", "0.0.0.0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END

Я использую Ruby / Rake для настройки и запуска локальных сборок.Часть этой сборки заменяет версию в ресурсах сборки.Я прочитал бы в файле gsub номера версий и выписал файл обратно.Однако, когда я читаю в файле, я получаю мусор

irb(main):001:0> File.open("source\\myproject\\app.rc").read
=> "\xFF\xFE/\x00/\x00 \x00M\x00i\x00c\x00r\x00o\x00s\x00o\x00f\x00t\x00 \x00V\x00i\x00s\x
00u\x00a\x00l\x00 \x00C\x00+\x00+\x00 \x00g\x00e\x00n\x00e\x00r\x00a\x00t\x00e\x00d\x00 \x
00r\x00e\x00s\x00o\x00u\x00r\x00c\x00e\x00 \x00s\x00c\x00r\x00i\x00p\x00t\x00.\x00\n\x00\n
\x00/\x00/\x00\n\x00\n\x00#\x00i\x00n\x00c\x00l\x00u\x00d\x00e\x00 \x00\"\x00r\x00e\x00s\x

Руби думает, что это кодировка IBM437 .

irb(main):006:0> File.open("source\\myproject\\app.rc").external_encoding
=> #<Encoding:IBM437>

И если я выписываю содержимоев другой файл я получаю странную кодировку (мой текстовый редактор клянется, что Unicode (UTF-16 BE BOM) ).

䴀椀挀爀漀猀漀昀琀 嘀椀猀甀愀氀 䌀⬀⬀ 最攀渀攀爀愀琀攀搀 爀攀猀漀甀爀挀攀 猀挀爀椀瀀琀⸀ഊ
਀⼀⼀ഊ
਀⌀椀渀挀氀甀搀攀 ∀爀攀猀漀甀爀挀攀⸀栀∀ഊ
਀ഊ

Как мне открыть / прочитать этот файлправильно?


Хорошо, теперь я могу правильно прочитать файл, если предоставлю правильные кодировки .

irb(main):003:0> File.open("source\\myproject\\app.rc", "rb:UTF-16LE")
=> #<File:source\myproject\app.rc>

Однако я не могу заменить версиюпока что нет.

irb(main):003:0> c = File.open("source\\myproject\\app.rc", "rb:UTF-16LE").read
irb(main):007:0> c.gsub("0.0.0.0", "0.0.5.0")
Encoding::CompatibilityError: incompatible encoding regexp match (US-ASCII regexp with UTF-16LE string)

Но я не могу предоставить кодировку для gsub.Нужно ли кодировать шаблон и замещающие строки?

1 Ответ

5 голосов
/ 09 марта 2012

Чтение и запись файла

Итак, первое, что я попробовал, - это поиск / запись UTF-16LE файлов в Ruby.Я нашел этот вопрос и ответ , который рекомендует всегда открывать файлы в режиме текстового файла (t) в Windows.

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

Итак, я сделал это

irb(main):002:0> File.open("source\\myproject\\app.rc", "rt:UTF-16LE")
ArgumentError: ASCII incompatible encoding needs binmode

Я не знаю, что такое binmode, но это может быть как-то связано с режимом двоичных файлов (b).Итак, давайте попробуем это вместо этого.

irb(main):003:0> File.open("source\\myproject\\app.rc", "rb:UTF-16LE")
=> #<File:source\myproject\app.rc>

Эврика!Тем не менее, я все еще вижу некоторые сумасшедшие управляющие символы и другие непечатаемые элементы (\n).

\r\n//\r\n\r\nVS_VERSION_INFO VERSIONINFO\r\n FILEVERSION 0,0,0,0\r\n PRODUCTVERSION 0,0,0
,0\r\n FILEFLAGSMASK 0x3fL\r\n#ifdef _DEBUG\r\n FILEFLAGS 0x1L\r\n#else\r\n FILEFLAGS 0x0L
\r\n#endif\r\n FILEOS 0x40004L\r\n FILETYPE 0x2L\r\n FILESUBTYPE 0x0L\r\nBEGIN\r\n    BLOC
K \"StringFileInfo\"\r\n    BEGIN\r\n        BLOCK \"040904b0\"\r\n        BEGIN\r\n

Замена строк

Итак, вы заметите, что делать простой gsub какэто приводит к ошибке кодирования.

irb(main):004:0> c.gsub("0.0.0.0","0.0.5.0")
Encoding::CompatibilityError: incompatible encoding regexp match (US-ASCII regexp with UTF-16LE string)

Если вы читаете , то первый аргумент документа , gsub превращается в Regexp, что показано, что кодируемое !Итак, давайте попробуем это ...

irb(main):005:0> c.gsub("0.0.0.0".encode("UTF-16LE"),"0.0.5.0".encode("UTF-16LE"))
=> myproduct.dll\"\r\n            VALUE \"ProductName\", \"My Product\"\r\n            VALU
E \"ProductVersion\", \"0.0.5.0\"\r\n        END\r\n    END\r\n    BLOCK \"VarFileInfo\"\r
\n    BEGIN\r\n        VALUE \"Translation\", 0x409, 1200\r\n    END\r\nEND\r\n\r\n#endif

Вы можете увидеть некоторые замены, работающие в предоставленном мною фрагменте.

...