How to write contents of an array to a text file? C# - c#

I'm trying to write the contents of an array to a text file. I've created the file, assigned text boxes to the array (not sure if correctly). Now I want to write the contents of the array to a text file. The streamwriter part is where I'm stuck at the bottom. Not sure of the syntax.
if ((!File.Exists("scores.txt"))) //Checking if scores.txt exists or not
{
FileStream fs = File.Create("scores.txt"); //Creates Scores.txt
fs.Close(); //Closes file stream
}
List<double> scoreArray = new List<double>();
TextBox[] textBoxes = { week1Box, week2Box, week3Box, week4Box, week5Box, week6Box, week7Box, week8Box, week9Box, week10Box, week11Box, week12Box, week13Box };
for (int i = 0; i < textBoxes.Length; i++)
{
scoreArray.Add(Convert.ToDouble(textBoxes[i].Text));
}
StreamWriter sw = new StreamWriter("scores.txt", true);

You could just do this:
System.IO.File.WriteAllLines("scores.txt",
textBoxes.Select(tb => (double.Parse(tb.Text)).ToString()));

using (FileStream fs = File.Open("scores.txt"))
{
StreamWriter sw = new StreamWriter(fs);
scoreArray.ForEach(r=>sw.WriteLine(r));
}

You may try to write to the file before you close it... after the FileStream fs = File.Create("scores.txt"); line of code.
You may also want to use a using for that.
Like this:
if ((!File.Exists("scores.txt"))) //Checking if scores.txt exists or not
{
using (FileStream fs = File.Create("scores.txt")) //Creates Scores.txt
{
// Write to the file here!
}
}

You can convert your List to an array then write the array to a textfile
double[] myArray = scoreArray.ToArray();
File.WriteAllLines("scores.txt",
Array.ConvertAll(myArray, x => x.ToString()));

Just do this to resolve your issue
Form.Close();

Related

How to go from byte[], to MemoryStream, Unzip, then write to FileStream

I am unsure what I am doing wrong. The files that I create after grabbing a byte[] (which is emailAttachment.Body) and passing it to the method ExtractZipFile, converting it to MemoryStream and then unzipping it, returning it as a KeyValuePair and then Writing to a file using FileStream.
However when I go to open the new created files there is an error in opening them. They are not able to be opened.
The below are in the same class
using Ionic.Zip;
var extractedFiles = ExtractZipFile(emailAttachment.Body);
foreach (KeyValuePair<string, MemoryStream> extractedFile in extractedFiles)
{
string FileName = extractedFile.Key;
using (FileStream file = new FileStream(CurrentFileSystem +
FileName.FileFullPath(),FileMode.Create, System.IO.FileAccess.Write))
{
byte[] bytes = new byte[extractedFile.Value.Length];
extractedFile.Value.Read(bytes, 0, (int) xtractedFile.Value.Length);
file.Write(bytes,0,bytes.Length);
extractedFile.Value.Close();
}
}
private Dictionary<string, MemoryStream> ExtractZipFile(byte[] messagePart)
{
Dictionary<string, MemoryStream> result = new Dictionary<string,MemoryStream>();
MemoryStream data = new MemoryStream(messagePart);
using (ZipFile zip = ZipFile.Read(data))
{
foreach (ZipEntry ent in zip)
{
MemoryStream memoryStream = new MemoryStream();
ent.Extract(memoryStream);
result.Add(ent.FileName,memoryStream);
}
}
return result;
}
Is there something I am missing? I do not want to save the original zip file just the extracted Files from MemoryStream.
What am I doing wrong?
After writing to your MemoryStream, you're not setting the position back to 0:
MemoryStream memoryStream = new MemoryStream();
ent.Extract(memoryStream);
result.Add(ent.FileName,memoryStream);
Because of this, the stream position will be at the end when you try to read from it, and you'll read nothing. Make sure to rewind it:
memoryStream.Position = 0;
Also, you don't have to handle the copy manually. Just let the CopyTo method take care of it:
extractedFile.Value.CopyTo(file);
I'd suggest that you clean up your use of MemoryStream in your code.
I agree that calling memoryStream.Position = 0; will allow this code to work correctly, but it's an easy thing to miss when reading and writing memory streams.
It's better to write code that avoids the bug.
Try this:
private IEnumerable<(string Path, byte[] Content)> ExtractZipFile(byte[] messagePart)
{
using (var data = new MemoryStream(messagePart))
{
using (var zipFile = ZipFile.Read(data))
{
foreach (var zipEntry in zipFile)
{
using (var memoryStream = new MemoryStream())
{
zipEntry.Extract(memoryStream);
yield return (Path: zipEntry.FileName, Content: memoryStream.ToArray());
}
}
}
}
}
Then your calling code would look something like this:
foreach (var extractedFile in ExtractZipFile(emailAttachment.Body))
{
File.WriteAllBytes(Path.Combine(CurrentFileSystem, extractedFile.Path.FileFullPath()), extractedFile.Content);
}
It's just a lot less code and a much better chance of avoiding bugs. The number one predictor of bugs in code is the number of lines of code you write.
Since I find it all a lot of code for a simple operation, here's my two cents.
using Ionic.Zip;
using (var s = new MemoryStream(emailAttachment.Body))
using (ZipFile zip = ZipFile.Read(s))
{
foreach (ZipEntry ent in zip)
{
string path = Path.Combine(CurrentFileSystem, ent.FileName.FileFullPath())
using (FileStream file = new FileStream(path, FileAccess.Write))
{
ent.Extract(file);
}
}
}

