I'm very new to C# ; does someone know how to write ALL output lines to a .txt file without starting new process?
This code writes only the last record:
class Program
{
static void Main(string[] args)
{
WezKomponent("Win32_DiskDrive", "Model");
Console.ReadKey();
}
private static void WezKomponent(string ass, string sax)
{
ManagementObjectSearcher wez = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + ass);
foreach (ManagementObject pie in wez.Get())
{
Console.WriteLine(Convert.ToString(pie[sax]));
StreamWriter SW = new StreamWriter(#"HDD.txt");
SW.WriteLine(Convert.ToString(pie[sax]));
SW.Close();
}
}
}
Actually, it does indeed write all the records to the file, the problem is that you overwrite the file each time, and thus what you observe is that only the last record is kept.
There are two solutions to this:
Open the file before the loop, write all the records, then close the file
Open the file inside the loop, but do so in a manner that will append new content
In general it's easier to get the first one right, so here's how to do it that way:
Move the opening of the stream up and out of the loop
Move the closing of the stream down and out of the loop
In essence you take these lines of code:
private static void WezKomponent(string ass, string sax)
{
ManagementObjectSearcher wez = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + ass);
foreach (ManagementObject pie in wez.Get())
{
Console.WriteLine(Convert.ToString(pie[sax]));
StreamWriter SW = new StreamWriter(#"HDD.txt");
SW.WriteLine(Convert.ToString(pie[sax]));
SW.Close();
}
}
And change them to this:
private static void WezKomponent(string ass, string sax)
{
ManagementObjectSearcher wez = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + ass);
StreamWriter SW = new StreamWriter(#"HDD.txt");
foreach (ManagementObject pie in wez.Get())
{
Console.WriteLine(Convert.ToString(pie[sax]));
SW.WriteLine(Convert.ToString(pie[sax]));
}
SW.Close();
}
Additionally, to be more failsafe in case of errors, it is better using this syntax:
using (... = new SomethingThatImplementsIDisposable(...))
{
}
than this:
... = new SomethingThatImplementsIDisposable(...);
...
...Close(); // or .Dispose();
So here's a better version of your method:
private static void WezKomponent(string ass, string sax)
{
using (ManagementObjectSearcher wez = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + ass))
using (StreamWriter SW = new StreamWriter(#"HDD.txt"))
{
foreach (ManagementObject pie in wez.Get())
{
Console.WriteLine(Convert.ToString(pie[sax]));
SW.WriteLine(Convert.ToString(pie[sax]));
}
}
}
The reason why this is better is because of the chance of exceptions in your code. If that happens, SW.Close(); will not be executed which means that you leave the stream and the file open, at least longer than intended. With a using clause like this, if an exception happens inside, the Dispose method on these objects will be called, closing the file, and in this case the ManagementObjectSearcher object as well.
So is there any way to improve your code even further? Yes, but only if you either know this other syntax I'm about to show, or willing to learn. Since you said you were new to C# you might not know it, and you might want to get comfortable with your existing code before making it even more complex from your point of view.
There's several ways to write to text files, StreamWriter is one of them, File.WriteAllLines is another but this expects the content to write to be provided as a collection of strings that will be written as a series of lines to the file.
So how can we get from your ManagementObjectSearcher object to a list of strings?
Through a set of syntax and .NET classes collectively known as "LINQ" or "Language INtegrated Query".
Here's a shorter version of your method:
private static void WezKomponent(string ass, string sax)
{
using (ManagementObjectSearcher wez = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + ass))
{
File.WriteAllLines(#"HDD.txt", wez
.Get()
.Select(pie => ConvertToString(pie[sax])));
}
}
This can even be shortened down to just put more on each line and removing some unnecessary braces, and using var when the exact type can easily be discerned from the surrounding code:
private static void WezKomponent(string ass, string sax)
{
using (var wez = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + ass))
File.WriteAllLines(#"HDD.txt", wez.Get().Select(pie => ConvertToString(pie[sax])));
}
class Program
{
static void Main(string[] args)
{
WezKomponent("Win32_DiskDrive", "Model");
Console.ReadKey();
}
private static void WezKomponent(string ass, string sax)
{
ManagementObjectSearcher wez = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + ass);
StreamWriter SW = new StreamWriter(#"HDD.txt");
foreach (ManagementObject pie in wez.Get())
{
Console.WriteLine(Convert.ToString(pie[sax]));
SW.WriteLine(Convert.ToString(pie[sax]));
}
SW.Close();
}
Try initializing StreamWriter in a different manner.
StreamWriter SW = new StreamWriter(#"HDD.txt", append: true);
Note append: true in the constructor call.
Related
All I need is for file1 and file2 to show the text inside the file. File1 is working great! File2 not so much. I believe there is something wrong with how I wrote file2 being read. Because I made a class so that I can make file2's text go to another file called outputfile2, and even that isn't working.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
namespace RandomName
{
class Program
{
static void Main(string[] args)
{
string winDir =
"C:/Users/RandomPerson/Desktop/RandomName/bin/Debug/";
string fileName = "file1.txt";
StreamReader reader = new StreamReader(winDir + fileName);
string outputFileName = "upperfile" + fileName;
StreamWriter writer = new StreamWriter(outputFileName);
int n = 0;
string st = "";
string upperString = "";
int n2 = 0;
string st2 = "";
string upperString2 = "";
string fileName2 = "file2.txt";
StreamReader reader2 = new StreamReader(winDir + fileName2);
string outputFileName2 = "output" + fileName2;
StreamWriter writer2 = new StreamWriter(outputFileName2);
do
{
++n;
st = reader.ReadLine(); // read one line from disk file
Console.WriteLine("Line #" + n + ": " + st); // write to the console
writer.WriteLine(st); // write line to disk file instead, using WriteLine() method
upperString = upperString + "\n" + st; // append each line to the big string
}
while (!reader.EndOfStream);
do
{
++n2;
st2 = reader2.ReadLine(); // read one line from disk file
Console.WriteLine("Line #" + n2 + ": " + st2); // write to the
console
writer2.WriteLine(st2); // write line to disk file instead,
using WriteLine() method
upperString2 = upperString2 + "\n" + st2; // append each line
to the big string
}
while (!reader2.EndOfStream);
reader.Close();
writer.Close();
Console.WriteLine("\nHere is the entire file in a string:");
Console.WriteLine(upperString);
Console.WriteLine(upperString2);
UpperString b = new UpperString(upperString);
UpperString2 c = new UpperString2(upperString2);
Console.WriteLine("\nThe string in reverse case: ");
b.showReverseCase();
Console.WriteLine("\n");
c.readingFile2();
c.toNewFile2();
}
}
}
"b." is for another class that I have. I copied the code from that class into the "c." one, changing names of strings and such. And that didn't work. Which is why I think something is wrong somewhere in the main.
Here is the class
class UpperString2
{
private string upperString2;
public UpperString2() { }
public UpperString2(string c) { upperString2 = c; }
public void readingFile2()
{
string[] lines = System.IO.File.ReadAllLines("C:/Users/SomeName/Desktop/FolderName/bin/Debug/file2.txt");
System.Console.WriteLine("\nAnother Poem \n");
foreach (string line in lines)
{
// Use a tab to indent each line of the file.
Console.WriteLine(line);
}
}
public void toNewFile2()
{
using (StreamWriter writetext = new StreamWriter("outputfile2.txt"))
{
string newText = (upperString2.ToUpper()).ToString();
writetext.WriteLine(newText);
}
}
I am a bit new to SteamReader and SteamWriter, which is why I think I went wrong somehow with that. I'm not sure what though. Thank you anyone who can help me have the text in file2 show up without it being overwritten by file1's text!
The problem is "outputfile2" was already opened by reader2 in Main().
string fileName2 = "file2.txt";
StreamReader reader2 = new StreamReader(winDir + fileName2);
string outputFileName2 = "output" + fileName2; //<--outputfile2.txt
StreamWriter writer2 = new StreamWriter(outputFileName2)
Then it raises an exception when you try to open the same file for writting in toNewFile2():
public void toNewFile2()
{
using (StreamWriter writetext = new StreamWriter("outputfile2.txt"))
{
string newText = (upperString2.ToUpper()).ToString();
writetext.WriteLine(newText);
}
}
This happens because the object writer2 is still alive and locking the file in Main() and there's no using statement for disposing the object when no longer needed.
Since you have moved the code to a class, call that class instead.
today i wrote my second Code in C#
why wont it work? the code ist (as it seems) correct!
error code: InvalidQuery
Code:
static void Main(string[] args)
{
GetComponent("Win32_Processor", "Name");
Console.Read();
Console.ReadKey();
}
private static void GetComponent(string hwclass, string syntax)
{
ManagementObjectSearcher mos = new ManagementObjectSearcher ("root\\CIMV2","SELECT * FROM" + hwclass);
foreach(ManagementObject mj in mos.Get())
{
Console.WriteLine(Convert.ToString(mj[syntax]));
}
}
Please, use formatting or string interpolation (C# 6.0+) to avoid syntax errors:
private static void GetComponent(string hwclass, string syntax) {
//DONE: keep query readable
string query =
$#"select *
from {hwclass}"; // <- you've missed space here
//DONE: wrap IDisposable into using
using (ManagementObjectSearcher mos = new ManagementObjectSearcher("root\\CIMV2", query)) {
foreach(ManagementObject mj in mos.Get())
Console.WriteLine(Convert.ToString(mj[syntax]));
}
}
You are missing a space after the "FROM":
("root\\CIMV2","SELECT * FROM" + hwclass);
Change to:
("root\\CIMV2","SELECT * FROM " + hwclass);
I'm trying to write a file with this File class method in C#.
public static void WriteAllLines(string path, IEnumerable<string> contents);
The end of line is CRLF but I need this to be LF.
WriteAllLines uses a StreamWriter to write the lines to a file, using the newline string specified in the NewLine property.
You can use the StreamWriter in your own code and use \n instead of \r\n. This has the benefit that you avoid string concatenations and generating temporary strings :
using (var writer = new StreamWriter(path))
{
writer.NewLine = "\n";
foreach (var line in contents)
{
writer.WriteLine(line );
}
}
Using a StreamWriter directly allows you to use asynchronous methods as well:
public async Task MyMethod()
{
....
using (var writer = new StreamWriter(path))
{
writer.NewLine = "\n";
foreach (var line in contents)
{
await writer.WriteLineAsync(line);
}
}
....
}
This can be a big benefit when writing large files, in server and web applications and web sites where you want to keep blocking at a minimum
There are so many ways of writing to a file, I'd just go with a different one - only a couple lines:
using (var writer = new StreamWriter(path)) {
foreach (var line in contents) {
writer.Write(line + "\n");
}
}
Instead of using WriteAllLines(), you can join the strings yourself and use WriteAllText():
File.WriteAllText(string path, string.Join("\n", contents) + "\n");
var builder = new StringBuilder();
for (int i = 0; i < 99999; i++)
{
builder.Append(i.ToString() + '\n');
}
File.WriteAllText("asd.txt", builder.ToString());
That is obviously with boilerplate code. Keep in mind that using a StringBuilder instead of a string[] is also faster.
I'd go with this, it avoids re-writing to memory and works quickly. This assumes you are only using ASCII and don't need to overwrite the file - otherwise use a different encoding and change the file mode accordingly.
public static void WriteAllLines(string path, IEnumerable<string> contents)
{
using (var s = new FileStream(path, FileMode.Append))
{
foreach (var line in contents)
{
var bytes = Encoding.ASCII.GetBytes($"{line}\r");
s.Write(bytes,0,bytes.Length);
}
s.Flush();
s.Close();
}
}
I'm new to programming and face some difficulties. I hope to save the data I'm generating (a WPF DataGrid) into a text file.
This is what I currently have:
MainWindow.xaml.cs:
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
string fileName = #"D:\projects\PersonInfos\Files\PersonInfos_Copy.txt";
PersonInfosTable.ConvertToTXTFile(fileName);
}
PersonInfosTable.cs:
public void ConvertToTXTFile(string fileName)
{
StringBuilder sb = new StringBuilder();
System.Text.Encoding Output = null;
Output = System.Text.Encoding.Default;
foreach (PersonInfos personinfos in PersonInfoDetails)
{
if (PersonInfos.SelectCheckBox == true)
{
string line = String.Format("L§" + personinfos.FirstName + "§" + personinfos.LastName + "§");
sb.AppendLine(line);
StreamWriter file = new StreamWriter(fileName);
file.WriteLine(sb);
file.Close();
}
}
}
Unfortunately, this doesn't work. PersonInfosDetails is of type ObservationCollections<T> and SelectCheckBox is the check box selected by the user, and indicates which files the user wants to save.
Any ideas or suggestions? I'd appreciate your help so much and thank you so much for your time!
It is not clear what is the SelectCheckBox property. However, you need to move the writing part of your program outside the loop. Inside the loop just add every person info to your StringBuilder instance.
public void ConvertToTXTFile(string fileName)
{
StringBuilder sb = new StringBuilder();
System.Text.Encoding Output = System.Text.Encoding.Default;
foreach (PersonInfos personinfos in PersonInfoDetails)
{
// Collect every personinfos selected in the stringbuilder
if (personinfos.SelectCheckBox == true)
{
string line = String.Format("L§" + personinfos.FirstName + "§" + personinfos.LastName + "§");
sb.AppendLine(line);
}
}
// Now write the content of the StringBuilder all together to the output file
File.WriteAllText(filename, sb.ToString())
}
Have you tried How to: Write to a Text File (C# Programming Guide)?
Also, the code you've supplied won't work unless SelectCheckBox is a static property of the PersonInfos class. You'll probably have to change the if statement to
if (personInfos.SelectCheckBox == true)
{
// ...
}
Firstly, i'd just like to mention that I've only started learning C# a few days ago so my knowledge of it is limited.
I'm trying to create a program that will parse text files for certain phrases input by the user and then output them into a new text document.
At the moment, i have it the program searching the original input file and gathering the selected text input by the user, coping those lines out, creating new text files and then merging them together and also deleting them afterwards.
I'm guessing that this is not the most efficient way of creating this but i just created it and had it work in a logical manor for me to understand as a novice.
The code is as follows;
private void TextInput1()
{
using (StreamReader fileOpen = new StreamReader(txtInput.Text))
{
using (StreamWriter fileWrite = new StreamWriter(#"*DIRECTORY*\FIRSTFILE.txt"))
{
string file;
while ((file = fileOpen.ReadLine()) != null)
{
if (file.Contains(txtFind.Text))
{
fileWrite.Write(file + "\r\n");
}
}
}
}
}
private void TextInput2()
{
using (StreamReader fileOpen = new StreamReader(txtInput.Text))
{
using (StreamWriter fileWrite = new StreamWriter(#"*DIRECTORY*\SECONDFILE.txt"))
{
string file;
while ((file = fileOpen.ReadLine()) != null)
{
if (file.Contains(txtFind2.Text))
{
fileWrite.Write("\r\n" + file);
}
}
}
}
}
private static void Combination()
{
ArrayList fileArray = new ArrayList();
using (StreamWriter writer = File.CreateText(#"*DIRECTORY*\FINALOUTPUT.txt"))
{
using (StreamReader reader = File.OpenText(#"*DIRECTORY*\FIRSTFILE.txt"))
{
writer.Write(reader.ReadToEnd());
}
using (StreamReader reader = File.OpenText(#"*DIRECTORY*\SECONDFILE.txt"))
{
writer.Write(reader.ReadToEnd());
}
}
}
private static void Delete()
{
if (File.Exists(#"*DIRECTORY*\FIRSTFILE.txt"))
{
File.Delete(#"*DIRECTORY*\FIRSTFILE.txt");
}
if (File.Exists(#"*DIRECTORY*\SECONDFILE.txt"))
{
File.Delete(#"*DIRECTORY*\SECONDFILE.txt");
}
}
The output file that is being created is simply outputting the first text input followed by the second. I am wondering if it is possible to be able to merge them into 1 file, 1 line at a time as it is a consecutive file meaning have the information from Input 1 followed 2 is needed rather than all of 1 then all of 2.
Thanks, Neil.
To combine the two files content in an one merged file line by line you could substitute your Combination() code with this
string[] file1 = File.ReadAllLines("*DIRECTORY*\FIRSTFILE.txt");
string[] file2 = File.ReadAllLines("*DIRECTORY*\SECONDFILE.txt");
using (StreamWriter writer = File.CreateText(#"*DIRECTORY*\FINALOUTPUT.txt"))
{
int lineNum = 0;
while(lineNum < file1.Length || lineNum < file2.Length)
{
if(lineNum < file1.Length)
writer.WriteLine(file1[lineNum]);
if(lineNum < file2.Length)
writer.WriteLine(file2[lineNum]);
lineNum++;
}
}
This assumes that the two files don't contains the same number of lines.
try this method. You can receive three paths. File 1, File 2 and File output.
public void MergeFiles(string pathFile1, string pathFile2, string pathResult)
{
File.WriteAllText(pathResult, File.ReadAllText(pathFile1) + File.ReadAllText(pathFile2));
}
If the pathResult file exists, the WriteAllText method will overwrite it. Remember to include System.IO namespace.
Important: It is not recommended for large files! Use another options available on this thread.
If your input files are quite large and you run out of memory, you could also try wrapping the two readers like this:
using (StreamWriter writer = File.CreateText(#"*DIRECTORY*\FINALOUTPUT.txt"))
{
using (StreamReader reader1 = File.OpenText(#"*DIRECTORY*\FIRSTFILE.txt"))
{
using (StreamReader reader2 = File.OpenText(#"*DIRECTORY*\SECONDFILE.txt"))
{
string line1 = null;
string line2 = null;
while ((line1 = reader1.ReadLine()) != null)
{
writer.WriteLine(line1);
line2 = reader2.ReadLine();
if(line2 != null)
{
writer.WriteLine(line2);
}
}
}
}
}
Still, you have to have an idea how many lines you have in your input files, but I think it gives you the general idea to proceed.
Using a FileInfo extension you could merge one or more files by doing the following:
public static class FileInfoExtensions
{
public static void MergeFiles(this FileInfo fi, string strOutputPath , params string[] filesToMerge)
{
var fiLines = File.ReadAllLines(fi.FullName).ToList();
fiLines.AddRange(filesToMerge.SelectMany(file => File.ReadAllLines(file)));
File.WriteAllLines(strOutputPath, fiLines.ToArray());
}
}
Usage
FileInfo fi = new FileInfo("input");
fi.MergeFiles("output", "File2", "File3");
I appreciate this question is almost old enough to (up)vote (itself), but for an extensible approach:
const string FileMergeDivider = "\n\n";
public void MergeFiles(string outputPath, params string[] inputPaths)
{
if (!inputPaths.Any())
throw new ArgumentException(nameof(inputPaths) + " required");
if (inputPaths.Any(string.IsNullOrWhiteSpace) || !inputPaths.All(File.Exists))
throw new ArgumentNullException(nameof(inputPaths), "contains invalid path(s)");
File.WriteAllText(outputPath, string.Join(FileMergeDivider, inputPaths.Select(File.ReadAllText)));
}