I´m reading a file in my C# code.
The file looks like this:
13
56
89
55
66
9
58
I´m trying to read the file and split the numbers up in different variabels.
Want it look like this:
numb1 = 13,56,89
numb2 = 55,66
numb3 = 9
numb4 = 58
When it is a blank line I want to split it up and group numbers together. But I don´t know how to do.
My code so far:
static void Main(string[] args)
{
InputReader inputReader = new InputReader();
var file =File.ReadAllLines(#"C:\Users\forsb\source\repos\ConsoleApp1\ConsoleApp1\Input\numberlist.txt");
string[] a = new string[] { };
foreach (var item in file)
{
a = item.Split(new string[] { "\r\n\r\n" },
StringSplitOptions.RemoveEmptyEntries);
}
Console.WriteLine();
Console.Read();
}
You can try the below code
public static void Main()
{
var fileName = "filename.txt";
// CREATE a file in your Sandbox using .NET Fiddle
WriteFile(fileName);
string line;
var str="";
// Read the file and display it line by line.
System.IO.StreamReader file =
new System.IO.StreamReader(fileName);
while((line = file.ReadLine()) != null)
{
line = line.Trim();
//if line is empty
//show total values until now
if (line == "")
{
Console.WriteLine(str);
str="";
continue;
}
else
{
//if first element, add here
if(str != "")
{
str=str+","+line;
}
else
{
str=line;
}
}
}
//for remaining last line
Console.WriteLine(str);
file.Close();
}
public static void WriteFile(string path)
{
File.WriteAllText(path, "13\n56\n89\n\n\n\n55\n66\n\n\n\n9\n58");
}
I have used the sample code in fiddle looks working.
https://dotnetfiddle.net/hOFSi2
basically, i am trying to read here line by line, if line is empty and there is some data saved in "str" print it, else continue
Note: You don't need to create file using "WriteFile" function, I have created it in fiddle, so adding code here for reference.
I would create a List<List<int>> to hold your sets of numbers. Then you can do whatever you want with them.
static void Main(string[] args)
{
String fileName = #"C:\Users\forsb\source\repos\ConsoleApp1\ConsoleApp1\Input\numberlist.txt";
List<List<int>> numberSets = new List<List<int>>();
// Read the file and collect the numbers in "curSet" until a blank line is encountered
List<int> curSet = new List<int>();
foreach (String line in System.IO.File.ReadLines(fileName))
{
if (line.Trim().Length == 0)
{
// blank line found, add the current set of numbers to our list,
// but only if the current set actually has any numbers in it.
if (curSet.Count > 0)
{
numberSets.Add(curSet);
curSet = new List<int>();
}
}
else
{
int number;
if (int.TryParse(line, out number))
{
curSet.Add(number);
}
}
}
// end of file reached, add a pending set of numbers if it exists
if (curSet.Count > 0)
{
numberSets.Add(curSet);
}
// do something with the collection of number lists:
for(int i=0; i<numberSets.Count; i++)
{
List<int> numberSet = numberSets[i];
// ... do something with "numberSet" ...
Console.WriteLine(i + ": " + String.Join(",", numberSet));
}
Console.Write("Press Enter to Quit");
Console.ReadLine();
}
Output on my system:
0: 13,56,89
1: 55,66
2: 9
3: 58
Press Enter to Quit
You are doing the split for each row that you read from the file. You need to do the split for the complete content of the file.
Code below will give the output you want.
a[0] = 13,56,89
a[1] = 55,66
a[2] = 9
a[3] = 58
var data = File.ReadAllText(#"C:\Users\forsb\source\repos\ConsoleApp1\ConsoleApp1\Input\numberlist.txt");
string[] a = data.Split("\r\n\r\n", System.StringSplitOptions.RemoveEmptyEntries);
for(int i = 0; i < split.Length; i++)
{
a[i] = a[i].Replace("\r\n", ",");
}
Related
I got assignment to do first line in upper case and in the rest every word that is 3 or more characters long starts with upper case.
I am testing it in console so its made partly with streamreader/streamwriter, but when it functions well I will correct it.
Problem is that the Console.WriteLine(); before for loop with it, it makes an empty line after the first line but without it, it does not make 3rd line. The input text looks like this
title of text
sssssss ss ssss, ss sssssss
ddddd ddd ddddd dddddd
with the WriteLine it ends up like this:
TITLE OF TEXT
sssssss ss ssss, ss sssssss
ddddd ddd ddddd dddddd
and without:
TITLE OF TEXT
Sssssss ss Ssss, ss Sssssss Ddddd Ddd Ddddd Dddddd
I think I made it too complicated and got kinda lost so I am looking for the solution to this small problem or also to make this code easier but thats not the point right now.
using System;
using System.IO;
namespace priklad_8._4
{
class Program
{
static void Main(string[] args)
{
firstUpper(#"aaa.txt", #"new.txt");
Console.ReadLine();
}
static void firstUpper(String from, String to)
{
StreamReader sr = new StreamReader(from);
StreamWriter sw = new StreamWriter(to);
String s;
int length = 0;
char[] pole = new char[100];
char dd = 'A';
while ((s = sr.ReadLine()) != null)
{
if (length == 0)
{
Console.WriteLine(s.ToUpper());
length++;
}
else
{
String[] ss = s.Trim(' ').Split(' ');
Console.WriteLine();
for (int i = 0; i < ss.Length; i++)
{
if (ss[i].Length >= 3)
{
String ds = ss[i];
char[] das = ds.ToCharArray();
Console.Write(Char.ToUpper(das[0]) + ds.Substring(1) + " ");
if ((int)dd == 10)
{
Console.WriteLine();
}
}
else Console.Write(ss[i] + " ");
}
}
}
sw.Close();
sr.Close();
}
}
}
Thank you!
If you want to leave everything else as it is, just instead of
Console.WriteLine(s.ToUpper());
use this:
Console.Write(s.ToUpper())
Maybe a cleaner way to get there:
using (var input = new StreamReader("input.txt"))
{
var currentLine = 0;
while (!input.EndOfStream)
{
var line = input.ReadLine() ?? "";
if (++currentLine == 1)
{
// first line is upper case
Console.WriteLine(line.ToUpper());
}
else
{
// Every word longer than 3 letter starts with capitalized
Console.WriteLine(Regex.Replace(line, #"\w{3,}",
(match) => CultureInfo.CurrentCulture
.TextInfo.ToTitleCase(match.Value.ToLower())));
}
}
}
Another Cleaner way to get there making use of File.ReadAllLines, and File.WriteAllLines
static void Main(string[] args)
{
var lines = File.ReadAllLines("text.txt");
var newLines = new string[lines.Count()];
for (var i = 0; i < lines.Count(); i++)
{
if (i == 0)
{
newLines[i] = lines[i].ToUpper();
}
else
{
foreach (var word in lines[i].Split(' '))
{
newLines[i] += string.Format("{0} ", word.Length >= 3 ? CultureInfo.CurrentCulture.TextInfo.ToTitleCase(word) : word);
}
}
}
File.WriteAllLines("newText.txt", newLines);
}
And i mean, if you wanted a very unclean looking one liner because i was bored.. You could do this.
static void Run(string fromFile, string toFile)
{
File.WriteAllLines(toFile, File.ReadAllLines(fromFile).Select((line, index) => index == 0 ? line.ToUpper() : Regex.Replace(line, #"\w{3,}", (match) => CultureInfo.CurrentCulture.TextInfo.ToTitleCase(match.Value))));
}
I have a small text file, containing a few integers on separate lines.
I wrote the following program (just a function called ReadFromFile) in order to read in the integers and assign them to some variables.
I wonder if I could improve it, and how? I tried reading in integers, but realized I would get errors with StreamReader, so I carried on using strings.
Is there anyway I could improve this program?
All it does is read in the following numbers, assign the first two to two variables, and put the rest in a list.
3
4
8
8
8
8
8
8
So, I will have: var1 = 3 , var2 = 4 , myList = [8,8,8,8,8,8]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Practice
{
class Program
{
static void Main(string[] args)
{
// Read the specifications from the file.
ReadFromFile();
// Prevent the console window from closing.
Console.ReadLine();
}
/// The function that reads the input specifications from a file.
public static void ReadFromFile()
{
string localPath = #"C:\Desktop\input.txt";
StreamReader sr = new StreamReader(localPath);
// Read all the lines from the file into a list,
// where each list element is one line.
// Each line in the file.
string line = null;
// All lines of the file.
List<string> lines = new List<string>();
while ( ( line = sr.ReadLine() ) != null )
{
lines.Add(line);
Console.WriteLine(line);
}
// Display the extracted parameters.
Console.WriteLine( lines[0] + " var1");
Console.WriteLine( lines[1] + " var2");
// Put the rest in a separate list.
List<int> myList = new List<int>();
for (int i = 2; i < lines.Count; i++)
{
Console.WriteLine("item {0} = {1}", i-1, lines[i] );
myList.Add( Int32.Parse( lines[i] ) );
}
sr.Close();
}
}
}
var vals = File.ReadAllLines(path).Select(int.Parse).ToList();
You might need a Skip(...) if you have header lines; for example to match your for(int i = 2; ...):
var vals = File.ReadAllLines(path).Skip(2).Select(int.Parse).ToList();
You could write it as follow :
public static void ReadFromFile(string localPath) // paremetrizing the path for more flexibility
{
StreamReader sr = new StreamReader(localPath);
// extrating the lines from the file
List<int> lines = Regex.Split(sr.ReadToEnd(), "\r\n").Select(int.Parse).ToList();
// we can close the reader as we don't need it anymore
sr.Close();
Console.WriteLine( lines[0] + " var1");
Console.WriteLine( lines[1] + " var2");
// removing the first 2 elements
lines = lines.Skip(2).ToList();
for (int i = 0; i < lines.Count; i++)
{
Console.WriteLine("item {0} = {1}", i-1, lines[i] );
}
}
I am creating an application to read and display Pokemon stats. Currently, I have 6 txt files, one for each stat. I have 6 arrays reading each txt file and displaying each stat in a label.
I want to condense this information into a single text file, splitting each stat by a " " to keep each Pokemon's data on a single line.
Current code if it helps explain the idea better:
using System;
using System.Windows.Forms;
using System.IO;
namespace Pokedex
{
public partial class Pokedex : Form
{
public Pokedex()
{
InitializeComponent();
}
//Read stat data from text files into string arrays
string[] HP = File.ReadAllLines("HP.txt");
string[] Atk = File.ReadAllLines("Atk.txt");
string[] Def = File.ReadAllLines("Def.txt");
string[] SpAtk = File.ReadAllLines("SpAtk.txt");
string[] SpDef = File.ReadAllLines("SpDef.txt");
string[] Spe = File.ReadAllLines("Spe.txt");
private void cbxPokemon_SelectedIndexChanged(object sender, EventArgs e)
{
//Get array index of currently selected Pokemon
int index = cbxPokemon.SelectedIndex;
//Get integer values out of the string arrays for appropriate use
int intHP = int.Parse(HP[index]);
int intAtk = int.Parse(Atk[index]);
int intDef = int.Parse(Def[index]);
int intSpAtk = int.Parse(SpAtk[index]);
int intSpDef = int.Parse(SpDef[index]);
int intSpe = int.Parse(Spe[index]);
//Update labels with stat values in string forme, could also assign intStat.ToString()
lblDexNum.Text = (index + 1).ToString("d3");
lblHP.Text = HP[index];
lblAtk.Text = Atk[index];
lblDef.Text = Def[index];
lblSpAtk.Text = SpAtk[index];
lblSpDef.Text = SpDef[index];
lblSpe.Text = Spe[index];
lblBST.Text = (intHP + intAtk + intDef + intSpAtk + intSpDef + intSpe).ToString();
//Update bar width based on stat value
barHP.Width = intHP;
barAtk.Width = intAtk;
barDef.Width = intDef;
barSpAtk.Width = intSpAtk;
barSpDef.Width = intSpDef;
barSpe.Width = intSpe;
//Disable Previous and Next buttons when they cannot be used
if (index == 0) { btnPrev.Enabled = false; }
else { btnPrev.Enabled = true; }
if (index == cbxPokemon.Items.Count - 1) { btnNext.Enabled = false; }
else { btnNext.Enabled = true; }
}
private void btnPrev_Click(object sender, EventArgs e)
{
cbxPokemon.SelectedIndex -= 1;
}
private void btnNext_Click(object sender, EventArgs e)
{
cbxPokemon.SelectedIndex += 1;
}
}
}
Ideally, the file would contain the 6 stats, for example "100 90 80 70 60 50" on each line, with each of those valued being stored.
Is there a simple way to read until a space, store that value, and keep doing that until the end of the line?
Yes, this is very simple to do. You can use the String.Split() method to break apart the lines into parsable pieces.
You can read the stats file in the same way you are now, except you would only need to read one file instead of six:
string[] lines = File.ReadAllLines("PokemonStats.txt");
Then, inside your cbxPokemon_SelectedIndexChanged method, you can retrieve the stats for a Pokemon like this:
//Get integer values out of the string for appropriate use
string line = lines[index];
string[] parts = line.Split(' ');
int intHP = int.Parse(parts[0]);
int intAtk = int.Parse(parts[1]);
int intDef = int.Parse(parts[2]);
int intSpAtk = int.Parse(parts[3]);
int intSpDef = int.Parse(parts[4]);
int intSpe = int.Parse(parts[5]);
Of course this assumes there will always be exactly 6 integer stats per line and they will all be in a specific order.
Try something like this:
static void Main(string[] args)
{
//list to store stats
List<string[]> pokemonStats = new List<string[]>();
//get a reader on the file
using (StreamReader reader = new StreamReader("TextFile1.txt"))
{
//while we still have lines to read
while (!reader.EndOfStream)
{
//get the line of stats
string line = reader.ReadLine();
//split it on the ' ' character and store it in our list of pokemon stats
pokemonStats.Add(line.Split(' '));
}
}
//we have them all so do something, like print to screen
foreach (string[] pokemon in pokemonStats)
{
foreach (string stat in pokemon)
Console.Write(stat + " ");
Console.WriteLine();
}
Console.ReadLine();
}
Where TextFile1.txt contains; which also happens to be the output...
1 1 1 1 1 1
2 2 2 2 2 2
3 3 3 3 3 3
Ideally, the file would contain the 6 stats, for example "100 90 80 70 60 50" on each line, with each of those valued being stored.
So this solution is actually very simple, assuming you have a file that looks like this:
100
90
80
70
60
50
You could write code that looks like this:
public string[] ReadStats(string fileName)
{
return File.ReadAllLines(fileName);
}
This would return:
[ "100", "90", "80", "70", "60", "50" ]
This is obviously an over-simplified version that does not checking on whether the file exists, whether there are more than 6 lines, etc. But it gets the idea across, and you could enhance it to suit your needs.
The answer to your main question:
Is there a simple way to read until a space, store that value, and keep doing that until the end of the line?
This is a bit more complicated, but this should work:
public IEnumerable<string[]> ReadAllPokemonStats(string fileName)
{
List<string[]> allPokemon = new List<string[]>();
string[] allStats = new string[6];
var allText = File.ReadAllText(fileName);
int nextStatIndex = 0;
string thisStat;
for(int i=0; i < allText.Length; i++)
{
var nextChar = allText[i];
if(nextChar == ' ')
{
allStats[nextStatIndex] = thisStat;
nextStatIndex++;
continue;
}
if(nextChar == '\r')
{
allPokemon.Add(allStats);
nextStatIndex = 0;
allStats = new string[6];
continue;
}
thisStat += nextChar.ToString();
}
return allPokemon;
}
Again, the above code is not perfect, for example it reads the entire file into memory so there's a potential attack vector there. It also does not ensure that the stats are actually numeric, but neither did your code (it would just blow up on the int.Parse()). But again, it gives you the general idea. You can see this approach is actually a lot more complex that reading each stat line by line.
I am thinking that each file is a one column file that represents one type of stat. If this is correct, you can try this:
Perhaps creating a class the represents all the stats that you are loading and then treat that as an array or a dictionary to fetch the proper stat or to create a single stat file.
public class PokemonStat
{
public int Hp { get; set; }
public int Atk { get; set; }
public int Def { get; set; }
public int SpAtk { get; set; }
public int SpDef { get; set; }
public int Spe { get; set; }
}
Then in your executing file:
var newPokemanData = new Dictionary<int, PokemonStat>();
var fileNames = new string[] { "Hp.txt", "Atk.txt", "Def.txt", "SpAtk.txt", "SpDef.txt", "Spe.txt" }
foreach (var fileName in fileNames)
{
var lineNumber = 0;
using (var stream = new StreamReader(fileName))
{
while (!stream.EndOfStream)
{
var singleStat = stream.ReadLine();
if (!newPokemanData.Keys.Contains(lineNumber))
{
newPokemanData.Add(lineNumber, new PokemonStat());
}
switch(fileName)
{
case "Hp.txt":
newPokemanData[lineNumber].Hp = int.Parse(singleStat);
break;
case "Atk.txt":
newPokemanData[lineNumber].Atk = int.Parse(singleStat);
break;
case "Def.txt":
newPokemanData[lineNumber].Def = int.Parse(singleStat);
break;
case "SpAtk.txt":
newPokemanData[lineNumber].SpAtk = int.Parse(singleStat);
break;
case "SpDef.txt":
newPokemanData[lineNumber].SpDef = int.Parse(singleStat);
break;
case "Spe.txt":
newPokemanData[lineNumber].Spe = int.Parse(singleStat);
break;
default:
Console.WriteLine("Error");
break;
}
lineNumber++;
}
}
}
using (var unifiedStats = new StreamWriter("unifieldFile.txt"))
{
foreach (var line in newPokemanData.Keys)
{
//write to a file
unifiedStats.WriteLine(newPokemanData[line].Hp.ToString() + " " +
newPokemanData[line].Atk.ToString() + " " +
newPokemanData[line].Def.ToString() + " " +
newPokemanData[line].SpAtk.ToString() + " " +
newPokemanData[line].SpDef.ToString() + " " +
newPokemanData[line].Spe.ToString() + " "
);
}
}
//
I am trying to search through a text file for a string, once I have found this string I need to display this line and then also display the 6 preceding lines i.e. which will contain the details about the error message in the string. I have been searching for similar code and have found the following code but it doesn’t meet my requirements, just wondering if it's possible to do this.
Thanks,
John.
private static void Main(string[] args)
{
string cacheline = "";
string line;
System.IO.StreamReader file = new
System.IO.StreamReader(#"D:\Temp\AccessOutlook.txt");
List<string> lines = new List<string>();
while ((line = file.ReadLine()) != null)
{
if (line.Contains("errors"))
{
lines.Add(cacheline);
}
cacheline = line;
}
file.Close();
foreach (var l in lines)
{
Console.WriteLine(l);
}
}
}
This is probably what you want:
static void Main(string[] args)
{
Queue<string> lines = new Queue<string>();
using (var reader = new StreamReader(args[0]))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains("error"))
{
Console.WriteLine("----- ERROR -----");
foreach (var errLine in lines)
Console.WriteLine(errLine);
Console.WriteLine(line);
Console.WriteLine("-----------------");
}
lines.Enqueue(line);
while (lines.Count > 6)
lines.Dequeue();
}
}
}
You can keep caching the lines until you find the line you are looking for:
using(var file = new StreamReader(#"D:\Temp\AccessOutlook.txt"))
{
List<string> lines = new List<string>();
while ((line = file.ReadLine()) != null)
{
if (!line.Contains(myString))
{
lines.Add(line);
}
else
{
Console.WriteLine(string.Join(Environment.NewLine, lines.Concat(new[] { line })));
}
if(lines.Count > 6) lines.RemoveAt(0);
}
}
string filename = "filename"; // Put your own filename here.
string target = "target"; // Put your target string here.
int numLinesToShow = 7;
var lines = File.ReadAllLines(filename);
int index = Array.FindIndex(lines, element => element.Contains(target));
if (index >= 0)
{
int start = Math.Max(0, index - numLinesToShow + 1);
var result = lines.Skip(start).Take(numLinesToShow).ToList();
// Use result.
}
The code below will open the file, search for the line you want, and then write the 6 preceeding lines to the Console.
var lines = File.ReadAllLines(filePath);
int lineIndex;
for (lineIndex = 0; lineIndex < lines.Length - 1; lineIndex++)
{
if (lines[lineIndex] == textToFind)
{
break;
}
}
var startLine = Math.Max(0, lineIndex - 6);
for (int i = startLine; i < lineIndex; i++)
{
Console.WriteLine(lines[i]);
}
As part of an assignment -
The User selects a file extension (.txt, .bat, or .xyz)
A list of files from a folder with that extension is shown
The user then selects a file from the list and are shown the first 40 characters of each of its first four lines (or as many lines as present if less than four lines are recorded in the file). If there are more lines left in the file, output a string: “xx more lines are not shown.” (substitute xx with the correct number).
I can't seem to wrap my head around number 3. Any help or pointers are greatly appreciated.
namespace unit9Assignment
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//add the extensions to the c box.
comboBox1.Items.Add(".txt");
comboBox1.Items.Add(".xyz");
comboBox1.Items.Add(".bat");
//make .txt the default selection
comboBox1.SelectedItem = ".txt";
tabControl1.SelectedIndexChanged += tabControl1_SelectedIndexChanged;
}
/******Tab Click Event********/
private void tabControl1_SelectedIndexChanged(Object sender, EventArgs e)
{
switch ((sender as TabControl).SelectedIndex)
{
case 0:
break;
case 1:
fileName(comboBox1.Text);
break;
case 2:
fileContent(Files.SelectedItem.ToString());
break;
}
}
/******Get Files Based on Selection*******/
public void fileName(string fileExt)
{
List<string> listOfFiles = new List<string>();
string[] fileExtArray = Directory.GetFiles(#"C:\Users\Public", "*" + fileExt);
foreach (string fileExtFile in fileExtArray)
{
listOfFiles.Add(fileExtFile);
}
Files.DataSource = listOfFiles;
}
/******Display 4 Lines # 40 Characters Per Line*********/
public void fileContent(string fileName)
{
int numberOfLines = File.ReadLines(#fileName).Count(),
remainingLines = numberOfLines - 4;
//THIS PRINTS OUT 4 LINES # 40 CHARACTERS PER LINE IF A FILE HAS LESS THAN 5 LINES
if (numberOfLines < 5)
{
foreach (string line in File.ReadLines(fileName))
{
richTextBox1.AppendText(line.Substring(0, 40) + Environment.NewLine);
Console.WriteLine(line.Substring(0, 40));
}
}
// NO CLUE WHAT TO DO
else
{
}
}
}
}
Rather than checking the number of lines in the file, why don't you just go ahead and start printing, and stop after 4 lines? Something like this:
StreamReader fileIn = new StreamReader(fileName);
for(int i=0; i<4 && !fileIn.EndOfStream; ++i)
{
string line = fileIn.ReadLine();
if(line.Length > 40)
richTextBox1.AppendText(line.Substring(0,40) + Environment.NewLine);
else
richTextBox1.AppendText(line + Environment.NewLine);
}
int j;
for(j=0; !fileIn.EndOfStream; ++j)
fileIn.ReadLine();
if(j>0)
richTextBox1.AppendText(j.ToString() + " more lines are not shown.";
fileIn.Close();
... To clarify, this would be your entire fileContent method. You actually do not need to know the number of lines in the file. Of course, this method won't work if you have more lines in your file than an int variable can hold, but I assume you're not working with such long files.
How about this:
public void fileContent(string fileName)
{
var lines = File.ReadLines(#fileName);
foreach (string line in lines.Take(4))
{
richTextBox1.AppendText(line.Substring(0, 40) + Environment.NewLine);
}
var remaining = lines.Count() - 4;
if (remaining > 0)
richTextBox1.AppendText(remaining + " more line(s) are not shown.");
}
The Take() documentation is here.
Giving answers to homework is bad practice. Instead here are some pointers to help you wrap your head around your problem:
//read a file
var lines = File.ReadLines("myfile");
//get the first 4 lines of your file
var first4 = lines.Take(4);
//get the first 40 characters of the first line of your file
var first40Chars = lines.FirstOrDefault().Take(40);
//get the remaining number of lines
var remainingCount = lines.Count() - 4;
Pulling up a dialog to show files is quite easy also. The WinForms FileDialog can help you there.