从文本文件替换字符串的一部分

时间:2018-11-20 20:50:04

标签: c#

我要替换.txt文件字符串行的第二部分。我的.txt是:

private final int fps = 1000; // Usually it's 60.

private SurfaceHolder surfaceholder;
private Panel panel;
private boolean running;
private Canvas canvas;

public MainThread(SurfaceHolder surfaceholder, Panel panel) {

    super();

    this.surfaceholder = surfaceholder;
    this.panel = panel;

}

public void Enable() {

    running = true;

}

public void Disable() {

    running = false;

}

@Override
public void run() {

    long updatetime = 1000000000 / fps;
    long starttime;
    long processtime;
    long waittime;

    while (running) {

        starttime = System.nanoTime();

        canvas = null;

        try {

            synchronized (surfaceholder) {

                // Takes about 10ms when the fps value is 1000
                canvas = surfaceholder.lockCanvas();

                // 7-8ms
                panel.ConfigureNextFrame(canvas);

            }

        } catch (Exception ex) {

        } finally {

            if (canvas != null) {

                // 0.5-1.5ms
                surfaceholder.unlockCanvasAndPost(canvas);

            }

        }

        processtime = System.nanoTime() - starttime;

        waittime = updatetime - processtime;

        try {

            if (waittime > 0) {

                this.sleep(waittime / 1000000, (int) (waittime % 1000000));

            }

        } catch (Exception ex) {

        }

    }

}

例如,我想这样替换它:

admin|admin
ruiliberal|123456789

我的代码是:

admin|12345
ruiliberal|123456789

这行不通,它删除了最后一行。

5 个答案:

答案 0 :(得分:2)

您的代码存在一些问题。

第一个问题是:永远不要以纯文本格式存储密码。这是一个可怕的想法。如果这是生产系统,请停止您正在做的事情,然后重新开始,因为这很不好。如果这只是学习中的一种练习,而不是将来的实际用途,请继续...

第二,您正在呼叫File.ReadLines()File.ReadAllLines(),而您又不需要。只需使用File.ReadLines(),因为它返回一个IEnumerable,并让您处理结果,而不用等待所有结果都返回(File.ReadAllLines()就是这样)。

接下来,您应该制作一个可以真正为您做修改的方法,以便您可以在需要时重复使用它:

private static IEnumerable<string> ModifyLines(IEnumerable<string> inputLines)
{
    foreach(var line in inputLines)
    {
        var split = line.Split('|');
        yield return $"{split[0]}|12345";
    }
}

这将迭代输入IEnumerableyield return一个新字符串。确实没有任何理由修改split数组,只需要获取所需的字符串(用户名),然后使用字符串插值将您的静态密码(“ 12345”)格式化即可。

然后一切都说完了,您需要使用File.WriteAllLines()方法将结果写入文件,而不是 File.WriteAllText()。您的代码无法正常工作的原因之一是因为您在循环中编写了所有文本。如果您read the docs查看该方法的实际用途,您将看到为什么该方法无法按您使用的方式工作。

所以总会是:

private void buttonGravaPass_Click(object sender, EventArgs e)
{
    var lines = ModifyLines(File.ReadLines(dirConta));
    File.WriteAllLines(dirConta, lines.ToArray());
}

提琴here

答案 1 :(得分:1)

这是我的选择...

using System;
using System.Collections.Generic;
using System.IO;

namespace Q_53401300
{
    class Program
    {

        static string dirConta = "C:\\temp2\\ListOfPWD.txt";

        static void Main(string[] args)
        {
            buttonGravaPass_Click(null, null);

        }

        private static void buttonGravaPass_Click(object sender, EventArgs e)
        {
            List<string> newLinesToWrite = new List<string>();
            using (System.IO.StreamReader sr = new StreamReader(dirConta))
            {
                string currentLine = string.Empty;
                while ((currentLine = sr.ReadLine()) != null)
                {
                    string[] parts = currentLine.Split(new char[] { '|' });
                    //if (parts[0] == Users.user)
                    //{
                    parts[0] = parts[0].Remove(parts[0].Length - 5);
                    parts[1] = parts[1] + "12345";
                    newLinesToWrite.Add($"{parts[0]}|{parts[1]}");
                    //}
                }
            }
            System.IO.File.WriteAllLines(dirConta, newLinesToWrite);
        }
    }
}

答案 2 :(得分:1)

如果您要在此处使用代码是经过测试的工作版本,只需更改代码中与以下代码相关的行即可:

string[] lines = File.ReadLines(dirConta).ToArray();

        for (int i = 0; i < lines.Length; i++)
        {

            string[] parts = lines[i].Split(new char[] { '|' });
            if (parts[0] == Users.user)
            {
                lines[i] = lines[i].Remove(lines[i].Length - 5);
                lines[i] = lines[i] + "12345";
            }

        }
        File.WriteAllText(dirConta, string.Join("\n",lines));

我希望此帮助能够帮助其他答案指出代码遗漏之处。

答案 3 :(得分:0)

因此,我认为这段代码有些错误。

1。)您的for循环:

for(int i = 0; i < lines.Count(); i++)
{ [...] }

您不必再次调用ReadAllLines()。 还是做:

foreach(string line in lines){[...]}

2。)分成几个部分: 由于您只有一个拆分字符,因此可以这样调用:

string[] parts = lines[i].Split('|');

3。)分配新的字符串值: 为什么不这样做:

lines[i] = $"{parts[0]}|12345";

4。)我不建议在每个循环中都写入文件。只需将File.WriteAllText(dirConta, lines[i]);放入循环中

5。)如果要存储数据,我强烈建议您研究对象序列化。它使很多东西变得更容易。 参见:Json Serialization in C#

答案 4 :(得分:0)

您的方法存在一些问题。首先,连接字符串时,应尽量避免使用+。请改用$""string.Format。其次,在进行事件编程时,最好编写事件方法调用的另一种方法,以便避免不必要的工作(例如,写入文件)而阻塞UI线程。查看System.IO的文档,可以使用File.ReadLines遍历文本行,因此我这样做不是代替读取文件两次来获取行数。另外,不要使用Remove+,而要使用Replace;这要容易得多。最后,您需要确保将 all 写为您所拥有的文本。现在,您只在写第一行。

string dirConta = $"{Environment.CurrentDirectory}/Bd/contas.txt";

private async Task ModifyFileAsync()
{
    var output = new List<string>();
    using (var reader = new StreamReader(dirConta))
    {
        while ((var line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
        {
            var parts = line.Split('|');
            if (parts[0] == Users.user)
            {
                var newLine = line.Replace(parts[1], "12345");
                lines.Add(newLine);
            }
            else
            {
                lines.Add(line);
            }
        }
    }

    using (var writer = new StreamWriter(dirConta))
    {
        foreach (var line in lines)
        {
            await writer.WriteLineAsync(line).ConfigureAwait(false);
        }
    }
}

private async void buttonGravaPass_Click(object sender, EventArgs e)
{
    await ModifyFileAsync().ConfigureAwait(false);
}