So I have the following code:
void ReadFromCsv()
{
using (var reader = new StreamReader(#"d:\test.csv", Encoding.Default))
{
List<string> listA = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
listA.Add(values[0]);
}
Console.WriteLine(listA);
}
}
which is reading from my csv file and an example of a line I get is:
50,2,10,201,10,9090339,24-OCT-21 09.38.38.679000 AM,123456789,24/10/2021 09:39:23,22/10/2021 09:39:37,Sm123456789-SM-20211031-VSR-000123.pdf,,,,,26/01/2022 13:08:58,,2,,0
first of all, why are there many commas around the end of the line?
second of all, what if I wanted to access the value "10" (which is the 5th value ) of that string line, is that possible?,
or going further, my task is to check for that 5th value and if its 5 for example, I'd want to take every row with 5thvalue=5 and create a csv for them, if 5thvalue=10 I want to create a csv for those records, and so on. but one task at a time, how do I access that value?
1: commas around the end of the line mean first item of lines is empty ""
2: you can get 5th value as below:
string _list = "50,2,10,201,10,9090339,24-OCT-21 09.38.38.679000 AM,123456789,24/10/2021 09:39:23,22/10/2021 09:39:37,Sm123456789-SM-20211031-VSR-000123.pdf,,,,,26/01/2022 13:08:58,,2,,0";
var fiveIndex = _list.Split(',')[4];
3:
then you can get list of lines that have a value of fiveIndex
var result =_list.Split(',').Select((v, i) => new { value = v, index = i }).Where(item => item.value == fiveIndex);
In your example, line 3 and line 5 have a value of 10(index=2, index=4). Then you can save these lines in csv file.
ended up doing:
string chargeMonth = DateTime.Now.ToString("yyyyMM");
var fileCreationDate = DateTime.Now.ToString("yyyyMMdd");
string fileCreationTime = DateTime.Now.ToString("HHmmss");
string constVal = "MLL";
string fileType = "HIYUV-CHEVRA";
string[] values;
string header, sumRow;
string line, compId;
string inputFile = "records.CSV";
Dictionary<string, System.IO.StreamWriter> outputFiles = new Dictionary<string, System.IO.StreamWriter>();
using (System.IO.StreamReader file = new System.IO.StreamReader("D:\\" + inputFile, Encoding.Default))
{
header = file.ReadLine();
while ((line = file.ReadLine()) != null)
{
values = line.Split(",".ToCharArray());
compId = values[3];
if (!outputFiles.ContainsKey(compId))
{
string outputFileName = constVal + "-" + fileType + "-" + (String.Format("{0:00000}", Int32.Parse(compId))) + "-" + chargeMonth + "-" + fileCreationDate + "-" + fileCreationTime + ".CSV";
outputFiles.Add(compId, new System.IO.StreamWriter("D:\\" + outputFileName));
outputFiles[compId].WriteLine(header);
}
outputFiles[compId].WriteLine(line);
}
}
foreach (System.IO.StreamWriter outputFile in outputFiles.Values)
{
outputFile.Close();
}
and the mission is done.
Related
i need your help!, i am working on a script that, takes the string from a text file that grabs a value from the text file 20 characters.
Now i want to add spaces in front of character that was grabbed from the text file. However, i want to apply it to the whole text file.
For example:
Text 1 A (input):
01253654758965475896N12345
012536547589654758960011223325
(output):
(added 10 spaces in front)01253654758965475896 N12345
(added 10 spaces in front)01253654758965475896 0011223325
The idea is to loop through them, i added 10x spaces in front of and then also added spaces after 01253654758965475896.
Here is my code:
class Program
{
[STAThread]
static void Main(string[] args)
{
int acc = 1;
string calcted = (acc++).ToString().PadLeft(20, '0');
string ft_space = new string(' ', 12);
string path = Console.ReadLine();
using (StreamReader sr = File.OpenText(path))
{
string s = "";
while ((s = sr.ReadToEnd()) != null)
{
string px = s;
string cnd = s.Substring(0, 16);
string cdr = cnd;
px = ft_space + cdr;
Console.Write("Enter Location:");
string pt1 = Console.ReadLine();
if (!File.Exists(pt1))
{
using (TextWriter sw = File.CreateText(pt1))
{
sw.Write(px);
}
}
} Console.ReadKey();
}
}
}
}
As noted in the comments, first change ReadToEnd to ReadLine.
ReadToEnd will read all the file, ReadLine will read one line every loop iteration.
Then, since you want 20 characters and not 16, you need to change s.Substring(0, 16) to s.Substring(0, 20).
After that you need to obtain the rest of the line, so that will be s.Substring(20).
You then need to concatenate all the parts together like this:
string result = spaces10 + first_part + spaces3 + second_part;
Another problem is that you just write the first line since you check if the file exists every time on the loop and you don't write the line if the file exists.
Here is how your code will look after such changes (and others):
string spaces10 = new string(' ', 10);
string spaces3 = new string(' ', 3);
string input_file = Console.ReadLine();
Console.Write("Enter Location:");
string output_file = Console.ReadLine();
using (StreamReader sr = File.OpenText(input_file))
{
using (TextWriter sw = File.CreateText(output_file))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string first_part = line.Substring(0, 20);
string second_part = line.Substring(20);
string result = spaces10 + first_part + spaces3 + second_part;
sw.WriteLine(result);
}
}
}
Console.ReadKey();
I have file.txt like:
EDIT: I didn't wrote but this is important i guess- In file.txt there can be others lines!
folder=c:\user;c:\test;c:\something;
I need to add one path like one list item (List<string> Folders).
So my List should looks like:
Folders[0] = c:\user
Folders[1] = c:\test
etc. (without text "folder=" which starts line in file.txt and ";" which means end of path).
file can contain much more paths.
I did something like this:
using (FileStream fss = new FileStream(path, FileMode.Open))
{
using (StreamReader sr = new StreamReader(fss))
{
while (sr.EndOfStream == false)
{
string line = sr.ReadLine();
if(line.StartsWith("folders"))
{
int index = line.IndexOf("=");
int index1 = line.IndexOf(";");
string folder = line.Substring(index + 1, index1 - (index + 1));
Folders.Add(folder);
Now in List Folders i have first path but what now? I can't go ahead :(
using(var sr = new StreamReader(path))
{
var folders = sr.ReadToEnd()
.Split(new char[]{';','\n','\r'}, StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.Replace("folder=",""))
.ToArray();
Folders.AddRange(folders);
}
You can try following code, using File.ReadAllText
string Filepath = "c:\abc.txt";
string filecontent = File.ReadAllText(Filepath);
string startingString = "=";
var startIndex = filecontent.IndexOf(startingString);
filecontent = filecontent.Substring(startIndex + 1, filecontent.Length - startIndex - 2);
List<String> folders = filecontent.Split(';').ToList();
Here's a simple example:
List<String> Folders = new List<string>();
private void button1_Click(object sender, EventArgs e)
{
string path = #"C:\Users\mikes\Documents\SomeFile.txt";
string folderTag = "folder=";
using (FileStream fss = new FileStream(path, FileMode.Open))
{
using (StreamReader sr = new StreamReader(fss))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (line.StartsWith(folderTag))
{
line = line.Substring(folderTag.Length); // remove the folderTag from the beginning
Folders.AddRange(line.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
}
}
}
}
foreach(string folder in Folders)
{
Console.WriteLine(folder);
}
}
I'd use this approach if you're going to read line by line, and do something else based on what each line starts with. In that case you could add different else if(...) blocks:
if (line.StartsWith(folderTag))
{
line = line.Substring(folderTag.Length); // remove the folderTag from the beginning
Folders.AddRange(line.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
}
else if(line.StartsWith("parameters="))
{
// do something different with a line starting with "parameters="
}
else if (line.StartsWith("unicorns="))
{
// do something else different with a line starting with "unicorns="
}
CSV data to .txt and sum all the amounts
string fileName = "../../TechFiles/";
using (var reader = new StreamReader(ConfigurationManager.AppSettings["ConfigurationSource"]))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
string fullFileName = fileName + values[4] + ".txt";
List<helper> package = new List<helper>
{
new helper() { bankName = values[4], amount = double.Parse(values[6])}
};
List<ResultLine> result = package.GroupBy(i => i.bankName)
.SelectMany(cl => cl.Select(
csLine => new ResultLine
{
bankName = csLine.bankName,
Quantity = cl.Count().ToString(),
amount = cl.Sum(c => c.amount),
}))
.ToList<ResultLine>();
List<string> listA = new List<string>();
foreach (var book in result)
{
if (!listA.Contains(book.bankName))
{
listA.Add(book.bankName);
File.WriteAllText(fullFileName,
book.bankName + " " + book.amount + " " + book.Quantity);
}
}
I put csv path on the app.config then retrieved all the data to the text file, but the problem is I want to some my value[4] which is a header and a sum of all the amounts to the header but it only returns a single amount, so I need a way to pass all the amounts same time so I can be able to sum the total.
You'll either need to loop through all the values twice (once to calculate the sum and once to write the text file), or sum the values as you write them to the text file and then insert the header row to the text file after you have written all the details.
I am a bit in a pickle regarding a consolidation application we are using in our company. We create a csv file from an progress database this csv file has 14 columns and NO header.
The CSV file contains payments (around 173 thousand rows). Most of these rows are the same except for the column amount (last column)
Example:
2014;MONTH;;SC;10110;;;;;;;;EUR;-6500000
2014;01;;SC;10110;;;;;;;;EUR;-1010665
2014;01;;LLC;11110;;;;;;;;EUR;-6567000
2014;01;;SC;10110;;;;;;;;EUR;-1110665
2014;01;;LLC;11110;;;;;;;;EUR;65670.00
2014;01;;SC;10110;;;;;;;;EUR;-11146.65
(around 174000 rows)
As you can see some of these lines are the same except for the amount column. What i need is to sort all rows, add up the amount and save one unique row instead of 1100 rows with different amounts.
My coding skills are failing me to get the job done within a certain timeframe, maybe one of you can push me in the right direction solving this problem.
Example code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string input = File.ReadAllText(#"c:\temp\test.txt");
string inputLine = "";
StringReader reader = new StringReader(input);
List<List<string>> data = new List<List<string>>();
while ((inputLine = reader.ReadLine()) != null)
{
if (inputLine.Trim().Length > 0)
{
string[] inputArray = inputLine.Split(new char[] { ';' });
data.Add(inputArray.ToList());
}
}
//sort data by every column
for (int sortCol = data[0].Count() - 1; sortCol >= 0; sortCol--)
{
data.OrderBy(x => x[sortCol]);
}
//delete duplicate rows
for (int rowCount = data.Count - 1; rowCount >= 1; rowCount--)
{
Boolean match = true;
for (int colCount = 0; colCount < data[rowCount].Count - 2; colCount++)
{
if(data[rowCount][colCount] != data[rowCount - 1][colCount])
{
match = false;
break;
}
}
if (match == true)
{
decimal previousValue = decimal.Parse(data[rowCount - 1][data[rowCount].Count - 1]);
decimal currentValue = decimal.Parse(data[rowCount][data[rowCount].Count - 1]);
string newStrValue = (previousValue + currentValue).ToString();
data[rowCount - 1][data[rowCount].Count - 1] = newStrValue;
data.RemoveAt(rowCount);
}
}
string output = string.Join("\r\n",data.AsEnumerable()
.Select(x => string.Join(";",x.Select(y => y).ToArray())).ToArray());
File.WriteAllText(#"c:\temp\test1.txt",output);
}
}
}
Read the CSV file line by line, and build an in-memory dictionary in which you keep the totals (and other information you require). As most of the lines belong to the same key, it will probably not cause out of memory issues. Afterwards, generate a new CSV based on the information in the dictionary.
As I interpret your question, your problem and the solution you are asking for are how to take your input that are in the form of
#"2014;MONTH;;SC;10110;;;;;;;;EUR;-6500000
2014;01;;SC;10110;;;;;;;;EUR;-1010665
2014;01;;LLC;11110;;;;;;;;EUR;-6567000
2014;01;;SC;10110;;;;;;;;EUR;-1110665
2014;01;;LLC;11110;;;;;;;;EUR;65670.00
2014;01;;SC;10110;;;;;;;;EUR;-11146.65"
Get the last column and then sum it up? If so this is actually very easy to do with something like this
public static void Main()
{
string input = #"2014;MONTH;;SC;10110;;;;;;;;EUR;-6500000
2014;01;;SC;10110;;;;;;;;EUR;-1010665
2014;01;;LLC;11110;;;;;;;;EUR;-6567000
2014;01;;SC;10110;;;;;;;;EUR;-1110665
2014;01;;LLC;11110;;;;;;;;EUR;65670.00
2014;01;;SC;10110;;;;;;;;EUR;-11146.65";
var rows = input.Split('\n');
decimal totalValue = 0m;
foreach(var row in rows)
{
var transaction = row.Substring(row.LastIndexOf(';') +1);
decimal val = 0m;
if(decimal.TryParse(transaction, out val))
totalValue += val;
}
Console.WriteLine(totalValue);
}
But maybe I have misunderstood what you were asking for?
Sorry answering my post so late but this is my final solution
Replacing all " characters and write the output to the stream writer. (going from 25mb to a 15mb file.). Than copy my CSV file to the SQL server so i can bulk insert. After my insert i just query the table and read / write the result set to a new file. My new file is only +/-700KB!
The Filldata() method is filling a datagridview in my application so you can review the result instead of opening the file in excel.
I am new with C#, i am currently writing a new solution to query the csv file directly or in memory and write it back to a new file.
Method1:
string line;
StreamWriter sw = new StreamWriter(insertFile);
using (StreamReader sr = new StreamReader(sourcePath))
{
while ((line = sr.ReadLine()) != null)
{
sw.WriteLine(line.Replace("\"", ""));
}
sr.Close();
sw.Close();
sr.Dispose();
sw.Dispose();
File.Copy(insertFile, #"\\SQLSERVER\C$\insert.csv");
}
Method2:
var destinationFile = #"c:\insert.csv";
var querieImportCSV = "BULK INSERT dbo.TABLE FROM '" + destinationFile + "' WITH ( FIELDTERMINATOR = ';', ROWTERMINATOR = '\n', FIRSTROW = 1)";
var truncate = #"TRUNCATE TABLE dbo.TABLE";
string queryResult =
#"SELECT [Year]
,[Month]
,[Week]
,[Entity]
,[Account]
,[C11]
,[C12]
,[C21]
,[C22]
,[C3]
,[C4]
,[CTP]
,[VALUTA]
,SUM(AMOUNT) as AMOUNT
,[CURRENCY_ORIG]
,[AMOUNTEXCH]
,[AGENTCODE]
FROM dbo.TABLE
GROUP BY YEAR, MONTH, WEEK, Entity, Account, C11, C12, C21, C22, C3, C4, CTP, VALUTA, CURRENCY_ORIG, AMOUNTEXCH, AGENTCODE
ORDER BY Account";
var conn = new SqlConnection(connectionString);
conn.Open();
SqlCommand commandTruncate = new SqlCommand(truncate, conn);
commandTruncate.ExecuteNonQuery();
SqlCommand commandInsert = new SqlCommand(querieImportCSV, conn);
SqlDataReader readerInsert = commandInsert.ExecuteReader();
readerInsert.Close();
FillData();
SqlCommand commandResult = new SqlCommand(queryResult, conn);
SqlDataReader readerResult = commandResult.ExecuteReader();
StringBuilder sb = new StringBuilder();
while (readerResult.Read())
{
sb.Append(readerResult["Year"] + ";" + readerResult["Month"] + ";" + readerResult["Week"] + ";" + readerResult["Entity"] + ";" + readerResult["Account"] + ";" +
readerResult["C11"] + ";" + readerResult["C12"] + ";" + readerResult["C21"] + ";" + readerResult["C22"] + ";" + readerResult["C3"] + ";" + readerResult["C4"] + ";" +
readerResult["CTP"] + ";" + readerResult["Valuta"] + ";" + readerResult["Amount"] + ";" + readerResult["CURRENCY_ORIG"] + ";" + readerResult["AMOUNTEXCH"] + ";" + readerResult["AGENTCODE"]);
}
sb.Replace("\"","");
StreamWriter sw = new StreamWriter(homedrive);
sw.WriteLine(sb);
readerResult.Close();
conn.Close();
sw.Close();
sw.Dispose();
File A B contains million urls.
1, go through the url in file A one by one.
2, extract subdomain.com (http://subdomain.com/path/file)
3, if subdomain.com exist file B, save it to file C.
Any quickest way to get file C with c#?
Thanks.
when i use readline, it have no much different.
// stat
DateTime start = DateTime.Now;
int totalcount = 0;
int n1;
if (!int.TryParse(num1.Text, out n1))
n1 = 0;
// memory
dZLinklist = new Dictionary<string, string>();
// read file
string fileName = openFileDialog1.FileName; // get file name
textBox1.Text = fileName;
StreamReader sr = new StreamReader(textBox1.Text);
string fullfile = File.ReadAllText(#textBox1.Text);
string[] sArray = fullfile.Split( '\n');
//IEnumerable<string> sArray = tool.GetSplit(fullfile, '\n');
//string sLine = "";
//while (sLine != null)
foreach ( string sLine in sArray)
{
totalcount++;
//sLine = sr.ReadLine();
if (sLine != null)
{
//string reg = "http[s]*://.*?/";
//Regex R = new Regex(reg, RegexOptions.Compiled);
//Match m = R.Match(sLine);
//if(m.Success)
int length = sLine.IndexOf(' ', n1); // default http://
if(length > 0)
{
//string urls = sLine.Substring(0, length);
dZLinklist[sLine.Substring(0,length)] = sLine;
}
}
}
TimeSpan time = DateTime.Now - start;
int count = dZLinklist.Count;
double sec = Math.Round(time.TotalSeconds,2);
label1.Text = "(" + totalcount + ")" + count.ToString() + " / " + sec + " = " + (Math.Round(count / sec,2)).ToString();
sr.Close();
I would go for using Microsoft LogParser for processing big files: MS LogParser. Are you limited to implement it in described way only?