I am currently writing a program that takes in a file, loops through all of the lines.
The file contains a lot of variables + values in this format:
Message =
"alfjawejf1ij4l2jr183fhaalfjawejf1ij4l2jr183fhahalfjawejf1ij4l2jr183fhahalfjawejf1ij4l2jr183fhahalfjawejf1ij4l2jr183fhahh" //the string will encompass multiple
lines of length
Answer = ?
My program will modify the value within message and write it in a new file.
How do I store multiple lines of the value into one string (so I can modify it)?
I need it so that it recognizes "message", starts storing the next few lines, detects "answer" and stops.
For the string holding the message value, I believe some sort of concatenation will be used (concatenating multiple lines).
string[] file = System.IO.File.ReadAllLines(#path); //file is read
string pathNew = Path.GetDirectoryName(path) + "\\completed_" + Path.GetFileName(path);
using (StreamWriter writer = File.CreateText(#pathNew))
{
foreach (string line in file)
{
for (int i = 0; i < line.Length; i++)
{
if (line.Substring(0,6).Equals("Msg = "))
{
foreach (string msg in file)
{
}
}
}
}
}
You could create it pretty easily, if you would provide a method that returns an IEnumerable<string>, and then use the File.WriteAllLines( string, IEnumerable<string> ) utility method
A way you could do it could be
private IEnumerable<string> ReturnAllMessages( IEnumerable<string> lines )
{
bool isMessage = false;
foreach (var line in lines)
{
if (line.StartsWith('Msg ='))
{
isMessage = true;
// set a flag that the next lines are part of the message
// this would exclude the rest of the line from the results
// if you want it, you could use:
// yield return line.Substring('Msg ='.Length));
continue;
}
if (line.StartsWith('Answer ='))
{
// remove the flag
isMessage = false;
continue;
}
if (isMessage)
{
// yield a line that is a message
yield return line;
}
}
}
and then use the method in the following way
File.WriteAllLines( #newPath, ReturnAllMessages( File.ReadAllLines( #path ) ) );
(didn't really test the code though, so just use it as a reference ;) )
One way to do this would be to read all the text as a single string using File.ReadAllText, and then split it on "Message =" to get all the messages, and then split each message on "Answer = " to get the answer for each message (assuming the format is "Message = some message Answer = some answer Message = some other message Answer = some other answer").
It would be helpful if you included an actual sample from the file, since your code clearly was not written for the sample you've provided (there is no line where line.Substring(0,6).Equals("Msg = ") is true).
I've included a method in my sample below that creates a text file with a multi-line message, and then showed how you can read the message into a variable and display it in the console window.
Hope this helps:
private static void CreateFile(string filePath)
{
if (File.Exists(filePath)) File.Delete(filePath);
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
var fileLines = new List<string>
{
"Message = ",
"I weigh nothing, but you can still see me.",
"If you put me in a bucket, I make the bucket lighter.",
"What am I?",
"Answer = A hole",
"Message = ",
"What’s the difference between",
"a hippo and a Zippo?",
"Answer = ",
"A hippo is really heavy, ",
"and a Zippo is a little lighter."
};
File.WriteAllLines(filePath, fileLines);
}
private static void Main()
{
// Set this to a file that doesn't exist or that you don't care about
var filePath = #"f:\private\temp\temp.txt";
// Create a file with multi-line messages
CreateFile(filePath);
// Read all the file text
var fileText = File.ReadAllText(filePath);
// Split it into the message/answers
var messageAnswers = fileText.Split(new[] {"Message ="},
StringSplitOptions.RemoveEmptyEntries);
// Split each message into a message/answer array
foreach (var messageAnswer in messageAnswers)
{
var parts = messageAnswer.Split(new[] {"Answer ="},
StringSplitOptions.RemoveEmptyEntries);
var message = parts[0].Trim();
var answer = parts.Length > 1 ? parts[1].Trim() : "";
Console.WriteLine(message);
var userResponse = Console.ReadLine().Trim();
if (userResponse.Equals(answer, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Correct!");
}
else
{
Console.WriteLine("The actual answer is: " + answer);
}
}
GetKeyFromUser("\nDone! Press any key to exit...");
}
Related
My Issue:
I am looking into a text file and i need to delete all the lines, or use string.empty that does not meet the requirement. For example,
The requirement is 50000. There are words/text in the file and also numbers that are smaller than the requirement. How can i delete all line in a text file that do not meet the requirement? I do not want to be specific with the other values in the text file as they can differ.
My Research:
I have searched and found to delete specific values then rewrite them onto a new file which i am trying to do. I have found different ways that dont meet my needs. I am using what i have found below but am missing something to make it complete
My Effort:
DialogResult openFile = openFileDialog1.ShowDialog();
if (openFile == DialogResult.OK)
{
string file = openFileDialog1.FileName;
string content = File.ReadAllText(file);
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Text File|*.txt";
sfd.FileName = "New Text Doucment";
sfd.Title = "Save As Text File";
if (sfd.ShowDialog() == DialogResult.OK)
{
string path = sfd.FileName;
StreamWriter bw = new StreamWriter(File.Create(path));
bw.WriteLine(content);
bw.Close();
File.WriteAllLines(path, File.ReadAllLines(path).Select(x => string.Format("{0},", x)));
string newContent = File.ReadAllText(path);
newContent = newContent.Remove(newContent.LastIndexOf(","));
File.WriteAllText(path, newContent);
string secondContent = File.ReadAllText(path);
int number = int.Parse(File.ReadAllText(path));
if (checkBox1.Checked == true)
{
secondContent = secondContent.Replace("BRUSH(1,0)", string.Empty);
secondContent = secondContent.Replace("REGION 1,", string.Empty);
secondContent = secondContent.Remove(secondContent.LastIndexOf(","));
File.WriteAllText(path, secondContent);
if (secondContent.Contains())
{
number = 0;
secondContent = secondContent.Replace(number.ToString(), string.Empty);
File.WriteAllText(path, secondContent);
}
}
else if (checkBox2.Checked == true)
{
secondContent = secondContent.Replace("BRUSH(1,0),", ")),");
secondContent = secondContent.Replace("REGION 1,", string.Empty);
secondContent = secondContent.Remove(secondContent.LastIndexOf(","));
File.WriteAllText(path, secondContent);
}
//Just trying
foreach (char c in secondContent)
{
if (secondContent.All(char.IsDigit))
{
char = string.Empty;
}
}
}
}
What i am doing above:
Grabbing an existing file,
adding the contents to a new file,
add a comma at the end of each line,
removing the last comma at the end of the file.
removing a line that contains brush or region
Now here are examples of the file:
TYPE_CODE char(2),
DESCRIPT0 char(25),
TYPE_COD0 char(3),
DESCRIPT1 char(36),
DATA,
BRUSH(1,0),
REGION(1,0),
13502,
319621.99946835 110837.002493295,
319640.501385461 110850.59860145,
319695.199120806 110879.700271183,
319728.303041127 110879.300385649,
319752.898058391 110876.501186912,
319767.401120868 110872.702274339,
The numbers at the bottom of that example is what the entire document should look like
To address just the issue stated try the following:
//Get the lines from the file
List<string> lines = System.IO.File.ReadAllLines("MyFile.txt").ToList();
//Removed the lines which are empty or when split using ' ' contain items other the numbers >= 50000
double d = 0;
lines.RemoveAll(x => string.IsNullOrWhiteSpace(x) || x.TrimEnd(',').Split(' ').Any(y => !double.TryParse(y, out d) || double.Parse(y) < 50000));
//Write the new file
System.IO.File.WriteAllLines("MyFile2.txt", lines.ToArray());
To add a comma to the end of each line add the following lines before saving:
//Remove any existing ',' and add our own
lines = lines.Select(x => x.TrimEnd(',') + ",").ToList();
//Remove any trailing ',' from the last line
lines[lines.Count - 1] = lines[lines.Count - 1].TrimEnd(',');
(Edited to handle multiple numbers per line)
(Fixed conversion errors)
(Fixed for existing ',')
First, abstraction would be your friend here. Break up your code into different peices to make it a little easier to handle. Plus when you have to change your requirements later, you will have an easy spot to do it.
Second, File.ReadLines is also your friend because it will give you a collection of strings, which will let you use LINQ.
Which brings me to your third friend, LINQ, which will let you query the collection of file lines.
public void FormatFile(string sourcePath, string targetPath)
{
IEnumerable<String> originalContent = GetFileLines(sourcePath);
IEnumerable<String> formatedContent = ProcessFileLines(originalContent);
OutputResults(targetPath, formatedContent);
}
public IEnumerable<String> GetFileLines(string path) {
return File.ReadLines(path);
}
public IEnumerable<string> ProcessFileLines(IEnumerable<string> fileLines)
{
// In this method you can process the logic that applies to the whole
// set of file lines (e.g. lineCount, removing empyLines, etc)
return processedLines.Select(l => ProcessLine(l)
.Where(l => !string.IsNullOrEmpty(l))
.GetRange(0, MAX_LINE_COUNT);
}
public string ProcessLine(string fileLine)
{
// In this method just focus on logic applied to each specific line.
string s = fileLine.Substring(0, 5);
if (s.Equals("BRUSH", StringComparison.InvariantCultureIgnoreCase)
return string.Empty;
return fileLine;
}
public void OutputResults(string targetPath, IEnumerable<string> fileLines)
{
string outputText = fileLines.Join($",{Environment.NewLine}");
File.WriteAllText(targetPath, outputText);
}
So basically you can just call FormatFile(#"C:\mySource", #"C:\myTarget"); and you will be good to go.
I'm a beginner at C# programming.
I wanted to create a text file to the desktop in C# Console, which is wanted to add my input new string value to the created text file's new line.
This is my work:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace noteonce
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("New Word: ");
string newWord = Console.ReadLine();
string wlist = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + #"\list.txt";
TextWriter inject = new StreamWriter(wlist, true);
inject.WriteLine(newWord);
inject.Close();
Console.WriteLine("New word has been added! ");Console.ReadKey();
}
}
}
I created the file through the console, but I want each of my entered string to be unique, I did some look up on google but I'm so confused. I want the console to tell me that whether the new input already exists or not, If it is, to warn me as "It already exists! Input another word : ", If it does not exist, just to add it to the list. I need your assistance.
Thank you all for your attention. By the help of Mr.Ankitkumar Bhatt, This is my recent work :
static void Main(string[] args)
{
string wlist = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+#"\list.txt";
FileStream create = File.Open(wlist, FileMode.Create);
create.Close();
for (int i = 0; i < 100; i++)
{
Console.WriteLine("New Word"+#" ("+(100-i)+") :");
string newWord = Console.ReadLine();
string FileContents = File.ReadAllText(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + #"\list.txt");
TextWriter inject = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + #"\list.txt", true);
if (!FileContents.Contains(newWord))
{
inject.WriteLine(newWord);
inject.Close();
}
else
{
Console.WriteLine("It already exists!");
Console.ReadKey();
inject.Close();
}
}
}
But I want to point that, I want the program to recognize all of items in the list, by my last method, it quite works, but when I close, and open the program again, It doesn't give me the warning that New Word is already exist, doesn't add it to the file neither. How can I do the rest ?
In case of "no duplicate" please, have a look at HashSet<String>; you may find TextWriter and TextReader being too complex - try File.ReadLines(), File.AppendAllLines instead:
static void Main(string[] args) {
// better practice is paths combining
string path = Path.Combine(Environment.SpecialFolder.Desktop, "list.txt");
// unique (no duplicates) strings so far
HashSet<String> hash = new HashSet<string>(
File.ReadLines(path), // file to read from
StringComparer.OrdinalIgnoreCase); // let's ignore words' case ("World", "world")
Console.WriteLine("New Word: ");
string newWord = Console.ReadLine().Trim(); // let's trim spaces: "world " -> "world"
if (!string.IsNullOrEmpty(newWord)) // let's not add an empty string
if (!hash.Contains(newWord)) {
// add new word to the end of file
File.AppendAllLines(path, new string[] {newWord});
Console.WriteLine("New word has been added!");
}
else
Console.WriteLine("It already exists! Input another word");
else
Console.WriteLine("We don't add empty lines.");
Console.ReadKey();
}
In case you want to add several words, one after one (put an empty line to exit):
static void Main(string[] args) {
// better practice is paths combining
string path = Path.Combine(Environment.SpecialFolder.Desktop, "list.txt");
// unique (no duplicates) strings so far
HashSet<String> hash = new HashSet<string>(
File.ReadLines(path), // file to read from
StringComparer.OrdinalIgnoreCase); // let's ignore words' case ("World", "world")
while (true) {
Console.WriteLine("New Word: ");
string newWord = Console.ReadLine().Trim(); // let's trim spaces: "world " -> "world"
if (string.IsNullOrEmpty(newWord))
break;
if (hash.Add(newWord)) {
File.AppendAllLines(path, new string[] {newWord});
Console.WriteLine("New word has been added!");
}
else
Console.WriteLine("It already exists! Input another word.");
}
Console.ReadKey();
}
before injecting word check the word exists or not like below
string FileContents = File.ReadAllText(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + #"\list.txt");
if (!FileContents.Contains(newWord))
{
// Add to file //
}
this can be accomplished in multiple ways. I will present a solution that most closely will work with your code. There is definitely a more elegant way to accomplish this, but this is a quick and dirty way to accomplish that.
one way is to have a foreach check from your text file so:
var isWordPresent = false;
var textLines = File.ReadAllLines(wlist);
foreach (var line in textLines) {
if (line.contains(newWord) {
isWordPresent = true;
}
}
if (isWordPresent == false) {
inject.WriteLine(newWord);
inject.Close();
isWordPresent = false; //added this portion incase you run this code in a while loop
//so you can reuse it. You would need to have the boolean reset to false
}
1) Read the file and write its content to a string[] (Array of string):
var lines = File.ReadAllLines(wlist , Encoding.UTF8);
2) Read your input and check for duplicates:
var input = Console.ReadLine();
if (lines.Contains(input)) {
//Warning message
} else {
//Success message
}
I have 10 txt files in Debug\Tests\Text\ (10 txt files). I need to write a program to open all 10 files and updated every single file. I'm not sure how to do it. Now, I'm actually reading the folder and getting the file name and storing the file name in an array. Below is my code:
private void getFilesName()
{
string[] fileArray = Directory.GetFiles(#"Tests\Text");
//looping through the folder and get the fileNames
for (int i = 0; i<fileArray.Length; i++)
{
MessageBox.Show(fileArray[i]); // I'm doing this is to double check i manage to get the file name.
}
}
After doing this, it do read all the text file name, but the challenge now is for me to access the filename and updating every file in it. I have also created another method just for updating the values in the txt files, below is the code:
private bool modifySQLFile()
{
string destFileName = #"Tests\Text\" // I need the fileName?
string[] fileTexts = File.ReadAllLines(destFileName);
int counter = 0;
//Processing the File
foreach(string line in fileTexts)
{
//only read those non-comments line
if(line.StartsWith("--") == false)
{
//Start to replace instances of Access ID
if(line.Contains(Variable) == true)
{
fileTexts[counter] = fileTexts[counter].Replace(Variable, textBox2.Text);
}
}
counter++;
}
//check if file exists in the backup folder
if(File.Exists("Tests\\Text\\file name "+ textBox1.Text +".sql") == true)
{
MessageBox.Show("This file already exist in the backup folder");
return false;
}
else
{
//update the file
File.WriteAllLines(destFileName, fileTexts);
File.Move(destFileName, "Tests\\Text\\file name"+ textBox1.Text +".sql");
MessageBox.Show("Completed");
return true;
}
}
Your problem seems to be passing the filename variable from the loop to the method.
In order to do what you want, add a parameter to the method:
private bool ModifySQLFile(string filename)
{
string[] fileTexts = File.ReadAllLines(filename);
// ...
}
Then call the method with this parameter:
for (int i = 0; i<fileArray.Length; i++)
{
ModifySQLFile(fileArray[i]);
}
But in general you really don't want to treat a formal language as plaintext like you do. It's very easy to break the SQL like that. What if the user wanted to replace the text "insert", or replaces something with "foo'bar"?
First, implement one (file) modification:
private bool modifySQLFile(String file) {
// given source file, let´s elaborate target file name
String targetFile = Path.Combine(
Path.GetDirectoryName(file),
String.Format("{0}{1}.sql",
Path.GetFileNameWithoutExtension(file),
textBox1.Text));
// In case you want a back up
//TODO: given source file name, elaborate back up file name
//String backUpFile = Path.Combine(...);
// Check (validate) before processing: do not override existing files
if (File.Exists(targetFile))
return false;
//TODO: what if back up file exists? Should we override it? skip?
// if line doesn't start with SQL commentary --
// and contains a variable, substitute the variable with its value
var target = File
.ReadLines(file)
.Select(line => (!line.StartsWith("--") && line.Contains(Variable))
? line.Replace(Variable, textBox2.Text)
: line);
// write modified above lines into file
File.WriteAllLines(targetFile, target);
// In case you want a back up
// Move file to backup
//File.Move(file, backUpFile);
return true;
}
Then call it in the loop:
// enumerate all the text files in the directory
var files = Directory
.EnumerateFiles("#"Tests\Text", "*.txt");
//TODO: you may want filter out some files with .Where
//.Where(file => ...);
// update all the files found above
foreach (var file in files) {
if (!modifySQLFile(file))
MessageBox.Show(String.Format("{0} already exist in the backup folder", file));
}
Please, do not do:
Use Magic values: what is #"Tests\Text\" within your modifySQLFile
Mix UI MessageBox.Show(...) and logic: modifySQLFile returns true or false and it's caller who can display message box.
Materialize when it's not required (Directory.GetFiles, File.ReadAllLines)
If you would like to edit the files in parallel. With threads you can parallelize work.
for (int i = 0; i < fileArray.Length; i++)
new Thread(UpdateFileThread).Start(fileArray[i]);
private void UpdateFileThread(object path)
{
string filePath = (string)path;
//ToDo: Edit file
}
In your case you would create 10 Threads. That solution works, but is a bad pattern if you have to deal with more than 10 files.
Below i have posted the real time code ,which i have used project
protected void btnSqlfinder_Click(object sender, EventArgs e)
{
//Defining the path of directory where all files saved
string filepath = # "D:\TPMS\App_Code\";
//get the all file names inside the directory
string[] files = Directory.GetFiles(filepath);
//loop through the files to search file one by one
for (int i = 0; i < files.Length; i++)
{
string sourcefilename = files[i];
StreamReader sr = File.OpenText(sourcefilename);
string sourceline = "";
int lineno = 0;
while ((sourceline = sr.ReadLine()) != null)
{
lineno++;
//defining the Keyword for search
if (sourceline.Contains("from"))
{
//append the result to multiline text box
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
if (sourceline.Contains("into"))
{
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
if (sourceline.Contains("set"))
{
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
if (sourceline.Contains("delete"))
{
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
}
}
}
This code will fetch the multiple files in the given directory,and show the lines as per the keyword in a separate text.
But you can easily change as per your requirement,Kindly let me know your thoughts.
Thanks
I need to check certain columns of data to make sure there are no trailing blank spaces. At first thought I thought it would be very easy, but after attempting to achieve the goal I have got stuck.
I know that there should be 6-digits in the column I need to check. If there is less I will reject, if there are more I will trim the blank spaces. After doing that for the entire file, I want to write it back to the file with the same delimiters.
This is my attempt:
Everything seems to be working correctly except for writing the file.
if (File.Exists(filename))
{
using (StreamReader sr = new StreamReader(filename))
{
string lines = sr.ReadLine();
string[] delimit = lines.Split('|');
while (delimit[count] != "COLUMN_DATA_TO_CHANGE")
{
count++;
}
string[] allLines = File.ReadAllLines(#filename);
foreach(string nextLine in allLines.Skip(1)){
string[] tempLine = nextLine.Split('|');
if (tempLine[count].Length == 6)
{
checkColumn(tempLine);
writeFile(tempLine);
}
else if (tempLine[count].Length > 6)
{
tempLine[count] = tempLine[count].Trim();
checkColumn(tempLine);
}
else
{
throw new Exception("Not enough numbers");
}
}
}
}
}
public static void checkColumn(string[] str)
{
for (int i = 0; i < str[count].Length; i++)
{
char[] c = str[count].ToCharArray();
if (!Char.IsDigit(c[i]))
{
throw new Exception("A non-digit is contained in data");
}
}
}
public static void writeFile(string[] str)
{
string temp;
using (StreamWriter sw = new StreamWriter(filename+ "_tmp", false))
{
StringBuilder builder = new StringBuilder();
bool firstColumn = true;
foreach (string value in str)
{
if (!firstColumn)
{
builder.Append('|');
}
if (value.IndexOfAny(new char[] { '"', ',' }) != -1)
{
builder.AppendFormat("\"{0}\"", value.Replace("\"", "\"\""));
}
else
{
builder.Append(value);
}
firstColumn = false;
}
temp = builder.ToString();
sw.WriteLine(temp);
}
}
If there is a better way to go about this, I would love to hear it. Thank you for looking at the question.
edit:
file structure-
country| firstname| lastname| uniqueID (column I am checking)| address| etc
USA|John|Doe|123456 |5 main street|
notice the blank space after the 6
var oldLines = File.ReadAllLines(filePath):
var newLines = oldLines.Select(FixLine).ToArray();
File.WriteAllLines(filePath, newLines);
string FixLine(string oldLine)
{
string fixedLine = ....
return fixedLine;
}
The main problem with writing the file is that you're opening the output file for each output line, and you're opening it with append=false, which causes the file to be overwritten every time. A better approach would be to open the output file one time (probably right after validating the input file header).
Another problem is that you're opening the input file a second time with .ReadAllLines(). It would be better to read the existing file one line at a time in a loop.
Consider this modification:
using (StreamWriter sw = new StreamWriter(filename+ "_tmp", false))
{
string nextLine;
while ((nextLine = sr.ReadLine()) != null)
{
string[] tempLine = nextLine.Split('|');
...
writeFile(sw, tempLine);
I've seen a lot of answers about using Trim for whitespace, but I need to trim everything after the first space as in " ". I'll post the section of code that I am talking about first and then below it I'll post the whole thing. I also want to know how to get a "tab" space in between the file and line variables in the same location. Here is the snippet of code I'm talking about.
var files = from file in Directory.EnumerateFiles(filePath, "*.FCJ", SearchOption.AllDirectories)
from line in File.ReadLines(file)
where line.Contains(".FCM")
select Path.GetFileName(file + line);
foreach (var f in files)
{
lbMerges.Items.Add(f);
}
The variable "line" comes out as Text ~Space~ More Text. I want to eliminate the second section "More Text". I also would like to know how to get my ouput in a listview to show a tab in between the file name and the line that is read. Here is the entire code in case you need it.
private void rbActive_CheckedChanged(object sender, EventArgs e)
{
if (rbActive.Checked == true)
{
cbFullPath.Enabled = false;
cbFullPath.Visible = false;
lbMerges.Items.Clear();
lbPCL.Items.Clear();
string filePath = textBox1.Text;
try
{
var files = from file in Directory.EnumerateFiles(filePath, "*.FCJ", SearchOption.AllDirectories)
from line in File.ReadLines(file)
where line.Contains(".FCM")
select Path.GetFileName(file + line);
foreach (var f in files)
{
lbMerges.Items.Add(f);
}
}
catch (UnauthorizedAccessException UAEx)
{
MessageBox.Show(UAEx.Message);
}
catch (PathTooLongException PathEx)
{
MessageBox.Show(PathEx.Message);
}
}
else
{
cbFullPath.Enabled = true;
cbFullPath.Visible = true;
}
}
Here you go:
void Main()
{
string test = "text some more text";
string result = test.Substring(0,test.IndexOf(" "));
// prints "text"
Console.WriteLine(result);
}
void Main()
{
string column2 = "Put me at column 15";
List<string> test = new List<string>() {"text some more text",
"longtext somemore text",
"t some more text" };
List<string> result = test
.Select(s => s.Substring(0,s.IndexOf(" ")).PadRight(15) + column2)
.ToList();
// output
// text Put me at column 15
// longtext Put me at column 15
// t Put me at column 15
foreach(string s in result)
Console.WriteLine(s);
}