How do i change a specific line in a textfile - c#

Im trying to read from a textfile into an array, change one element and then read array back into the file but not appending the original text. But it says the file is being used by another process. Any help is appreciated.
using (StreamReader readName = new StreamReader("fileA"))
{
using (StreamReader readColour = new StreamReader("fileB"))
{
var lineCount = File.ReadLines("fileB").Count();
string[] linesA = new string[lineCount];
string[] linesB = new string[lineCount];
for (int a = 0; a < linesA.Length; a++)
{
if (linesA[a] == UserVariables.userNameC)
{
linesB[a] = UserVariables.colourC.ToString();
}
}
}
}
try
{
using (StreamWriter colourWrite = new StreamWriter("fileB"))
{
for (int a = 0; a < linesB.Length; a++)
colourWrite.WriteLine(linesB[a], false);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error");
}
}

You are trying to read fileB twice,
using (StreamReader readColour = new StreamReader("fileB")) <-- this opens
the file
here and
leaves it
open
{
var lineCount = File.ReadLines("fileB").Count(); <-- this tries to open it,
read it and close it..
but it can't because
you have it open
above..

This part opens fileB two times:
using (StreamReader readColour = new StreamReader("fileB"))
{
var lineCount = File.ReadLines("fileB").Count();

Try adding the line readColour.Close(); in between your read and write sections

Related

Need to write all results to a txt file

I have the query below and it is working fine, I can see the results in the console. But I need to write all the result into a txt file to load it into a table. The query as is only write one line to the txt file. How can I make it write all lines from the output into the txt file? Really appreciate any help on this.
using System;
using Microsoft.AnalysisServices.AdomdClient;
using System.IO;
using System.Diagnostics;
using System.Text;
namespace PowerQry
{
class Program
{
#pragma warning disable IDE0060 // Remove unused parameter
static void Main(string[] args)
#pragma warning restore IDE0060 // Remove unused parameter
{
AdomdConnection adomdConnection = new AdomdConnection("Data Source=localhost:49971");
String query = #"
EVALUATE
SUMMARIZECOLUMNS(
Customer[City],
Customer[Country-Region],
Customer[Customer],
Customer[Customer ID],
Customer[CustomerKey]
)
";
AdomdCommand adomdCommand = new AdomdCommand(query, adomdConnection);
/*******************************************************
connection
*******************************************************/
adomdConnection.Open();
AdomdDataReader reader = adomdCommand.ExecuteReader();
// Create a loop for every row in the resultset
while (reader.Read())
{
String rowResults = "";
// Create a loop for every column in the current row --need to add header
for (
int columnNumber = 0;
columnNumber < reader.FieldCount;
columnNumber++
)
{
rowResults += $"\t{reader.GetValue(columnNumber)}";
}
//Console.WriteLine(rowResults);
//--write all lines to txt
{
string UserName = System.Environment.UserName;
string fileName = #"C:\Temp\nm.txt";
FileStream ostrm;
StreamWriter writer;
TextWriter oldOut = Console.Out;
try
{
ostrm = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);
writer = new StreamWriter(ostrm);
for (int i = 0; i < 10; i++) ;
}
catch (Exception e)
{
Console.WriteLine("Cannot open Redirect.txt for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(writer);
Console.WriteLine(rowResults);
Console.SetOut(oldOut);
writer.Close();
ostrm.Close();
Console.WriteLine("Done");
}
//==
}
adomdConnection.Close();
}
}
}
You can use File.AppendAllLines.
Instead of append to a single string instance you can use List<string>
//String rowResults = "";
List<string> rows = new List<string>();
// Create a loop for every column in the current row --need to add header
for (int columnNumber = 0; columnNumber < reader.FieldCount;columnNumber++)
{
// tabulator should be removed
rows.Add($"\t{reader.GetValue(columnNumber)}");
// rowResults += $"\t{reader.GetValue(columnNumber)}";
}
File.AppendAllLines(your path - for example #"C:\output.txt", rows);

create lines with strings for each blank line until it reaches line 100

I'm new to C# i need help on reading a file that currently has 7 lines of text but I need it to write "Line PlaceHolder" after those 7 lines until it reaches line 100 in the text file. This is what i have so far and i know it's my failed attempt: EDIT: It's good but only issue is an exception is throw that a process is already using the text file, how do I solve this to read/write that file at the same time??
public void ReadFile()
{
if (File.Exists(AccountsFile))
{
using (StreamReader Reader = new StreamReader(AccountsFile))
using (StreamWriter Writer = new StreamWriter((AccountsFile)))
{
for (int i = 0; i < 100; i++)
{
string line;
if ((line = Reader.ReadLine()) == null)
{
Writer.WriteLine("Line Placeholder");
}
}
}
}
else
{
File.Create(AccountsFile);
}
}
You could first read the file contents into an array using File.ReadAllLines, get the array .Length (representing the number of lines in the file), and subtract that number from 100 to see how many lines you need to write. If the number is greater than zero, then create a List<string> with that many empty lines and write those lines to the end of the file using File.AppendAllLines:
// See how many lines we need to add
var newLinesNeeded = 100 - File.ReadAllLines(AccountsFile).Length;
// Add them if needed
if (newLinesNeeded > 0)
{
// Create a list of empty lines
var blankLines = new List<string>();
for(int i = 0; i < newLinesNeeded; i++)
{
blankLines.Add("");
}
// Append them to our file
File.AppendAllLines(AccountsFile, blankLines);
}
Looks like you are just missing an else:
public void ReadFile()
{
if (File.Exists(AccountsFile))
{
using (StreamReader Reader = new StreamReader(AccountsFile))
using (StreamWriter Writer = new StreamWriter((AccountsFile)))
{
for (int i = 0; i < 100; i++)
{
string line;
if ((line = Reader.ReadLine()) == null)
{
Writer.WriteLine("Line Placeholder");
}
else
Writer.WriteLine(line);
}
}
}
else
{
File.Create(AccountsFile);
}
}
this may work if you do not mind opening the file as Read/Write
using (FileStream fileStream = File.Open(AccountsFile, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
var streamWriter = new StreamWriter(fileStream);
var streamReader = new StreamReader(fileStream);
var i = 0;
// read and count the lines
while (streamReader.ReadLine() != null){
i++;
}
// if any more lines are needed write them
while (i++ < 100)
{
streamWriter.WriteLine("Line Placeholder");
}
streamWriter.Flush();
}

Reading and writing very large text files in C#

I have a very large file, almost 2GB in size. I am trying to write a process to read the file in and write it out without the first row. I pretty much have been only able to read and write one line at a time which takes forever. I can open it, remove the first row and save it faster in TextPad, though that is still very slow.
I use this code to get the number of records in the file:
private long getNumRows(string strFileName)
{
long lngNumRows = 0;
string strMsg;
try
{
lngNumRows = 0;
using (var strReader = File.OpenText(#strFileName))
{
while (strReader.ReadLine() != null)
{
lngNumRows++;
}
strReader.Close();
strReader.Dispose();
}
}
catch (Exception excExcept)
{
strMsg = "The File could not be read: ";
strMsg += excExcept.Message;
System.Windows.MessageBox.Show(strMsg);
//Console.WriteLine("Thee was an error reading the file: ");
//Console.WriteLine(excExcept.Message);
//Console.ReadLine();
}
return lngNumRows;
}
This only takes seconds to run. When I add the following code it takes forever to run. Am I doing something wrong? Why does the write add so much time? Any ideas on how I can make this faster?
private void ProcessTextFiles(string strFileName)
{
string strDataLine;
string strFullOutputFileName;
string strSubFileName;
int intPos;
long lngTotalRows = 0;
long lngCurrNumRows = 0;
long lngModNumber = 0;
double dblProgress = 0;
double dblProgressPct = 0;
string strPrgFileName = "";
string strOutName = "";
string strMsg;
long lngFileNumRows;
try
{
using (StreamReader srStreamRdr = new StreamReader(strFileName))
{
while ((strDataLine = srStreamRdr.ReadLine()) != null)
{
lngCurrNumRows++;
if (lngCurrNumRows > 1)
{
WriteDataRow(strDataLine, strFullOutputFileName);
}
}
srStreamRdr.Dispose();
}
}
catch (Exception excExcept)
{
strMsg = "The File could not be read: ";
strMsg += excExcept.Message;
System.Windows.MessageBox.Show(strMsg);
//Console.WriteLine("The File could not be read:");
//Console.WriteLine(excExcept.Message);
}
}
public void WriteDataRow(string strDataRow, string strFullFileName)
{
//using (StreamWriter file = new StreamWriter(#strFullFileName, true, Encoding.GetEncoding("iso-8859-1")))
using (StreamWriter file = new StreamWriter(#strFullFileName, true, System.Text.Encoding.UTF8))
{
file.WriteLine(strDataRow);
file.Close();
}
}
Not sure how much this will improve the performance, but surely, opening and closing the output file for every line that you want to write is not a good idea.
Instead open both files just one time and then write the line directly
using (StreamWriter file = new StreamWriter(#strFullFileName, true, System.Text.Encoding.UTF8))
using (StreamReader srStreamRdr = new StreamReader(strFileName))
{
while ((strDataLine = srStreamRdr.ReadLine()) != null)
{
lngCurrNumRows++;
if (lngCurrNumRows > 1)
file.WriteLine(strDataRow);
}
}
You could also remove the check on lngCurrNumRow simply making an empty read before entering the while loop
strDataLine = srStreamRdr.ReadLine();
if(strDataLine != null)
{
while ((strDataLine = srStreamRdr.ReadLine()) != null)
{
file.WriteLine(strDataRow);
}
}
Depending on the memory of your machine. You could try the following (my big file was "D:\savegrp.log" I had a 2gb file knocking about) This used about 6gb memory when I tried it
int counter = File.ReadAllLines(#"D:\savegrp.log").Length;
Console.WriteLine(counter);
It does depends on the memory available..
File.WriteAllLines(#"D:\savegrp2.log",File.ReadAllLines(#"D:\savegrp.log").Skip(1));
Console.WriteLine("file saved");

Output not correctly being written to CSV

So I am having an issue with my output being written to a CSV file. The output to this code is in the correct format when being written to the CSV file but it is only entering a single row in the file. There should be much more. Around 150 lines. Current out put is:
(859.85 7N830127 185)
Which is correct, but there should be more of these. It seems like to me that it is only writing the first line of the parsed EDI file and then stopping. I need to find a way to make sure it writes all data that is being parsed can anyone help me?
static void Main(string[] args)
{
StreamReader sr = new StreamReader("edifile.txt");
string[] ediMapTemp = sr.ReadLine().Split('|');
List<string[]> ediMap = new List<string[]>();
List<object[]> outputMatrix = new List<object[]>();
foreach (var line in ediMapTemp)
{
ediMap.Add(line.Split('~'));
}
DetailNode node = new DetailNode(0, null, 0);
int hierarchicalDepth = 0;
int hierarchicalIdNumber;
int hierarchicalParentIdNumber;
int hierarchicalLevelCode;
int hierarchicalChildCode = 0;
for (int i = 0; i < ediMap.Count; i++)
{
string segmentHeader = ediMap[i][0];
if (segmentHeader == "HL")
{
hierarchicalIdNumber = Convert.ToInt32(ediMap[i][1]);
hierarchicalParentIdNumber = Convert.ToInt32(ediMap[i][2]);
hierarchicalLevelCode = Convert.ToInt32(ediMap[i][3]);
hierarchicalChildCode = Convert.ToInt32(ediMap[i][4]);
List<string[]> levelDetails = new List<string[]>();
for (int v = i + 1; v < ediMap.Count; v++)
{
if (ediMap[v][0] == "HL") break;
levelDetails.Add(ediMap[v]);
}
DetailNode getNode = node.Find(node, hierarchicalParentIdNumber);
getNode.headList.Add(new DetailNode(hierarchicalIdNumber, levelDetails, getNode.depth + 1));
}
}
node.Traversal(new VID(), node);
foreach (var vid in VIDList.vidList)
using (StreamWriter writer = new StreamWriter("Import.csv"))
{
//probably a loop here
writer.WriteLine(String.Join(",", vid.totalCurrentCharges, vid.assetId, vid.componentName, vid.recurringCharge));
}
}
Quick Review, should the code be the following:
using (StreamWriter writer = new StreamWriter("Import.csv"))
{
//a loop here
foreach (var vid in VIDList.vidList)
{
writer.WriteLine(String.Join(",", vid.totalCurrentCharges, vid.assetId, vid.componentName, vid.recurringCharge));
}
}
You would open the file once and then loop thru your collection, writing each one.
It looks to me like you're re-opening the output file for each line you're trying to write, so you're overwriting the output file with a new file for each line. That would mean only the last entry remains in the file. Try moving this line
using (StreamWriter writer = new StreamWriter("Import.csv"))
Outside the foreach loop.

How to write back to the CSV file

I am trying to write back to CSV file , How can I change this script to write back to CSV file,I am new to C#? Please help me
public void Main()
{
List<String> lines = new List<string>();
string line;
System.IO.StreamReader file = new System.IO.StreamReader("C:\\NewFolder\\Test.csv");
while ((line = file.ReadLine()) != null)
{
lines.Add(line);
}
lines.RemoveAll(l => l.Contains(",,,,,"));
using (System.IO.StreamWriter writer = new System.IO.StreamWriter("C:\\NewFolder\\Test.csv", false))
{
for (int i = 0; i < lines.Count; i++)
{
writer.WriteLine(lines[i]);
}
}
Dts.TaskResult = (int)ScriptResults.Success;
}
Simply this
//Convert your list to csv string
string toWrite = string.Join(",",lines );
File.WriteAllText(YourFilePath, toWrite);
You're using a StreamReader to read from the file. Use a StreamWriter to write back to it. This code should do it
using (System.IO.StreamWriter writer = new System.IO.StreamWriter("c:\\test.txt", false))
{
for (int i = 0; i < lines.Count; i++)
{
writer.WriteLine(lines[i]);
}
}
Note this assumes 2 things:
You've closed your reader
You're wanting to replace the original file
EDIT: Alternatively you can rewrite the whole thing as:
string fileName = "C:\\NewFolder\\Test.csv";
List<string> lines = System.IO.File.ReadAllLines(fileName).ToList();
lines.RemoveAll(l => l.Contains(",,,,,"));
System.IO.File.WriteAllLines(fileName, lines.ToArray());

Categories