The following code is used by me to convert the entries in a datagrid view into a text file! (The process of creating a text file is successfull) After converting the datagrid view entries into a string I append a string from outside(This should appear on the last line of the textfile)
private void button1_Click_1(object sender, EventArgs e) // converting data grid value to single string
{
StringBuilder file = new StringBuilder();
for (int i = 0; i < dataGridView2.Rows.Count; i++)
{
for (int j = 0; j < dataGridView2.Rows[i].Cells.Count; j++)
{
var val = dataGridView2.Rows[i].Cells[j].Value;
if (val == null)
continue;//IF NULL GO TO NEXT CELL, MAYBE YOU WANT TO PUT EMPTY SPACE
var s = val.ToString();
file.Append(s.Replace(Environment.NewLine, " "));
}
file.AppendLine(); // NEXT ROW WILL COME INTO NEXT LINE
}
file.Append("Hello");
using (StreamWriter sw = new
StreamWriter(#"C:\Users\sachinthad\Desktop\VS\Tfiles\file.txt"))
{
sw.Write(x);
}
}
But when I check text file the outside string("Hello" in this scenario) appears on the last line but there is an additional space above it! How can i remove this additional space?
You can use string.Joinwhich concatenates a collection of strings with a separator in between. Together with refactoring it to use linq .Select:
var lines = dataGridView2.Rows.Select(row => string.Join(" ",
row.Cells.Select(cell => cell.Value).Where(val => val != null));
Then of course you can also use it on the entire collection of lines to concatenate them with a new line:
// Will eliminate problem of extra \n at the end
var result = string.Join(Environment.NewLine, lines);
If you prefer having the loops instead of linq then what you can do in the inner loop is add the values to a List<string> initialized in the outer loop. After the inner loop ends to use string.Join on the values of that list. Psudocode:
for each row:
List<string> items = new List<string>();
for each column in row:
items.Add(value of column);
file.Append(string.Join(" ", items));
Related
I have a text file and required to have all 7 elements including the empty ones to be parsed into an array for further processing. However, there are no unique delimiter to be make use of except for whitespaces and some of the data/value will come with whitespace. Example per "Data Sample" and some of the block will have null entry. How can i make this happen?
Snippet of Data
Actual Sample Data
My end results would be some ting similar like below:
Array[0]:123456789
Array[1]:HLTX
Array[2]:5
Array[3]:BT5Q02
Array[4]:4SV
Array[5]:D8041
Array[6]:LIANG LIN
My code for the above function for now per below and it will omit the empty values. Which likely will missed out some of the data required.
string[] splitlinecontent = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var OrderNum = splitlinecontent[0];
var OrderType = splitlinecontent[1];
int OrderQTY = int.Parse(splitlinecontent[2]);
var OrderSINumInRpt = splitlinecontent[3];
var OrderHoldMod = splitlinecontent[5];
var SalesPerson = splitlinecontent[6];
I think bestpractice for these files is to use TextFieldParser from Microsoft.VisualBasic.FileIO;
using (var parser = new TextFieldParser(fileName))
{
parser.TextFieldType = FieldType.FixedWidth;
parser.SetFieldWidths(3, 7, 10, 13, 8, 6, 1, 7, -1);
while (!parser.EndOfData)
{
var fields = parser.ReadFields();
But I guess it isn't that hard to code the stuff yourself.
Based on the screenshot of your sample data, your columns have a fixed charsize of ten chars. You now can simply read the sample data line by line and split the lines by this fixed size.
public static List<List<string>> GetRecords(string path, bool hasColHeader, int colLength, int colCount){
//Result will be stored in lists
List<List<string>> result = new List<List<string>>();
//Get the sample file
string[] records = File.ReadAllLines(path,Encoding.UTF8);
//Go for each line through the data from sample file
for(int n = 0; n<records.Length;n++){
//create new list for this line
result.Add(new List<string>());
//here you can do something with headers. for simplification i do nothing with them and continue with next line.
if(n==0 && hasColHeader){
continue;
}
//go for each column (colCount specifies the count of columns)
for(int i = 0; i< colCount ;i++){
//if the length of the line is not devisible by colLength, you have to put some spaces to match the columns size
//not the best way to do this but this is not the major point of this question
if(records[n].Length % colLength != 0){
int charsToAdd = (colLength * colCount) - records[n].Length;
string spaces = "";
for(int s = 0; s< charsToAdd; s++){
spaces += " ";
}
records[n] += spaces;
}
//add the result to the currently created list
result[n].Add(records[n].Substring(i*colLength,colLength).Trim());
}
}
return result;
}
You can use this code like this:
static void Main(string[] args)
{
List<List<String>> list = GetRecords(#"C:\temp\DataSample.txt",true, 10, 7);
}
The data in list looks like this:
List[0]:List[0]:123456789
List[0]:List[1]:HLTX
List[0]:List[2]:5
List[0]:List[3]:BT5Q02
List[0]:List[4]:4SV
List[0]:List[5]:D8041
List[0]:List[6]:LIANG LIN
List[1]:List[0]:3835443
List[1]:List[1]:HLTX
List[1]:List[2]:1
...
Here you can optimize two things by youreself.
Calculate the size of the columns by the chars between headers. The columnsize will alsways be the start of a columnheader and the start of the next columnheader. The charcount between this two points, will be the size of the column.
Find a better way to get the last column! :D i dont think what i've done is good. There a better ways to do this.
I have an array that holds user and passwords in user:pass form, and I like ro remove lines which pass is less than 8 characters or password uses repetitive chars like 111111,22222222222,...
I have tried string.take but it takes lines completely, I need conditional deletion.
public string[] lines;
//open file dialogue to load the user pass file
lines = File.ReadAllLines(openFileDialog1.FileName);
//delete button click event
//the place that I have problem
I have email:pass combination like so:
email1:1234567895121
email2:12345
email4:11111
email5"454545454545
and I would like the output to be like
email1:1234567895121
email5"454545454545
Just loop the characters of every line and see if the current is equal to the previous:
public string[] lines = File.ReadAllLines(openFileDialog1.FileName);
var filteredLines = new List<string>(lines);
foreach(var line in lines)
{
var pair = line.Split(':');
var mail = pair[0];
var pass = pair[1]; // may throw exception on invalid format of your line
for(int i = 1; i < pass.Length; i++)
{
if(pass[i] == pass[i - 1])
{
filteredLines.Remove(line);
break; // will break inner loop and continue on next line
}
}
}
string[] lines =
{
"email1:1234567895121",
"email2:12345",
"email3:22222222222",
"email4:11111",
"email5:454545454545"
};
lines = lines
.Where(s =>
{
string pass = s.Split(new[] { ':' }, 2)[1];
return pass.Length >= 8 && pass.Any(c => c != pass[0]);
})
.ToArray();
foreach (var s in lines)
Console.WriteLine(s);
Output:
email1:1234567895121
email5:454545454545
I have hundreds of files in a directory. Many of the text files have the Code Column values as blank and i need to iterate over all the text files and fill it. I am able to write the code to add the code value in a new line, but i am not able to write it under code column. String value is: "STRINGTOENTER". I only want it be entered in the 1st line after the header. The last line should be left alone
Id Code File_Number Suffix Check_Number Check_Date
047 7699 01 99999 11/11/2012
1 -6.15
Below is my code snippets that add the value at a newline. I think I need to do a regular expression or a tab delimited type solution here.
public static void AddAStringtoAllTextFiles()
{
try
{
string path = #"C:\Users\ur\Desktop\TestFiles\";
string[] fileEntries = Directory.GetFiles(path);
for (int i = 0; i < fileEntries.Length; i++)
{
File.AppendAllText(fileEntries[i], "STRINGTOENTER" + Environment.NewLine);
}
}
catch (Exception e)
{
throw e;
}
}
EDITED
please try this with the assumption that its space(s) delimited.
its working on my VS2017 and kindly add the using statement on the top as below .
using System.Text.RegularExpressions
public static void AddAStringtoAllTextFiles()
{
try
{
string path = #"C:\Users\ur\Desktop\TestFiles\";
var fileEntries = Directory.GetFiles(path);
int indexPosition2InsertData=1;
foreach (var entry in fileEntries)
{
var lines = File.ReadAllLines(entry);
for (var index = 1; index < lines.Length; index++) //starting from first row, leaving the header
{
var split= Regex.Split(lines[index].Trim(), #"\s{1,}"); //reading the line with space(s)
if(split.Length==5) //edited //checking if the row is not blank
{
var list = split.ToList(); //convert to list to insert
list.Insert(indexPosition2InsertData, "STRINGTOENTER"); //inserting at the index 1
lines[index] = string.Join("\t", list);
}
}
File.WriteAllLines(entry, lines);
}
}
catch (Exception e)
{
throw e;
}
}
I am getting this after running the code.
Id Code File_Number Suffix Check_Number Check_Date
047 STRINGTOENTER 7699 01 99999 11/11/2012
1 -6.15
Please let me know if this helps.
Assuming each file has the right tab delimitation (and that's a big assumption given the question quality)
// Get the files
var fileEntries = Directory.GetFiles(path);
// iterate through each file name
foreach (var entry in fileEntries)
{
// Load the File into the lines array
var lines = File.ReadAllLines(entry);
// Iterate over each line
if(lines.Length >1)
{
// Split the lines by tab
var split = lines[1].Split('\t');
// your code should be at array index 1
split[1] = "STRINGTOENTER";
// write the whole line back
lines[1] = string.Join("\t", split);
// write the file
File.WriteAllLines(entry, lines);
}
}
Note : you should probably do this with a CSV parser, this was only for academic purposes and totally untested
I want to show my desired solution based on your input. Amazing how a simple piece of code can contribute to solving a larger and a complex problem. Thanks again!
public static void AddClientCodetoAllTextFiles(string update_batch_with_clientcode, string batchfilepathtobeupdated)
{
try
{
var fileEntries = Directory.GetFiles(#batchfilepathtobeupdated.Trim());
foreach (var entry in fileEntries)
{
var lines = File.ReadAllLines(entry);
if (lines.Length > 1)
{
for (int i = 1; i < lines.Length - 1; i++)
{
var split = lines[i].Split('\t');
split[1] = update_batch_with_clientcode.Trim();
lines[i] = string.Join("\t", split);
File.WriteAllLines(entry, lines);
}
}
}
}
catch (Exception e)
{
throw e;
}
}
I am trying to randomly read a huge .txt file. It has tons of paragraphs separated by a full line of empty space prior and post each paragraph. I would like each time I randomly read that it pulls up a full intact paragraph without any characters or words missing for the sake of context. I appreciated the help in advance.
I added a for loop just to test it out and see if I can at some point include a way to recognize consecutively running empty space. That would only work post already selected the starting point obviously if applied.
public static string GetRandomLine(string filename)
{
var lines = File.ReadAllLines(filename);
var lineNumber = _rand.Next(0, lines.Length);
string reply = lines[lineNumber];
return reply ;
}
Try the following:
public static string[] GetRandomParagraph(string filePath)
{
if (File.Exists(filePath))
{
string text = File.ReadAllText(filePath);
string[] paragraphs = text.Split(new string[] { "\n\n" }, StringSplitOptions.None);
return paragraphs[new Random().Next(0, paragraphs.Length)].Split('\n');
}
else
throw new FileNotFoundException("The file was not found", filePath);
}
I really hope that is that what you are looking for.
// This builds a list of Paragraph first
public static List<string> GetParagraphs(string filename)
{
var paragraphs = new List<string>();
var lines = File.ReadAllLines(filename);
bool newParagraph = true;
string CurrentParagraph = string.Empty;
// Build the list of paragraphs by adding to the currentParagraph until empty lines and then starting a new one
foreach(var line in lines)
{
if(newParagraph)
{
CurrentParagraph = line;
newParagraph = false;
}
else
{
if(string.IsNullOrWhiteSpace(line))// we're starting a new paragraph, add it to the list of paragraphs and reset current paragraph for next one
{
paragraphs.Add(CurrentParagraph);
CurrentParagraph = string.Empty;
newParagraph = true;
}
else // we're still in the same paragraph, add the line to current paragraph
{
newParagraph += (Environment.NewLine + line);
}
}
}
// Careful, if your file doesn't end with a newline the last paragraph won't count as one, in that case add it manually here.
}
public static Random rnd = new Random();
// And this returns a random one
public static string GetRandomParagraph(string fileName)
{
var allParagraphs = GetParagraphs(filename);
allParagraphs[rnd.Next(0,allParagraphs.length-1)]; // pick one of the paragraphs at random, stop at length-1 as collection indexers are 0 based
}
Note that if you're always reading from the same file this could be much faster by only calling GetParagraphs once and keeping the list of paragraphs in memory.
Try this:
public static string GetRandomLine(string filename)
{
var lines = File.ReadAllLines(filename);
var lineNumber = _rand.Next(0, lines.Length - 1);
var blankBefore = lineNumber;
var blankAfter = lineNumber + 1;
string reply = "";
while (lines[blankBefore].Length > 0)
{
blankBefore--;
}
while (lines[blankAfter].Length != 0)
{
blankAfter++;
}
for ( int i = blankBefore + 1; blankBefore < blankAfter; blankBefore++)
{
reply += lines[i];
}
return reply;
}
Based on your description, I'm assuming the file begins and ends with a blank line. By setting the exclusive upper bound of the random line to be one less than the length of lines, you avoid the chance of the random line being the last line of the file. If the random line is a blank line, blankBefore will be the index of that line, otherwise, it will be back tracked until it reaches the previous blank. blankAfter starts as the index of the next line after the random line and if that line is not blank, blankAfter is increased until it is the index of the next blank line.
Once you have the index of the blank lines before and after the target paragraph, simply append the lines between them to reply.
If the first and last lines of the file are not blank, you would need to verify that blankBefore and blankAfter remain within the bounds of the array.
I made some modifications to the code provided above by #TheCoderCrab. I turned the method to a string method so it would return a string. I simply added a for loop append all the characters of the paragraph array on to a new string which returns it to the main. Thank you.
public static string GetRandomParagraph(string filePath)
{
if (File.Exists(filePath))
{
string text = File.ReadAllText(filePath);
string[] paragraphs = text.Split(new string[] { "\n\n" }, StringSplitOptions.None);
string [] paragraph = paragraphs[new Random().Next(0, paragraphs.Length)].Split('\n');
//Added a for loop to build the string out of all the characters in the 'paragraph' array index.
string pReturn = "";
for (int a = 0; a < paragraph.Length; a++)
{
//Loop through and consecutively append each character of mapped array index to a return string 'pReturn'
pReturn = pReturn + paragraph[a].ToString();
}
return pReturn;
}
else
throw new FileNotFoundException("The file was not found", filePath);
}
To get intact paragraphs
public static string GetRandomParagraph(string fileName)
{
/*
Rather than reading all the lines, read all the text
this gives you the ability to split by paragraph
*/
var allText = File.ReadAllText(fileName);
// Use as separator for paragraphs
var paragraphSeparator = $"{Environment.NewLine}{Environment.NewLine}";
// Treat large white spaces after a new line as separate paragraphs
allText = Regex.Replace(allText, #"(\n\s{3,})", paragraphSeparator);
// Split the text into paragraphs
var paragraphs = allText.Split(paragraphSeparator);
// Get a random index between 0 and the amount of paragraphs
var randomParagraph = new Random().Next(0, paragraphs.Length);
return paragraphs[randomParagraph];
}
Example of a text file below
text_file a
Text_ID "441124_aad0656_1234"
Text_FILE_NAME
I would like to keep only last index of string "1234"
StreamReader streamReader = new StreamReader(text);
string text2;
while ((text2 = streamReader.ReadLine()) != null)
{
num++;
string[] array3 = text2.Split(new char[0]);
if (array3[0] == "Text_ID")
{
string[] array4 = array3[1].Split(new char[] {'_'});
string value = "Text_ID" + " " + '"' + array4[1];
streamWriter.WriteLine(value);
}
else
{
streamWriter.WriteLine(text2);
}
}
try below code, and hope it should work for you.
var startsWith = "Text_ID";
var allLines = File.ReadAllLines("a.txt").ToList();
allLines = allLines.Select(ln =>
{
if(ln.StartsWith(startsWith))
{
var finalValue = ln.Split(' ')[1].Trim('"').Split('_').Last();
//get update line
return string.Format("{0} \"{1}\"", startsWith, finalValue);
}
return ln;
}).ToList();
//Write back to file.
File.WriteAllLines("a.txt", allLines.ToArray());
Content before code execution.
Record 1
Text_ID "441124_aad0656_1234"
other content.
Record 2
Text_ID "Deepak_Sharma"
other content for line 2
Content in file after execution.
Record 1
Text_ID "1234"
other content.
Record 2
Text_ID "Sharma"
other content for line 2
You could use File.ReadAllLines to read the file into an array, then search through the array for the line you want to change, replace that line with the new string, and then use File.WriteAllLines to write the array back to the file:
var filePath = #"f:\public\temp\temp.txt";
// The string to search for
var searchTxt = "Text_ID";
// Read all the lines of the file into an array
var fileLines = File.ReadAllLines(filePath);
// Loop through each line in the array
for(int i = 0; i < fileLines.Length; i++)
{
// Check if the line begins with our search term
if (fileLines[i].Trim().StartsWith(searchTxt, StringComparison.OrdinalIgnoreCase))
{
// Get the end of the line, after the last underscore
var lastPartOfLine = fileLines[i].Substring(fileLines[i].LastIndexOf("_") + 1);
// Combine our search string, a quote, and the end of the line
fileLines[i] = $"{searchTxt} \"{lastPartOfLine}";
// We found what we were looking for, so we can exit the for loop now
// Remove this line if you expect to find more than one match
break;
}
}
// Write the lines back to the file
File.WriteAllLines(filePath, fileLines);
If you only want to save the last four lines of the file, you can call Skip and pass in the Length of the array minus the number of lines you want to keep. This skips all the entries up to the number that you want to save:
// Read all the lines of the file into an array
var fileLines = File.ReadAllLines(filePath);
// Take only the last 4 lines
fileLines = fileLines.Skip(fileLines.Length - 4).ToArray();