3

I have a multiline string (from a txt-file using ReadAllText). the string looks like this:

R;0035709310000026542510X0715;;;  
R;0035709310000045094410P1245;;;  
R;0035709310000026502910Z1153;;;

I want to put in a ";" in each line on place 22, so it looks like this:

R;00357093100000265425;10X0715;;;  
R;00357093100000450944;10P1245;;;  
R;00357093100000265029;10Z1153;;;

The multiline string always contain the samme amount of data but not always 3 lines - sometimes more lines.

How do I make this? Please show some code.

Thanks alot :-) Best regards Bent

Alex R.
  • 4,664
  • 4
  • 30
  • 40

6 Answers6

5

Try this ...

using System.IO;
using System.Linq;

var lines = File.ReadAllLines("data.txt");
var results = lines.Select(x => x.Insert(22, ";"));
Antony Scott
  • 21,690
  • 12
  • 62
  • 94
  • 1
    That does take twice the memory. Not a problem here (the OP mentions "more than 3 lines") but I wouldn't recommend this for Gigabyte data. – H H Aug 04 '11 at 08:13
  • @Henk - because I'm not operating on the original data, and basically making a copy of it? – Antony Scott Aug 04 '11 at 08:21
  • Yes, and you block the entire array from GC for the duration. – H H Aug 04 '11 at 08:26
4

Step 1, don't use ReadAllText(). Use ReadAllLines() instead.

 string[] myLinesArray = File.ReadAllLines(...);

Step 2, replace all lines (strings) with the changed version.

for(int i = 0; i < myLinesArray.Length; i++)
    myLinesArray[i] = myLinesArray[i].Insert(22, ";");

Step 3, Use WriteAllLines()

H H
  • 263,252
  • 30
  • 330
  • 514
1

try this

string s ="R;0035709310000026542510X0715;;;";
s = s.Insert(22,";");
Console.Write(s);

or use Regex

    string s =@"R;0035709310000026542510X0715;;;
R;0035709310000045094410P1245;;;
R;0035709310000026502910Z1153;;;";
    string resultString = Regex.Replace(s, "^.{22}", "$0;", RegexOptions.IgnoreCase | RegexOptions.Multiline);
    Console.Write(resultString);
Monday
  • 1,403
  • 12
  • 10
1

I think it would be better to read the source file line by line and modify the line as you go.

You could build up your new file in a StringBuilder or, if is large, write it to a new file, used to replace the source at the end.

Something like this,

using System.IO;

string tempFileName = Path.GetTempFileName();

using (StreamWriter target = File.CreateText(tempFileName))
{
    using(StreamReader source = file.OpenText("YourSourceFile.???"))
    {
        while (source.Peek() >= 0)
        {
            target.WriteLine(source.ReadLine().Insert(22, ";"));
        }
    }
}

File.Delete("YourSourceFile.???");
File.Move(tempFileName, "YourSourceFile.???");

This approach becomes is especially appropriate for large files since it avoids loading all the data into memory at once but the performance will be good for all but very large files or, I guess, if the lines were very (very) long.

Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • Yes, for very large files this would be the only option. But note that the OP mentions "more than 3 lines". And in Fx4+ you can use File.GetLines() for this. – H H Aug 04 '11 at 08:24
  • @Henk Holterman, getting philosophical considering the set of all possible files with more than 3 lines, there are infinitely more "large" files "than" small files since the set is without an upper limit. However, I'm willing to concede that the set of real world files is likely to be much more heavily weighted to the "small" side, so I guess the point is moot and only the OP can say. Is `File.GetLines()` in the next .Net release, a function that used `yield return` to give us an `IEnumerable` would be useful, ofc, I could write my own extension with a `StreamReader`. – Jodrell Aug 04 '11 at 08:37
  • Not philosophy, just ballpark. – H H Aug 04 '11 at 08:38
  • I never can be sure which side of my finger is dry :-) – Jodrell Aug 04 '11 at 08:41
0

You could go with Regex:

myString = Regex.Replace(myString, @"(^.{22})", @"\1;", RegexOptions.Multiline);

Explanation: you have 3 string arguments:

  • 1st one is the input
  • 2nd is the pattern
  • 3rd is the replacement string

In the pattern:

  • () is a capturing group: you can call it in the replacement string with \n, n being the 1-based index of the capturing group in the pattern. In this case, \1 is whatever matched "(^.{22})"
  • "^" is the beginning of a line (because we set the multiline options, otherwise it would be the beginning of the input string)
  • "." matches any character
  • {22} means you want preceeding pattern (in this case ".", any character) 22 times

So what that means is: "in any line with 22 characters or more, replace the 22 first characters by those same 22 characters plus ";"

Evren Kuzucuoglu
  • 3,781
  • 28
  • 51
  • 2
    Don't you think it's a little (over)complicated? When the req's say Insert, look for an Insert() method. When the req's talk about patterns, use RegEx. – H H Aug 04 '11 at 08:12
  • yes maybe it's overkill. You'd have to compare performance, but I think since regex are compiled internally by the CLR the first time they get used, if you're going to run the code several times, the regex is probably faster. – Evren Kuzucuoglu Aug 04 '11 at 08:18
  • Not just performance. I was thinking about readability. For performance, see @jodrel's answer. – H H Aug 04 '11 at 08:29
  • OK for performance, actually reading the file is going to be the most important time consumer anyway. But I don't see readability as a problem here, the pattern is simple and if someone is not used to Regex, it's a good start here. Anyway, the ReadAllLines solution seems better to me too when I see it. I'll plus it! – Evren Kuzucuoglu Aug 04 '11 at 08:49
0

As suggested, you can use the Insert method to achieve your goal.

If your file contains a lot of lines and you need to work on 1 line at a time, you might also consider reading it line by line from a TextReader.

vc 74
  • 37,131
  • 7
  • 73
  • 89