I want to know how I can delete a certain amount of text from a file on each line.
I can not think of a way of accomplishing such a task.
878 57 2
882 63 1
887 62 1
1001 71 0
1041 79 1
1046 73 2
This is what the text file looks like but I only want the numbers that are on the very left. I can not manually the 2 rows on the right because there is over 16,000 lines of this.
The numbers on the left also change in length so I can't read them by length.
I'm also not sure what character the numbers are separated by, it may be tab.
Anyone have any ideas on what I could try?
If you wish to take a look at the text file, here: http://pastebin.com/xyaCsc6W
var query = File.ReadLines("input.txt")
.Where(x => char.IsDigit(x.FirstOrDefault()))
.Select(x => string.Join("", x.TakeWhile(char.IsDigit)));
File.WriteAllLines("output.txt", query);
string line;
using (var sr = new StreamReader(#"E:\test1.txt"))
{
using (var sw = new StreamWriter(#"E:\test1.tmp"))
{
while (!sr.EndOfStream)
{
line = sr.ReadLine();
line = Regex.Match(line, #"([\d]*)").Groups[1].Value;
sw.WriteLine(line);
}
}
}
File.Replace(#"E:\test1.tmp", #"E:\test1.txt", null);
You could do:
var col =
from s in File.ReadAllLines(input_file_name);
select s.Split(" ".ToCharArray())[0];
Note: In the Split(" ") I have a space and a tab characters.
StringBuilder sb = new StringBuilder();
//read the line by line of file.txt
using (StreamReader sr = new StreamReader("file.txt"))
{
String line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null)
{
//for each line identify the space
//cut the data from beginning of each line to where it finds space
string str = line.Substring(0, line.IndexOf(' '));
//Append each modifed line into string builder object
sb.AppendLine(str);
}
}
//Create temp newfile
using (File.Create("newfile.txt"))
{
//create newfile to store the modified data
}
//Add modified data into newfile
File.WriteAllText("newfile.txt",sb.ToString());
//Replace with new file
File.Replace("newfile.txt", "file.txt", null);
You could also do this which will give you a list of results of only the left (column) characters (numeric/alphanumeric) of the text file:
var results = File.ReadAllLines("filename.txt")
.Select(line => line.Split('\t').First())
.ToList();
It looks like the text file is delimited by tabs.
To save the list of results back into a text file add the following in addition:
File.WriteAllLines("results.txt", results.ToArray());
Related
I have a text file with this multi line structure:
12345 beautiful text in line01
95469 other text in line02
16987 nice text in line03
(etc...)
and want this:
12345
beautiful text in line01
95469
other text in line02
16987
nice text in line03
So, for every line, at position 5 i need a new line for the textual string.
Tried inserting \n with string.Remove().Insert() but works only for first line.
How can I do this?
EDIT
Code added by request
In input.txt there is the multiline textfile.
StreamReader myReader = new StreamReader("input.txt");
string myString00 = myReader.ReadLine();
string myStringFinal = myString00;
myStringFinal = myStringFinal.Remove(5, 1).Insert(5, "\n");
myReader.Close();
FileStream myFs = new FileStream("output.txt", FileMode.Create);
// First, save the standard output.
TextWriter tmp = Console.Out;
StreamWriter mySw = new StreamWriter(myFs);
Console.SetOut(mySw);
Console.WriteLine(myStringFinal);
Console.SetOut(tmp);
Console.WriteLine(myStringFinal);
mySw.Close();
Console.ReadLine();
Here is something you can try with a Regex
var subject = #"12345 beautiful text in line01
95469 other text in line02
16987 nice text in line03";
var expected = Regex.Replace(subject,#"(\d{5})\s?","$1\r\n");
Basically this finds 5 digits followed by a space(optional), if found replaces it with digits and a new line. And you're done.
This will work only if the number is exactly 5 characters.
string input = #"12345 beautiful text in line01
95469 other text in line02
16987 nice text in line03";
var lines = input.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
var formattedLines = lines
.Select(x => new
{
Number = int.Parse(x.Substring(0, 5)),
Data = x.Substring(5).TrimStart()
})
.ToList();
formattedLines will be a collection of your lines, with Number and Data holding the info from the lines.
var firstLinesData = formattedLines[0].Data;
So now, to make your output format:
StringBuilder builder = new StringBuilder();
foreach (var item in formattedLines)
{
builder.AppendLine(item.Number.ToString());
builder.AppendLine(item.Data);
}
string output = builder.ToString();
loop over each line. Use substring (http://msdn.microsoft.com/en-us/library/aka44szs(v=vs.110).aspx) to get the first 5 character as a string. Use a string builder and add the first part, grab the next part and add tot he string builder
I'm working on a little test program to experiment with text files and storing some data in them, and I've stumbled accross a problem when trying to replace a value in a specific line.
This is how the formatting of my text file is done :
user1, 1500, 1
user2, 1700, 17
.. and so on.
This is the code I am using at the moment to read the file line by line :
string line;
Streamreader sr = new Streamreader(path);
while ((line = sr.ReadLine()) != null)
{
string[] infos = line.Split(',');
if (infos[0] == username) //the username is received as a parameter (not shown)
//This is where I'd like to change the value
}
Basically, my objective is to update the number of points (the second value in the text line - infos[1]) only if the username matches. I tried using the following code (edited to match my informations)
string text = File.ReadAllText("test.txt");
text = text.Replace("some text", "new value");
File.WriteAllText("test.txt", text);</pre>
The problem with this is that it will replace every corresponding value in the text file, and not just the one of the correct line (specified by the matching username). I know how to change the value of infos[1] (ex: 1500 for user1) but I don't know how to rewrite it to the file after that.
I've searched online and on StackOverflow, but I couldn't find anything for this specific problem where the value is only to be modified if it's on the proper line - not anywhere in the text.
I run out of ideas on how to do this, I would really appreciate some suggestions.
Thank you very much for your help.
Try this:
var path = #"c:\temp\test.txt";
var originalLines = File.ReadAllLines(path);
var updatedLines = new List<string>();
foreach (var line in originalLines)
{
string[] infos = line.Split(',');
if (infos[0] == "user2")
{
// update value
infos[1] = (int.Parse(infos[1]) + 1).ToString();
}
updatedLines.Add(string.Join(",", infos));
}
File.WriteAllLines(path, updatedLines);
use ReadLines and LINQ:
var line = File.ReadLines("path")
.FirstOrDefault(x => x.StartsWith(username));
if (line != null)
{
var parts = line.Split(',');
parts[1] = "1500"; // new number
line = string.Join(",", parts);
File.WriteAllLines("path", File.ReadLines("path")
.Where(x => !x.StartsWith(username)).Concat(new[] {line});
}
Currently i am reading the tab delimited file line by line, splitting the items in each line and looking for the tab delimited line with 50 items by hard coding value 50 and then create the
data table.
Issues: Faced - tab delimited source files has tab delimited lines sometimes with 50 or 53 items after splitting. Need to directly read a line which has the maximum tab delimiters in the tab delimited source file and then continue with my logic.
My C# code
using (var sr = new StreamReader(sourceFileFullName))
{
string line = null;
while ((line = sr.ReadLine()) != null)
{
var items = line.Split(new[] { '\t', '\n' }).ToArray();
if (items.Length != 50)
continue;
//Rest of my code to create datatable for the items after splitting in tab delimitedline
}
}
You could use the below snippet
string content = "";
using (var reader = new StreamReader("C:\\temp\\abc.txt"))
{
content = reader.ReadToEnd();
}
if (!string.IsNullOrEmpty(content))
{
var value = content.Split('\n').OrderByDescending(y => y.Split('\t').Count()).Take(1);
}
I have a 60GB csv file I need to make some modifications to. The customer wants some changes to the files data, but I don't want to regenerate the data in that file because it took 4 days to do.
How can I read the file, line by line (not loading it all into memory!), and make edits to those lines as I go, replacing certain values etc.?
The process would be something like this:
Open a StreamWriter to a temporary file.
Open a StreamReader to the target file.
For each line:
Split the text into columns based on a delimiter.
Check the columns for the values you want to replace, and replace them.
Join the column values back together using your delimiter.
Write the line to the temporary file.
When you are finished, delete the target file, and move the temporary file to the target file path.
Note regarding Steps 2 and 3.1: If you are confident in the structure of your file and it is simple enough, you can do all this out of the box as described (I'll include a sample in a moment). However, there are factors in a CSV file that may need attention (such as recognizing when a delimiter is being used literally in a column value). You can drudge through this yourself, or try an existing solution.
Basic example just using StreamReader and StreamWriter:
var sourcePath = #"C:\data.csv";
var delimiter = ",";
var firstLineContainsHeaders = true;
var tempPath = Path.GetTempFileName();
var lineNumber = 0;
var splitExpression = new Regex(#"(" + delimiter + #")(?=(?:[^""]|""[^""]*"")*$)");
using (var writer = new StreamWriter(tempPath))
using (var reader = new StreamReader(sourcePath))
{
string line = null;
string[] headers = null;
if (firstLineContainsHeaders)
{
line = reader.ReadLine();
lineNumber++;
if (string.IsNullOrEmpty(line)) return; // file is empty;
headers = splitExpression.Split(line).Where(s => s != delimiter).ToArray();
writer.WriteLine(line); // write the original header to the temp file.
}
while ((line = reader.ReadLine()) != null)
{
lineNumber++;
var columns = splitExpression.Split(line).Where(s => s != delimiter).ToArray();
// if there are no headers, do a simple sanity check to make sure you always have the same number of columns in a line
if (headers == null) headers = new string[columns.Length];
if (columns.Length != headers.Length) throw new InvalidOperationException(string.Format("Line {0} is missing one or more columns.", lineNumber));
// TODO: search and replace in columns
// example: replace 'v' in the first column with '\/': if (columns[0].Contains("v")) columns[0] = columns[0].Replace("v", #"\/");
writer.WriteLine(string.Join(delimiter, columns));
}
}
File.Delete(sourcePath);
File.Move(tempPath, sourcePath);
memory-mapped files is a new feature in .NET Framework 4 which can be used to edit large files.
read here http://msdn.microsoft.com/en-us/library/dd997372.aspx
or google Memory-mapped files
Just read the file, line by line, with streamreader, and then use REGEX! The most amazing tool in the world.
using (var sr = new StreamReader(new FileStream(#"C:\temp\file.csv", FileMode.Open)))
{
var line = sr.ReadLine();
while (!sr.EndOfStream)
{
// do stuff
line = sr.ReadLine();
}
}
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.