How to read a line and write to that line, of a text file?

I'm use MS-Visual Studio 2015, develop a Winforms application in C#.
What I'm trying to reach is a reader&writer which opens a CSV file with UTF-8 coding, and reads line for line. My program actually reads a line, split it at the semicolons (;) and send that informations to my database. Now it should mark that line as already read, by appending a text or a special sign e.g. ("read" or "done" or "§$%").
Because it's possible that someone or something (ERP-Systems), appends new data to that CSV file. So, the next time my program iterates through that file, it shall only read the line without my special mark.
my program:
foreach (string sFile in Directory.GetFiles(sImportPfad, "*.*", SearchOption.TopDirectoryOnly))
{
var oStream = new FileStream(sFile, FileMode.Append, FileAccess.Write, FileShare.Read);
var iStream = new FileStream(sFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var sw = new System.IO.StreamWriter(oStream);
var sr = new System.IO.StreamReader(iStream);
int c = 0;
// alle Zeilen jedes Files laden
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
String[] splitLine = line.Trim().Split(txtDivider.Text.Trim().ToCharArray());
if (line.Contains("§$%"))
break;
DatenbankEintragAuftragsPool dbEintrag = new DatenbankEintragAuftragsPool();
foreach (myImportFilterObject ob in arrImportFilterObjects)
{
.
.
.
}
String result = Program.myPaletti.AuftragInDieDatenbankSchreiben(dbEintrag);
if (result.Equals("ok"))
{
sw.WriteLine(line + " §$%"); sw.Flush();
}
}
}
My problem is the writer is appending the line+"special mark" to the end of my file.
Additionally I didn't figure out how to read the file with UTF-8 coding.
I appreciate your answers !!
EDIT: ##############
This code would do the trick...
string[] lines = System.IO.File.ReadAllLines("test");
lines[0] = lines[0] + " $%&"; /* replace with whatever you need */
System.IO.File.WriteAllLines("test", lines);
But for my usage it's not recommended to read all lines, 'cause it's possible that the guys never delete any data for the next 20 years.
I'll go further to find a solution line by line...
There are some problems in your code that I will try to solve here
using(var stream = new FileStream(sFile, FileMode.Open, FileAccess.Read)
using(var reader = new StreamReader(stream, Encoding.UTF8))
{
long position = GetFirstNewRecordOfFile(sFile);
stream.Seek(position, SeekOrigin.Begin);
while(!reader.EndOfStream)
{
var line = reader.ReadLine();
// Process line
}
SaveFirstNewRecordOfFile(sFile, stream.Position);
}
Now you just need to figure out where and how to save the position of the file.
If you have a writer that appends data to the file the file might grow to a huge size over time, maybe it is better to truncate or delete the file when it has been read.
I recommend deleting the file since you will not have to loop through a lot of empty files, that will however require that you rename/move the file before processing it to avoid that the writer process appends data to it after you close it but before you delete it.
If you just move the file to a sub folder you can use that as a backup.
My solution now is to create a new file, write into this file, delete the original file and rename the new file.
foreach (string sFile in Directory.GetFiles(sImportPfad, "*.*", SearchOption.TopDirectoryOnly))
{
FileStream iStream;
try
{
using (iStream = new FileStream(sFile, FileMode.Open, FileAccess.Read, FileShare.None))
{
var sr = new System.IO.StreamReader(iStream, Encoding.UTF8);
if (rbCSVfilesMarkieren.Checked)
{
using (var oStream = new FileStream(sFile + "_new", FileMode.Create, FileAccess.Write, FileShare.None))
{
var sw = new System.IO.StreamWriter(oStream, Encoding.UTF8);
int c = 0;
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
String[] splitLine = line.Trim().Split(txtDivider.Text.Trim().ToCharArray());
if (line.Contains("$$$"))
{
sw.WriteLine(line);
sw.Flush();
continue;
}
String result = Program.myPaletti.Irgendwasneues(splitLine, arrImportFilterObjects);
if (result.Equals("ok"))
{
sw.WriteLine(line + "$$$");
sw.Flush();
anzNeueDatensätze++;
}
}
}
}
System.IO.File.Delete(sFile);
System.IO.File.Move(sFile + "_new", sFile);
}
}
}
I also included the UTF-8 coding.
Furthermore I've found a way to block the file I'm reading/writing, by using FileShare.None.
Thank you guys for your help !! I appreciate it !

