一个查找替换文本的例子(C#实现)

来源:互联网 发布:深圳市宜众软件怎么样 编辑:程序博客网 时间:2024/05/16 12:19

问题来源于游戏汉化,游戏剧本文件资源拆包后的样子如下:


CMD-x05SoundBgmPlay int 2ShowBackground string "ev901a0.iph" int 10CMD-x05SetLine string " 戦いは終わった。"ShowLinesSetLine string " 当事者達には長い戦いだったかもしれないが、未"SetLine string " 来の歴史書には数行で記される戦い。"ShowLinesSetLine string " ヴィスト王国が他国に侵攻し、抵抗した周辺諸国"SetLine string " は団結してこれに抵抗。"SetLine string " そしてヴィスト王国が滅ぼされた。"ShowLinesSetLine string " ただ、それだけの戦い。"ShowLinesSetLine string " しかし、その戦いには数多の人物が関わった。"ShowLinesSetLine string " この時代を、そして次の時代を作る者達が。"ShowLinesSetLine string " この戦いを乗り越えた者達は、それぞれに未来を"SetLine string " 歩み始める。"ShowLinesJumpConditional f`short 220 bool false *label99JumpConditional f`short 210 bool false *label99CMD-x38 int 2 nullCMD-x26 f`short 332_label99JumpConditional f`short 208 bool false *label120CMD-x38 int 3 nullCMD-x26 f`short 333_label120JumpConditional f`short 221 bool false *label141CMD-x38 int 4 nullCMD-x26 f`short 334_label141JumpConditional f`short 210 bool false *label198JumpConditional f`short 222 bool false *label182CMD-x38 int 10 nullCMD-x26 f`short 335CMD-x02 *label198Jump *label198_label182CMD-x38 int 11 nullCMD-x26 f`short 335CMD-x02 *label198_label198JumpConditional f`short 223 bool false *label255JumpConditional f`short 224 bool false *label239CMD-x38 int 5 nullCMD-x26 f`short 336CMD-x02 *label255Jump *label255_label239CMD-x38 int 6 nullCMD-x26 f`short 336CMD-x02 *label255_label255JumpConditional f`short 201 bool false *label351JumpConditional f`short 202 bool false *label351JumpConditional f`short 222 bool false *label351JumpConditional f`short 223 bool false *label351JumpConditional f`short 225 bool false *label351JumpConditional f`short 226 bool false *label351JumpConditional f`short 227 bool false *label351JumpConditional f`short 228 bool false *label351CMD-x38 int 1 nullCMD-x26 f`short 331CMD-x02 *label415_label351JumpConditional f`short 335 bool true *label403JumpConditional f`short 336 bool true *label387CMD-x38 int 7 nullCMD-x26 f`short 337CMD-x02 *label415_label387CMD-x38 int 8 nullCMD-x26 f`short 337CMD-x02 *label415_label403CMD-x38 int 9 nullCMD-x02 *label415_label415CMD-x06CMD-x06

可以看到,其中带有许多游戏的命令,我们不可能将这样的文本交给翻译,于是我们将文字转化成易读的形式:


m 0  戦いは終わった。m 1  当事者達には長い戦いだったかもしれないが、未m 2  来の歴史書には数行で記される戦い。m 3  ヴィスト王国が他国に侵攻し、抵抗した周辺諸国m 4  は団結してこれに抵抗。m 5  そしてヴィスト王国が滅ぼされた。m 6  ただ、それだけの戦い。m 7  しかし、その戦いには数多の人物が関わった。m 8  この時代を、そして次の時代を作る者達が。m 9  この戦いを乗り越えた者達は、それぞれに未来をm 10  歩み始める。

翻译拿到了上面的文字后进行翻译,翻译后的结果如下:


m 0  战争结束了。m 1  虽然当事者们或许进行了很长时间的战斗,m 2  但战斗在未来的历史书中仅留下了数行。m 3  威斯特王国侵略了其他国家,周边诸国m 4  团结起来与之对抗。m 5  然后威斯特王国被灭亡了。m 6  仅仅,是这样的战斗罢了。m 7  不过,这场战斗牵连了众多的人物。m 8  开创了这个时代,以及下个时代的人们。m 9  还有跨越了这场战争的人们,开始走向m 10  各自的未来。m 11 

现在的问题是,要想把翻译好的文字封回游戏,必须将翻译好的文字嵌入到最开始的那种代码当中,问如何实现文字替换?


最直接的想法是一次性的读取整个原始代码,然后将翻译内容一行一行替换掉,但这样有个问题,那就是可能会误操作掉其他部分。比如说m0后面是123,m5后面是12345,那么在替换m0的时候就会把m5后面的文字也替换掉,这样就使得想要替换m5的时候找不到原始文本。

如果非要按照上面的思路来,那么有一个补救方法,那就是将日文文本按照长度排序,由长到短依次替换,这样就不会出现误替换的现象了。

那么有没有其他方法呢?当然有。注意到剧本文本只出现在“SetLine string”之后,所以只要保证第n次替换只替换第n个“SetLine string”之后的文本即可。

C#的实现如下,程序不难,但仍有可参考的地方,故记录下来以作备忘:


using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.IO;namespace stringReplace{    class Program    {        static void Main(string[] args)        {            //String orgCode = System.IO.File.ReadAllText("D:/Test/代码/ending00.txt");            StreamReader orgCodeStream = File.OpenText("D:/Test/代码/ending00.txt");            StreamReader jpStream = File.OpenText("D:/Test/日文/ending00.txt");            StreamReader chsStream = File.OpenText("D:/Test/中文/ending00.txt");            String jp = null;            String chs = null;            String newCode = null;            String temp = null;            while (true)            {                jp = jpStream.ReadLine();                chs = chsStream.ReadLine();                if (String.IsNullOrEmpty(jp) || String.IsNullOrEmpty(chs)) break;                while (true)                 {                    temp = orgCodeStream.ReadLine();                    if (temp.Equals(null)) System.Console.WriteLine("Error1");                    if (temp.IndexOf("SetLine string") != -1) break;                    else if (!String.IsNullOrEmpty(newCode)) newCode = String.Concat(newCode, "\r\n", temp);                         else newCode = String.Concat(newCode, temp);                }                temp=temp.Replace(jp.Substring(jp.IndexOf("  ")+2), chs.Substring(chs.IndexOf("  ")+2));                if(!String.IsNullOrEmpty(newCode)) newCode = String.Concat(newCode, "\r\n", temp);                else newCode = String.Concat(newCode, temp);            }            temp = orgCodeStream.ReadLine();            while (!String.IsNullOrEmpty(temp))            {                if (!String.IsNullOrEmpty(newCode)) newCode = String.Concat(newCode, "\r\n", temp);                else newCode = String.Concat(newCode, temp);                temp = orgCodeStream.ReadLine();            }            newCode = String.Concat(newCode, "\r\n");            StreamWriter sw = new StreamWriter("D:/1.txt");            sw.Write(newCode);            sw.Flush();            sw.Close();            jpStream.Close();            chsStream.Close();            orgCodeStream.Close();        }    }}


0 0