1

次のようなデータを含むtxtファイルがあります。

:10FF800000040B4E00040B4E00047D1400047D148D
:10FF900000040B4E0004CF6200040B4E00040B4E15
:10FFA00000040B4E00040B4E00040B4E00040B4EDD
:10FFB00000047D1400047D1400047D1400047D14ED
:10FFC00000040B4E000000000000000000000000D4
:10FFD0000000000000040B4E0000000000000000C4
:10FFE0000000000000000000000000000000000011
:10FFF0000000000000000000060000000000BFF844
:020000020000FC
:020000040014E6
:043FF0005AC8A58C7A
:00000001FF

私がC#プログラムでやりたいのは、特定の行の前後に行を追加することです。たとえば、次の行を追加します。

:020000098723060

この行の前:

:020000020000FC

File.ReadLines( "file.txt")。Last();を使用してみました。しかし、それは私に最後のものを与えるだけです、私が3番目または4番目が欲しい場合はどうなりますか?また、ファイル内の「:」を識別する方法はありますか?

4

6 に答える 6

11

最も簡単な方法は、ファイル全体をメモリに読み込むことに満足している場合、次のようになります。

public void InsertLineBefore(string file, string lineToFind, string lineToInsert)
{
    List<string> lines = File.ReadLines(file).ToList();
    int index = lines.IndexOf(lineToFind);
    // TODO: Validation (if index is -1, we couldn't find it)
    lines.Insert(index, lineToInsert);
    File.WriteAllLines(file, lines);
}

public void InsertLineAfter(string file, string lineToFind, string lineToInsert)
{
    List<string> lines = File.ReadLines(file).ToList();
    int index = lines.IndexOf(lineToFind);
    // TODO: Validation (if index is -1, we couldn't find it)
    lines.Insert(index + 1, lineToInsert);
    File.WriteAllLines(file, lines);
}

これを行うにははるかに効率的な方法がありますが、このアプローチは本当に簡単です。

于 2013-01-31T23:08:58.550 に答える
3

ブルートフォースアプローチ

string[] lines = File.ReadAllLines("file.txt");
using(StreamWrite sw = new StreamWriter("file.txt"))
{
   foreach(string line in lines)
   {
       if(line == ":020000020000FC")
          sw.WriteLine(":020000098723060");
       sw.WriteLine(line);
   }
}
于 2013-01-31T23:09:18.113 に答える
2

特にターゲットファイルのサイズが大きくなる傾向がある場合は、1行ずつ読み取りと書き込みを行う方がよいと思います。

using (StreamReader r = new StreamReader("Test.txt"))
{
    using (StreamWriter w = new StreamWriter("TestOut.txt"))
    {
        while (!r.EndOfStream)
        {
            string line = r.ReadLine();
            w.WriteLine(line);
            if (line == ":020000020000FC")
                w.WriteLine(":020000098723060");
        }
        w.Close();
        r.Close();
    }
}
于 2013-01-31T23:14:30.973 に答える
0

「:」文字は実際には実装に役立ちません。行はすべて改行で区切られています。

これは、すべてをメモリにロードしたり、別のファイルに出力したりしないメソッドの試みです。

決して小川を渡らないでください。

static Int32 GetCharPos(StreamReader s)
{
    var ia = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField;
    Int32 charpos = (Int32)s.GetType().InvokeMember("charPos", ia, null, s, null);
    Int32 charlen = (Int32)s.GetType().InvokeMember("charLen", ia, null, s, null);
    return (Int32)s.BaseStream.Position - charlen + charpos;
}

static void Appsert(string data, string precedingEntry = null)
{
    if (precedingEntry == null)
    {
        using (var filestream = new FileStream(dataPath, FileMode.Append))
        using (var tw = new StreamWriter(filestream))
        {
            tw.WriteLine(data);
            return;
        }
    }

    int seekPos = -1;
    using (var readstream = new FileStream(dataPath, 
        FileMode.Open, FileAccess.Read, FileShare.Write))
    using (var writestream = new FileStream(dataPath, 
        FileMode.Open, FileAccess.Write, FileShare.Read))
    using (var tr = new StreamReader(readstream))
    {
        while (seekPos == -1)
        {
            var line = tr.ReadLine();
            if (line == precedingEntry)
                seekPos = GetCharPos(tr);
            else if (tr.EndOfStream)
                seekPos = (int)readstream.Length;
        }

        writestream.Seek(seekPos, SeekOrigin.Begin);
        readstream.Seek(seekPos, SeekOrigin.Begin);
        int readLength = 0;
        var readBuffer = new byte[4096];
        var writeBuffer = new byte[4096];
        var writeData = tr.CurrentEncoding.GetBytes(data + Environment.NewLine);
        int writeLength = writeData.Length;
        writeData.CopyTo(writeBuffer, 0);
        while (true & writeLength > 0)
        {
            readLength = readstream.Read(readBuffer, 0, readBuffer.Length);
            writestream.Write(writeBuffer, 0, writeLength);
            var tmp = writeBuffer;
            writeBuffer = readBuffer;
            writeLength = readLength;
            readBuffer = tmp;
        }                
    }
}
于 2013-02-01T01:41:42.877 に答える
0

サイズなどの理由でファイル全体を読み込まないようにしているのかどうかはわかりませんが、ファイルを読み込んでから置き換えることはできません...例:

var text = readFile(somePath);
writeFile( text.replace(":020000020000FC\n",":020000098723060\n:020000020000FC\n") , somePath);
于 2013-01-31T23:17:49.040 に答える
0

これが解決策ですが、最善ではないかもしれませんが、機能します。

public void AddTextToFile(string filePath, int lineNumber, string txt) //zero based lineNumber
{
        Collection<string> newLines = new Collection<string>(File.ReadAllLines(filePath).ToList());


        if (lineNumber < newLines.Count)
            newLines.Insert(lineNumber, txt);
        else 
            newLines.Add(txt);

        using (StreamWriter writer = new StreamWriter(filePath, false))
        {
            foreach (string s in newLines)
                writer.WriteLine(s);
        }
}

そして、「:」が文字列に存在するかどうかを判断することについての質問に答えるには、答えは「はい」です。上記の例では、行にそれが含まれているかどうかを次のように確認できます...

if(newLines[idx].Contains(':'))
//do something
于 2013-02-01T00:21:37.280 に答える