C# StreamWriter writing over a current text file

I have a text file with the following text inside:
[username][0]
I have opened the file using StreamWriter and I want to change the 0 to a 1 using the StreamWriter.Write Method. How can I do this?
If you know the exact byte position of the character(s) you want to overwrite then you can do something like this:
using (var writer = new StreamWriter(filePath))
{
writer.BaseStream.Seek(bytePos, SeekOrigin.Begin);
writer.Write('1');
}
If you don't know the exact byte position then you could do something like this:
using (var file = new FileStream(filePath, FileMode.Open))
using (var reader = new StreamReader(file))
using (var writer = new StreamWriter(file))
{
var openBracketCount = 0;
// Keep reading characters until the second open bracket is found.
do
{
var ch = Convert.ToChar(reader.Read());
if (ch == '[')
{
openBracketCount++;
}
} while (openBracketCount < 2);
writer.Write('1');
}

using Stream CopyTo() without overwriting existing output file

How do I use the Stream CopyTo method without overwriting the existing output file?
public void MergeAndDeleteFiles(string outputFile, IEnumerable<string> inputFiles)
{
using (var output = File.OpenWrite(outputFile))
{
foreach (var inputFile in inputFiles)
{
using (var input = File.OpenRead(inputFile))
{
input.CopyTo(output);
}
}
}
}
The above method overwrites the outputFile for some reason? DO i need to set the position of the output file before using the CopyTo method?
Instead of OpenWrite use Open and pass in FileMode.Append:
using (var output = File.Open(outputFile, FileMode.Append))
This will append the output to the end of the file.
If you want to append data, then use something like this:
using (var output = new FileStream(outputFile, FileMode.Append, FileAccess.Write, FileShare.Write))
{
Or
using (var output = File.Open(outputFile, FileMode.Append))
{
as suggested by Oded.
Use StreamWriter to write into text files:
// create a writer and open the file
TextWriter tw = new StreamWriter("date.txt");
// write a line of text to the file
tw.WriteLine(DateTime.Now);
// close the stream
tw.Close();

Fetch files from folder

I have somes files in a folder. I want to fetch the files from that folder and convert each file to an object of binary stream and store in a collection. And from the collection, I want to retrieve each binary stream objects. How is it possible using ASP.Net with c# ?
It can be as simply as this:
using System;
using System.Collections.Generic;
using System.IO;
List<FileStream> files = new List<FileStream>();
foreach (string file in Directory.GetFiles("yourPath"))
{
files.Add(new FileStream(file, FileMode.Open, FileAccess.ReadWrite));
}
But overall, storing FileStreams like this does not sound like a good idea and does beg for trouble. Filehandles are a limited resource in any operating system, so hocking them is not very nice nore clever. You would be better off accessing the files as needed instead of simply keeping them open at a whim.
So basically storing only the paths and accessing the files as needed might be a better option.
using System;
using System.Collections.Generic;
using System.IO;
List<String> files = new List<String>();
foreach (string file in Directory.GetFiles("yourPath"))
{
files.Add(file);
}
If you wish to have it stored in a MemoryStream you could try
List<MemoryStream> list = new List<MemoryStream>();
string[] fileNames = Directory.GetFiles("Path");
for (int iFile = 0; iFile < fileNames.Length; iFile++)
{
using (FileStream fs = new FileStream(fileNames[iFile], FileMode.Open))
{
byte[] b = new byte[fs.Length];
fs.Read(b, 0, (int)fs.Length);
list.Add(new MemoryStream(b));
}
}
Or even use a Dictionary if you wish to keep the file names as keys
Dictionary<string, MemoryStream> files = new Dictionary<string, MemoryStream>();
string[] fileNames = Directory.GetFiles("Path");
for (int iFile = 0; iFile < fileNames.Length; iFile++)
{
using (FileStream fs = new FileStream(fileNames[iFile], FileMode.Open))
{
byte[] b = new byte[fs.Length];
fs.Read(b, 0, (int)fs.Length);
files.Add(Path.GetFileName(fileNames[iFile]), new MemoryStream(b));
}
}
This can be done using DirectoryInfo and FileInfo classes. Here is some code that should hopefully do what you need:
System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(#"C:\TempDir\");
if (dir.Exists)
{
foreach (System.IO.FileInfo fi in dir.GetFiles())
{
System.IO.StreamReader sr = new System.IO.StreamReader(fi.OpenRead());
// do what you will....
sr.Close();
}
}

Categories