开发者

how to insert row in first line of text file?

开发者 https://www.devze.com 2022-12-22 10:34 出处:网络
I have a test file that con开发者_如何学Gotains 1,2,3 2,3,4 5,6,7 I want to insert this into the first line: A,B,C

I have a test file that con开发者_如何学Gotains

1,2,3
2,3,4
5,6,7

I want to insert this into the first line: A,B,C

So that I get:

A,B,C
1,2,3
2,3,4
5,6,7

How can I do this?


Similar to the previous answers, but this illustrates how to do what you want to do while minimizing memory consumption. There is no way around reading through the entire file you want to modify, even if you open it in a read/write stream, because you can't "insert" data.

static void WriteABC(string filename)
{
    string tempfile = Path.GetTempFileName();
    using (var writer = new StreamWriter(tempfile))
    using (var reader = new StreamReader(filename))
    {
        writer.WriteLine("A,B,C");
        while (!reader.EndOfStream)
            writer.WriteLine(reader.ReadLine());
    }
    File.Copy(tempfile, filename, true);
}


I think this answer is easier and faster:

public static void WriteToFile(string Path, string Text)
{
    string content = File.ReadAllText(Path);
    content = Text + "\n" + content;      
    File.WriteAllText(Path, content);
}

Then you can call it:

WriteToFile("yourfilepath", "A,B,C");


Here is a link that explains how to use the TextReader (StreamReader) and TextWriter (StreamWriter) classes in C#.

http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=132

Though this is specific to C#, the approach could be relatively the same across many languages.

(Note: There are several ways to do this, this is just one idea that comes quickly to mind.)

Essentially, you could read in the contents of your text file into a string, find the beginning of that string, write your information (A,B,C with your carriage returns or line feeds) and then write that information back out into the text file overwriting the original contents and save.


Late to the party...

Good question. You can use this code:

static void WriteABC2(string filename)
{
    string tempfile = Path.GetTempFileName();
    using (var writer = new FileStream(tempfile, FileMode.Create))
    using (var reader = new FileStream(filename, FileMode.Open))
    {
        var stringBytes = Encoding.UTF8.GetBytes("A,B,C" + Environment.NewLine);
        writer.Write(stringBytes, 0, stringBytes.Length);

        reader.CopyTo(writer);
    }
    File.Copy(tempfile, filename, true);
    File.Delete(tempfile);
}

This code is based on the excellent Jake answer, but I use FileStream instead of StreamWriter and StreamReader. There are big performance improvements (even 4X faster from my test) using FileStream when big files are processed. Just to be a little clear, I made some test and I reported the results below.

How I made tests

I created 7 files. Each file contains 10^X lines and its name is file<line count>.txt. So the list of the files is:

| File name       | Line count | File size |
|-----------------|------------|-----------|
| file1.txt       |          1 | 66 byte   |
| file10.txt      |         10 | 678 byte  |
| file100.txt     |        100 | 6,72 KB   |
| file1000.txt    |       1000 | 68,2 KB   |
| file10000.txt   |      10000 | 692 KB    |
| file100000.txt  |     100000 | 6,85 MB   |
| file1000000.txt |    1000000 | 69,5 MB   |

Each line of each file is composed as follows:

<line index starting from 0> - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

For example, the first two lines of file10.txt are:

0 - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
1 - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

I used the below code to make tests and to get the function execution duration:

var stopwatch = new Stopwatch();

long abcTotalDuration = 0;
long abc2TotalDuration = 0;

string fileInput = "file1.txt";
string outputFolder = "output";

for (int i = 0; i < 100; i++)
{
    string filename1 = Path.Combine(outputFolder, Guid.NewGuid().ToString());
    string filename2 = Path.Combine(outputFolder, Guid.NewGuid().ToString());

    stopwatch.Restart();
    WriteABC(fileInput, filename1);
    stopwatch.Stop();
    abcTotalDuration += stopwatch.ElapsedMilliseconds;

    stopwatch.Restart();
    WriteABC2(fileInput, filename2);
    stopwatch.Stop();
    abc2TotalDuration += stopwatch.ElapsedMilliseconds;

    File.Delete(filename1);
    File.Delete(filename2);
}

Console.WriteLine("ABC : " + abcTotalDuration.ToString());
Console.WriteLine("ABC2: " + abc2TotalDuration.ToString());

// Just to wake me up :-)
Console.Beep(800, 1000);

Console.ReadKey();

The test consists of prepending A,B,C(new line) for each specified file. The result is saved in separate file (only for test).

I launched the code 5 times for each input file (specified in fileInput variable). WriteABC and WriteABC2 functions are executed 100 times each every time I launch the code.

Here are the results (all in ms):

Processing file1.txt

      | ABC | ABC2 |
      |-----|------|
      | 285 |  305 |
      | 356 |  352 |
      | 435 |  371 |
      | 355 |  313 |
      | 362 |  372 |
|-----|-----|------|
  AVG | 359 |  343 |
|-----|-----|------|

Processing file10.txt

      | ABC | ABC2 |
      |-----|------|
      | 256 |  251 |
      | 273 |  323 |
      | 355 |  347 |
      | 350 |  314 |
      | 315 |  286 |
|-----|-----|------|
  AVG | 310 |  304 |
|-----|-----|------|

Processing file100.txt

      | ABC | ABC2 |
      |-----|------|
      | 247 |  253 |
      | 239 |  246 |
      | 357 |  353 |
      | 387 |  334 |
      | 333 |  329 |
|-----|-----|------|
  AVG | 313 |  303 |
|-----|-----|------|

Processing file1000.txt

      | ABC  | ABC2  |
      |------|-------|
      |  977 |   924 |
      |  784 |   738 |
      |  818 |   764 |
      | 1142 |  1101 |
      |  975 |   903 |
|-----|------|-------|
  AVG |  939 |   886 |
|-----|------|-------|

Processing file10000.txt

      | ABC  | ABC2  |
      |------|-------|
      | 1150 |   748 |
      | 1147 |   811 |
      | 1069 |   654 |
      | 1181 |   799 |
      | 1234 |   805 |
|-----|------|-------|
  AVG | 1156 |   763 |
|-----|------|-------|

Processing file100000.txt

      | ABC  | ABC2  |
      |------|-------|
      | 5485 |  1769 |
      | 5268 |  1528 |
      | 5296 |  1555 |
      | 5308 |  1529 |
      | 5289 |  1553 |
|-----|------|-------|
  AVG | 5329 |  1587 |
|-----|------|-------|

Processing file1000000.txt

      | ABC   | ABC2   |
      |-------|--------|
      | 49034 |  12633 |
      | 52116 |  12484 |
      | 51643 |  12109 |
      | 52022 |  12359 |
      | 53145 |  12716 |
|-----|-------|--------|
  AVG | 51592 |  12460 |
|-----|-------|--------|

The difference becomes remarkable from file10000.txt.


You cannot 'insert' anything in a Text file.

You will have to

  • copy the contents
  • inert extra data at the right time
  • close the files
  • delete the original and rename the new one to the old name


@Jake: StringBuilder is better and easiest

public static void WriteToFile(string path, string text)
{
        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.AppendLine("a,b,c");
        stringBuilder.Append(File.ReadAllText(path)).AppendLine();
        File.WriteAllText(path, stringBuilder.ToString()); 
}

Edit: But StringBuilder has a buffer limit: Maximum Capacity 2147483647

0

精彩评论

暂无评论...
验证码 换一张
取 消