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

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


CMD-x05
SoundBgmPlay int 2
ShowBackground string "ev901a0.iph" int 10
CMD-x05
SetLine string " 戦いは終わった。"
ShowLines
SetLine string " 当事者達には長い戦いだったかもしれないが、未"
SetLine string " 来の歴史書には数行で記される戦い。"
ShowLines
SetLine string " ヴィスト王国が他国に侵攻し、抵抗した周辺諸国"
SetLine string " は団結してこれに抵抗。"
SetLine string " そしてヴィスト王国が滅ぼされた。"
ShowLines
SetLine string " ただ、それだけの戦い。"
ShowLines
SetLine string " しかし、その戦いには数多の人物が関わった。"
ShowLines
SetLine string " この時代を、そして次の時代を作る者達が。"
ShowLines
SetLine string " この戦いを乗り越えた者達は、それぞれに未来を"
SetLine string " 歩み始める。"
ShowLines
JumpConditional f`short 220 bool false *label99
JumpConditional f`short 210 bool false *label99
CMD-x38 int 2 null
CMD-x26 f`short 332
_label99
JumpConditional f`short 208 bool false *label120
CMD-x38 int 3 null
CMD-x26 f`short 333
_label120
JumpConditional f`short 221 bool false *label141
CMD-x38 int 4 null
CMD-x26 f`short 334
_label141
JumpConditional f`short 210 bool false *label198
JumpConditional f`short 222 bool false *label182
CMD-x38 int 10 null
CMD-x26 f`short 335
CMD-x02 *label198
Jump *label198
_label182
CMD-x38 int 11 null
CMD-x26 f`short 335
CMD-x02 *label198
_label198
JumpConditional f`short 223 bool false *label255
JumpConditional f`short 224 bool false *label239
CMD-x38 int 5 null
CMD-x26 f`short 336
CMD-x02 *label255
Jump *label255
_label239
CMD-x38 int 6 null
CMD-x26 f`short 336
CMD-x02 *label255
_label255
JumpConditional f`short 201 bool false *label351
JumpConditional f`short 202 bool false *label351
JumpConditional f`short 222 bool false *label351
JumpConditional f`short 223 bool false *label351
JumpConditional f`short 225 bool false *label351
JumpConditional f`short 226 bool false *label351
JumpConditional f`short 227 bool false *label351
JumpConditional f`short 228 bool false *label351
CMD-x38 int 1 null
CMD-x26 f`short 331
CMD-x02 *label415
_label351
JumpConditional f`short 335 bool true *label403
JumpConditional f`short 336 bool true *label387
CMD-x38 int 7 null
CMD-x26 f`short 337
CMD-x02 *label415
_label387
CMD-x38 int 8 null
CMD-x26 f`short 337
CMD-x02 *label415
_label403
CMD-x38 int 9 null
CMD-x02 *label415
_label415
CMD-x06
CMD-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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值