I'm writing a program for some data entry I have to periodically do. I have begun testing a few things that the program will have to do but i'm not sure about this part.
What i need this part to do is:
read a .txt file of data
take the first 12 characters from each line
take the first 12 characters from each line of the data that has been entered in a multi-line text box
compare the two lists line by line
if one of the 12 character blocks from the multi-line text box match one of the blocks in the .txt file then overwrite that entire line (only 17 characters in total)
if one of the 12 character blocks from the multi-line text box DO NOT match any of the blocks in the.txt file then append that entire line to the file
thats all it has to do.
i'll do an example:
TXT FILE:
G01:78:08:32 JG05
G08:80:93:10 JG02
G28:58:29:28 JG04
MULTI-LINE TEXT BOX:
G01:78:08:32 JG06
G28:58:29:28 JG03
G32:10:18:14 JG01
G32:18:50:78 JG07
RESULTING TXT FILE:
G01:78:08:32 JG06
G08:80:93:10 JG02
G28:58:29:28 JG03
G32:10:18:14 JG01
G32:18:50:78 JG07
as you can see lines 1 and 3 were overwriten, line 2 was left alone as it did not match any blocks in the text box, lines 4 and 5 were appended to the file.
thats all i want it to do.
How do i go about this?
Thanks in advance
Edit
The code i'm using is this:
private void WriteToFile()
{
// Read all lines from file into memory
System.IO.StreamReader objReader = new System.IO.StreamReader("Jumpgate List.JG");
List<String> fileTextList = new List<String>();
do
{
fileTextList.Add(objReader.ReadLine());
}
while (objReader.Peek() != -1);
objReader.Close();
// Read all lines from the Input textbox into memory
System.IO.StringReader objReaderi = new System.IO.StringReader(txtInput.Text);
List<String> inputTextList = new List<String>();
do
{
inputTextList.Add(objReaderi.ReadLine());
}
while (objReaderi.Peek() != -1);
objReaderi.Close();
for(int i=0;i<fileTextList.Count;i++)
{
for(int j=0;j<inputTextList.Count;j++)
//compare the first 12 characters of each string
if (String.Compare(fileTextList[i], 0, inputTextList[j], 0, 12) == 0) // strings are equal
{
//replace the fileTextList string with the inputTextList string
fileTextList[i] = inputTextList[j];
// now that you have matched you inputTextList line you remember not to append it at the end
inputTextList[j] = String.Empty; // or nothing
}
}
for(int i=0;i<inputTextList.Count;i++)
{
if (!string.IsNullOrEmpty(inputTextList[i])) fileTextList.Add(inputTextList[i]);
}
System.IO.StreamWriter objWriter = new System.IO.StreamWriter("Jumpgate List.JG");
// Overwrite the Jumpgate List.JG file using the updated fileTextList
objWriter.Write(fileTextList);
objWriter.Close();
}
However, when i open the txt file all i get is: System.Collections.Generic.List`1[System.String]
I'm not going to write the whole code for doing this but it would be something like this:
Disclaimer: I have not used a code editor to try the code, just wrote it here, hopefully you'll get the idea and fill in the missing pieces :)
1) get all the lines in the file in a list. Something like this
StreamReader rd = new StreamReader("sadasd");
List<String> llist = new List<String>();
do
{
llist.Add(rd.ReadLine());
} while (rd.Peek() != -1);
2) get all the lines in your multiline text box (the procedure should be similar to the one above): multiTextList
3) now that you can compare the content of the 2 lists iterating through them
for(int i=0;i<fileTextList.Count;i++)
{
for(int j=0;j<multiTextList.Count;j++)
//compare the first 12 characters of each string
if String.Compare(fileTextList[i], 0, multiTextList[j], 0, 12) == 0 // strings are equal
{
//replace the initial line with whatever you want
fileTextList[i] = //whatever
// now that you have matched you multiTextList line you remember not to append it at the end
multiTextList[j] = String.empty // or nothing
}
}
4) at the end you will have in fileTextList the initial rows, modified where necessary
In multiTextList you will have only the lines that were not matched so we add them to the initial file rows
for(int i=0;i<multiTextList.Count;i++)
{
if !string.isnullorempty(multitextlist[i]) fileTextList.add(multitextlist[i])
}
5) now in fileTextList you have all the rows you require so you can print them one by one in a file and you have your result
StringBuilder lSb = new StringBuilder();
for (int i = 0; i < fileTextList.Count; i++)
{
lSb.AppendLine(fileTextList[i]);
}
File.WriteAllText(#"C:/test2.txt",lSb.ToString());
In C:/test2.txt you should have the results.
Hope this helps!
// this variable maps the timestamps to complete lines
var dict = new Dictionary<string, string>();
// create the map of stamp => line for the original text file
string fileLine = file.ReadLine();
string fileStamp = fileLine.Substring(0, 12);
dict[fileStamp] = fileLine;
// now update the map with results from the text input. This will overwrite text
// strings that already exist in the file
foreach (string inputLine in textInputString.Split('\n'))
{
string inputStamp = inputLine.Substring(0, 12);
dict[inputStamp] = inputLine;
}
// write out the new file with the updated lines
foreach (string line in dict.Values)
{
outputFile.WriteLine(line);
}
if the file is large, loading the entire file into a dictionary to update a handful of lines from a textfield is probably excessive.
In pseudocode I would probably:
Create a list of booleans or other structure to track if a line was matched.
open the file in read/write mode.
For each line in file
{
for each unmatched line in text field
{
If stamps match
Update file
record that it was matched
}
}
for each unmatched line in text field
{
append to file
}
If the lines are fixed width, you can probably optimize by only reading the stamp rather than the whole line. If they match your file pointer is in the right spot to start writing, if not you move to the next line.
Related
I'm trying to copy data from textfile1 to a new textfile (textfile2). but there's a specific line that i wish to exclude. i found a way to get the line where data i want to exclude is from.
What i'm doing here is that i'm checking if "testfile.txt" contains the string inputted by the user from textbox1. if the file does contain said input, it would then check if that same input is also available in "textfile1".
string old = #"textfile1.txt";
string new = #"textfile2.txt";
string test = #"testfile.txt";
string[] line = File.ReadAllLines(test);
for (int i = 0; i < line.Length; i++)
{
if (line[i].Contains(textbox1.Text))
{
string fileData = File.ReadAllText(path);
for (int n = 0; n < line.Length; n++)
{
if (line[n].Contains(textbox1.Text))
{
n++; //gets line number
//other code
}
}
}
}
now what i want to do is to copy everything in that textfile1 except the line wherein the inputted data was found.
SAMPLE DATA
textfile1.txt (id,item,price)
0001,apple,5
0002,banana,3
0003,mango,6
user inputs 0002 in textbox1
SUPPOSED OUTPUT
textfile2.txt
0001,apple,5
0003,mango,6
"why not just delete that line from the file?" well, i tried but yeah i'm having troubles with is too so i tried doing this instead.
I've been trying all sorts of things but i can't seem to make anything work :( any suggestions? any form of help would be appreciated!
You've got too many loops. You should be able to do it in one:
string oldFile = #"textfile1.txt";
string newFile = #"textfile2.txt";
string test = #"testfile.txt";
string[] lines = File.ReadAllLines(oldFile);
using (StreamWriter w = File.AppendText(newFile))
{
foreach(var line in lines) {
if (!line.Contains(textbox1.Text))
{
w.WriteLine(line);
}
}
}
Alternatively, you could also use LINQ to filter out the lines you don't want, and then write them back out all at once:
var newLines = File.ReadLines(oldFile).Where(l => !l.contains(textbox1.Text));
File.WriteAllLines(newFile, newLines);
I need to read the text file and then check the input text in contents in text file.
If input text exists then move nextline(after input text) into csv file.
Sample Input: input.txt
Hi
Hello
-------------------------------------------------------------------------------
Code Name ID Customers CID Time. %
==================== ========= =========== ============ ===== =================
Harish SM 1001 Tower India 44.58
Siva DM 2310 Cata China 56.78
No Name ID Customers
==================== ========= ===========
MS Norway 1001 UNIBIC
Datas are inside the csv file.
THanks
If I give input "Code Name" then those 2 rows behind the CodeName will be saved in csv file upto newline.
If give input "No Name" then one row after No Name will be stored in another csv file.
Need to write code in c# only.
I'm little bit knowledge about c# console application
How can I write code to perform text file read and content into csv?.
Since the format of the input file isn't the nicest setup, we need to do a read ahead in order to get it to work. The following procedure should work to extract the lines after the given ID code into an array of strings, the first containing the identifier line.
public string[] GetDataLinesFromFile(string filename, string searchString)
{
List<string> dataEntries = new List<string>();
using (System.IO.StreamReader stream = new System.IO.StreamReader(filename))
{
System.IO.TextReader tr = stream;
bool foundSearchString = false;
string lastLine = string.Empty;
string line = string.Empty;
while (!stream.EndOfStream)
{
lastLine = line;
line = tr.ReadLine();
if (lastLine.Trim().StartsWith(searchString) && line.Contains("===================="))
{
foundSearchString = true;
continue;
}
if (foundSearchString)
{
// Start after the divider line
if (lastLine.Contains("===================="))
continue;
// If the current line read is a marker line, then our last line is actually a new identifier line
if (line.Contains("===================="))
{
// Can be used to look for multiple listings with the same ID
foundSearchString = false;
continue;
// If you only want the first found ID, uncomment this and comment out above
// return dataEntries.ToArray();
}
// If our previously read line is not empty, add it to the list of strings
if (lastLine.Trim().Length != 0)
dataEntries.Add(lastLine);
}
}
}
return dataEntries.ToArray();
}
Then to use this function, just call it like so:
string[] entries = GetDataLinesFromFile("input.txt", "Code Name");
To save these to a .csv file, you would just iterate through each of the strings in the string array and look for the tab marker as a divider or if the colums are at a set width then you would hard code those widths in.
I have five lines of text in a text file that I want to read and write in the following way:
read 1st line and copy it to new text file 1.
read 1st and 2nd line and copy them to new text file 2.
read 1st, 2nd and 3rd line and copy them to new text file 3.
read 1st, 2nd, 3rd and 4th line and copy them to new text file 4.
read all lines and copy them to new text file 5.
I have tried something with loops, but I just get confused. Or maybe to use recursion....?
Something like that (just Linq with Take)
// ..Or ReadAllLines to cache the file lines
var source = File.ReadLines(#"C:\MyText.txt");
File.WriteAllLines(#"C:\target1.txt", source.Take(1));
File.WriteAllLines(#"C:\target2.txt", source.Take(2));
File.WriteAllLines(#"C:\target3.txt", source.Take(3));
File.WriteAllLines(#"C:\target4.txt", source.Take(4));
// not 5 lines, but entire file
File.WriteAllLines(#"C:\target5.txt", source);
I created a basic solution for you.. Please check for the rest, this is just for help you out.
List<String> lines = File.ReadLines(#"C:\Users\m\Desktop\te\source.txt").ToList();
string basicPath = #"C:\Users\m\Desktop\te\";
int i = 1;
foreach (string line in lines)
{
File.WriteAllLines(basicPath + i + ".txt", lines.GetRange(0, i));
i++;
}
This question already has answers here:
Get last 10 lines of very large text file > 10GB
(21 answers)
Closed 9 years ago.
Currently I'm reading file content using File.ReadAllText(), but now I need to read last x lines in my txt file. How can I do that?
content of myfile.txt
line1content
line2content
line3content
line4content
string contentOfLastTwoLines = ...
What about this
List <string> text = File.ReadLines("file.txt").Reverse().Take(2).ToList()
Use Queue<string> to store last X lines and replace the first one with currently read:
int x = 4; // number of lines you want to get
var buffor = new Queue<string>(x);
var file = new StreamReader("Input.txt");
while (!file.EndOfStream)
{
string line = file.ReadLine();
if (buffor.Count >= x)
buffor.Dequeue();
buffor.Enqueue(line);
}
string[] lastLines = buffor.ToArray();
string contentOfLastLines = String.Join(Environment.NewLine, lastLines);
You can use ReadLines to avoid reading the entire file into memory, like this:
const int neededLines = 5;
var lines = new List<String>();
foreach (var s in File.ReadLines("c:\\myfile.txt")) {
lines.Add(s);
if (lines.Count > neededLines) {
lines.RemoveAt(0);
}
}
Once the for loop is finished, the lines list contains up to the last neededLines of text from the file. Of course if the file does not contain as many lines as required, fewer lines will be placed in the lines list.
Read the lines into an array, then extract the last two:
string[] lines = File.ReadAllLines();
string last2 = lines[lines.Count-2] + Environment.NewLine + lines[lines.Count-1];
Assuming your file is reasonably small, it's easier to just read the whole thing and throw away what you don't need.
Since reading a file is done linearly, usually line-by-line. Simply read line-by-line and remember last two lines (you can use queue or something if you want... or just two string variables). When you get to EOF, you'll have your last two lines.
You want to read the file backwards using ReverseLineReader:
How to read a text file reversely with iterator in C#
Then run .Take(2) on it.
var lines = new ReverseLineReader(filename);
var last = lines.Take(2);
OR
Use a System.IO.StreamReader.
string line1, line2;
using(StreamReader reader = new StreamReader("myFile.txt")) {
line1 = reader.ReadLine();
line2 = reader.ReadLine();
}
I'm running three counters, one to return the total amount of chars, one to return the number of '|' chars in my .txt file (total). And one to read how many separate lines are in my text file. I'm assuming my counters are wrong, I'm not sure. In my text file there are some extra '|' chars, but that is a bug I need to fix later...
The Message Boxes show
"Lines = 8"
"Entries = 8"
"Total Chars = 0"
Not sure if it helps but the .txt file is compiled using a streamwriter, and I have a datagridview saved to a string to create the output. Everything seems okay with those functions.
Here is a copy of the text file I'm reading
Matthew|Walker|MXW320|114282353|True|True|True
Audrey|Walker|AXW420|114282354|True|True|True
John|Doe|JXD020|111222333|True|True|False
||||||
And here is the code.
private void btnLoadList_Click(object sender, EventArgs e)
{
var loadDialog = new OpenFileDialog
{
InitialDirectory = Convert.ToString(Environment.SpecialFolder.MyDocuments),
Filter = "Text (*.txt)|*.txt",
FilterIndex = 1
};
if (loadDialog.ShowDialog() != DialogResult.OK) return;
using (new StreamReader(loadDialog.FileName))
{
var lines = File.ReadAllLines(loadDialog.FileName);//Array of all the lines in the text file
foreach (var assocStringer in lines)//For each assocStringer in lines (Runs 1 cycle for each line in the text file loaded)
{
var entries = assocStringer.Split('|'); // split the line into pieces (e.g. an array of "Matthew", "Walker", etc.)
var obj = (Associate) _bindingSource.AddNew();
if (obj == null) continue;
obj.FirstName = entries[0];
obj.LastName = entries[1];
obj.AssocId = entries[2];
obj.AssocRfid = entries[3];
obj.CanDoDiverts = entries[4];
obj.CanDoMhe = entries[5];
obj.CanDoLoading = entries[6];
}
}
}
Hope you guys find the bug(s) here. Sorry if the formatting is sloppy I'm self-taught, no classes. Any extra advice is welcomed, be as honest and harsh as need be, no feelings will be hurt.
In summary
Why is this program not reading the correct values from the text file I'm using?
Not totally sure I get exactly what you're trying to do, so correct me if I'm off, but if you're just trying to get the line count, pipe (|) count and character count for the file the following should get you that.
var lines = File.ReadAllLines(load_dialog.FileName);
int lineCount = lines.Count();
int totalChars = 0;
int totalPipes = 0; // number of "|" chars
foreach (var s in lines)
{
var entries = s.Split('|'); // split the line into pieces (e.g. an array of "Matthew", "Walker", etc.)
totalChars += s.Length; // add the number of chars on this line to the total
totalPipes = totalPipes + entries.Count() - 1; // there is always one more entry than pipes
}
All the Split() is doing is breaking the full line into an array of the individual fields in the string. Since you only seem to care about the number of pipes and not the fields, I'm not doing much with it other than determining the number of pipes by taking the number of fields and subtracting one (since you don't have a trailing pipe on each line).