I have here a piece of code for my class where I am entering values that are being written into a .txt and .bin file.
My problems are that my .txt file ends up being empty and my .bin file is not writing in binary.
I believe I have written and closed the .bin file and .txt correctly but my inputs are not being stored correctly
Here is my code
static void Main(string[] args)
{
string numberOfStudents, studentName, studentHeight, studentWeight;
int studentInput = 0, height;
bool numberOutput, heightOutput, weightOutput;
double weight;
Console.Write("Enter number of students: ");
numberOfStudents = Console.ReadLine();
numberOutput = int.TryParse(numberOfStudents, out studentInput);
if (numberOutput == true)
{
if (studentInput <= 0)
{
Console.WriteLine("Number of students must be a positive integer (greater than 0)!");
Console.ReadKey();
}
else
{
for (int i = 1; i <= studentInput; i++)
{
Console.Write("Enter student name: ");
studentName = Console.ReadLine();
Console.Write("Enter student height in centimetres: ");
studentHeight = Console.ReadLine();
heightOutput = int.TryParse(studentHeight, out height);
Console.Write("Enter student weight in kilograms: ");
studentWeight = Console.ReadLine();
weightOutput = double.TryParse(studentWeight, out weight);
try
{
StreamWriter outputFile;
outputFile = new StreamWriter("test.txt");
outputFile.Write(numberOfStudents + studentName + studentHeight + studentWeight);
outputFile.Close();
}
catch (System.IO.IOException exc)
{
Console.WriteLine("There was an error!: " + exc.Message);
}
try
{
FileStream outputFile = new FileStream("outFile.bin", FileMode.Create);
BinaryWriter BinFile = new BinaryWriter(outputFile);
BinFile.Write(studentName + " " + studentHeight + " " + studentWeight);
BinFile.Close();
}
catch (System.IO.IOException exc)
{
Console.WriteLine("There was an error!: " + exc.Message);
}
FileStream dataOutput = new FileStream("Database", FileMode.Create);
BinaryWriter databaseFile = new BinaryWriter(dataOutput);
StreamWriter textOutput = new StreamWriter("outText.txt");
databaseFile.Write(studentName + " " + studentHeight + " " + studentWeight);
databaseFile.Close();
textOutput.Close();
}
}
}
Thank you
You're almost there but there are a few issues with the code and it could be tidied up a little.
You are creating 3 files: outFile.bin, outText.txt, and test.txt. No data/text is written to outFile.txt, it is opened then closed a few lines later. Look in test.txt, it will have the last students data (see next point).
You are writing the files in a loop, which is overwriting the data, so only the last users data is being written to the file. Use outputFile = new StreamWriter("test.txt", true) this overload of StreamWriter will allow you to choose to append to the file (true) or overwrite (false).
I'd recommend looking at the using() statement when writing to file or any class that implements IDisposable. For example, when opening the StreamWriter you could do using (var outputFile = new StreamWriter("test.txt", true)) { }. This ensures the streamwriter is closed and disposed by the garbage collector, (For example, you are not closing the dataOutput file stream, if this was in a using(){} block it would automatically be handled for you)
This could be refactored into using just one try {} catch {} block, you do not need a separate try/catch for each time you write to a file.
From the Docs, the BinaryWriter class
Writes primitive types in binary to a stream and supports writing strings in a specific encoding.
So, the binary writer is writing in binary, but the data it's writing are strings. It could easily write int, double, bool, etc.
Here's the code in your try/catch blocks tidied up a bit (this only creates test.txt and outFile.bin):
try
{
// will open or create file in 'append' mode
using (var outputFile = new StreamWriter("test.txt", true))
{
outputFile.Write($"{numberOfStudents}, {studentName}, {studentHeight},{studentWeight}");
outputFile.Write(Environment.NewLine);
}
using (BinaryWriter databaseFile = new BinaryWriter(File.Open("outFile.bin", FileMode.Append)))
{
databaseFile.Write(studentName + " " + studentHeight + " " + studentWeight);
}
}
catch (System.IO.IOException exc)
{
Console.WriteLine("There was an error!: " + exc.Message);
}
Related
I'm doing a c# wcf service in which I receive a bunch of images and the service merge them in a multiimage Tiff file. At the end of the service I want to delete the original files but I'm receiving an error that some other process is locking the file.
This is the code that receives the images (as a byte[] list) and write them to disk
public static List<string> SaveByteImagesToFile(List<byte[]> bytesToCopyIntoFiles, string imageReferenceType, string imageReferenceValue)
{
_applicationLogger.Debug(MethodBase.GetCurrentMethod().DeclaringType.Name, MethodBase.GetCurrentMethod().Name);
string imageFinalPath = string.Empty;
string joinImagesFilePath = string.Empty;
List<string> imagesFilePath = new List<string>();
int count = 1;
try
{
if (bytesToCopyIntoFiles.Count == 0)
{
throw new ArgumentNullException("bytesToCopyIntoFiles");
}
else
{
joinImagesFilePath = SettingsManager.GetServiceSetting(AppSettingsKeys.CopyImagesToFilePath, "NO_VALID_FILEPATH");
if (joinImagesFilePath.IsValidFilePath(out string errorMessage, true, true))
{
foreach (byte[] image in bytesToCopyIntoFiles)
{
var imageFileName = imageReferenceType + "_" + imageReferenceValue + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + count.ToString();
imageFinalPath = joinImagesFilePath + Path.DirectorySeparatorChar + imageFileName + ".tiff";
using (FileStream stream = new FileStream(imageFinalPath, FileMode.Create, FileAccess.ReadWrite))
{
stream.Write(image, 0, image.Length);
stream.Flush();
}
imagesFilePath.Add(imageFinalPath);
count++;
}
}
else
{
exceptionMessageType = MainRepository.GetExceptionMessage("E171");
throw new IOException(exceptionMessageType.ExceptionMessage + " " + errorMessage);
}
}
return imagesFilePath;
}
catch
{
throw;
}
}
How or what can I use to prevent the service or any process to lock the file. As you can see I'm using the using scope for filestream without any luck.
Any ideas? Thanks
Resolved! By organizing the files in a certain order, when creating the multipage tiff, by the time the logic ends the worker already unlock the resources and I'm able now to delete them without any issue.
My method takes a List and creates a ZIP file and a log file. It works with smaller amounts of files. But when I go for a large amount of files (tested with 11,000) it throws a SystemOutOfMemory exception.
By research I learned that my method probably puts a lot of load in the memory. So I put in the part were I flush the streamwriter and the zip archive. I probably have to do something to the file stream.
What is an efficient approach to solve this problem?
Here is the code:
public static void BackupFilesToZip(string directory, string fileFilter, string zipFilePath, bool backupInSubDir, string logFilePath, List<FileInfo> filesToBackup)
{
FileInfo logFile = new FileInfo(logFilePath);
FileInfo zipFile = new FileInfo(zipFilePath);
int numberOfFiles = filesToBackup.Count;
if (!Directory.Exists(zipFile.DirectoryName)) Directory.CreateDirectory(zipFile.DirectoryName);
using (FileStream zipToOpen = new FileStream(zipFile.FullName, FileMode.OpenOrCreate))
{
using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
{
ZipArchiveEntry readmeEntry = archive.CreateEntry(logFile.Name);
using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
{
writer.WriteLine("This ZIP archive was created: " + DateTime.Now.ToString("MM/dd/yy HH:mm:ss"));
writer.WriteLine("ZIP File: " + zipFilePath);
writer.WriteLine("Source Directory: " + directory);
string backupInSubText = "yes";
if (!backupInSubDir) backupInSubText = "no";
writer.WriteLine("Subdirectories included: " + backupInSubText);
writer.WriteLine("Filter Critera: " + fileFilter);
writer.WriteLine("Number of Files selected: " + numberOfFiles + " (for # of files archived/skipped scroll down)");
writer.WriteLine("");
writer.WriteLine("File Log:");
int filesArchivedCounter = 0;
int filesSkippedCounter = 0;
int filesSum = 0;
TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.Normal);
foreach (FileInfo file in filesToBackup)
{
//ZipArchiveEntry readmeEntry = archive.CreateEntry(logFile.Name);
string DateTimeStampBegin = DateTime.Now.ToString("MM/dd/yy HH:mm:ss");
try
{
string relativePath = MakeRelativePath(directory, file.FullName);
archive.CreateEntryFromFile(file.FullName, relativePath);
writer.WriteLine(DateTimeStampBegin + " - " + DateTime.Now.ToString("HH:mm:ss") + " archived: " + file.FullName);
filesArchivedCounter++;
}
catch
{
writer.WriteLine(DateTimeStampBegin + " - " + " SKIPPED: " + file.FullName);
filesSkippedCounter++;
}
filesSum = filesSkippedCounter + filesArchivedCounter;
TaskbarManager.Instance.SetProgressValue(filesSum, numberOfFiles);
//write from memory to files every 75 items (to avoid out of memory exception)
if (filesSum % 75 == 0)
{
writer.Flush();
zipToOpen.Flush();
}
}
writer.WriteLine("");
writer.WriteLine("# of Files archived: " + filesArchivedCounter);
writer.WriteLine("# of Files skipped: " + filesSkippedCounter);
}
if (!String.IsNullOrEmpty(logFile.Name))
{
if (!Directory.Exists(logFile.DirectoryName)) Directory.CreateDirectory(logFile.DirectoryName);
readmeEntry.ExtractToFile(logFile.FullName, true);
}
TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.NoProgress);
}
}
}
All the string parameters of this method are just for the log file.
The problem in your implementation is that you are putting the log entry at the beginning of the archive and update it after adding new files, so zip cannot be flushed. You should write log to file, not the archive, and add it to the archive when all files are added.
Using Seek Method to read a specific part of a text but it fails.
I have two classes "allmethods.cs" and "caller.cs"
There are two methods in "allmethods.cs" which are "WritingMethod" and "SeekReader"
The program should writes in a text file and read data using seek method in order to read certain part in the text file.
The programs writes smoothly in the text file but it doesn't read anything when calling "SeekReader" which is the seek method.
My Code:
public class allmethods
{
private static string Name;
private static int ID;
private static int Age;
private static string Email;
private static string output;
public static void WritingMethod()
{
int count = 0;
while (count < 10)
{
Console.Write(" Enter your Name: ");
Name = Console.ReadLine();
Console.Write(" Enter your ID: ");
ID = int.Parse(Console.ReadLine());
Console.Write(" Enter your Age: ");
Age = int.Parse(Console.ReadLine());
Console.Write(" Enter your E-mail: ");
Email = Console.ReadLine();
StreamWriter Sw = new StreamWriter("fileone.txt", true);
string output = string.Format("Thank you for registration! Your Submitted information are:" + Environment.NewLine + "Name: {0}"
+ Environment.NewLine + "ID: {1}" + Environment.NewLine + "Age: {2}" + Environment.NewLine + "E-mail: {3}", Name, ID, Age, Email);
Console.WriteLine(output);
Sw.WriteLine(output + Environment.NewLine);
Console.ReadLine();
Sw.Close();
count++;
}
}
public static void SeekReader()
{
FileStream FS=new FileStream("fileone.txt",FileMode.Open,FileAccess.Read);
StreamReader SR = new StreamReader(FS);
SR.BaseStream.Seek(2, SeekOrigin.Begin);
FS.Close();
SR.Close();
}
}
I failed to identify the error. Any suggestions?
Thanks in Advance.
You can use File.ReadAllText([FilePah]) to read the file.
public static void SeekReader()
{
FileStream fsr = new FileStream("fileone.txt", FileMode.Open, FileAccess.Read);
StreamReader Sr = new StreamReader(fsr);
string line = string.Empty;
var ctr = 0;
while(ctr < 3){
line = Sr.ReadLine();
ctr++;
}
Console.WriteLine(line);
Sr.Close();
fsr.Close();
}
I'm trying to read from a binary file with BinaryReader.
This is how I call my reading method :
foreach (Movie film in TreeBuilder.myMovies)
{
if (File.Exists(#"C:\Users\DaPhunk\Documents\Visual Studio 2010\Projects\YLK\Binary\" + film.MovieName + ".txt"))
{
string[] myArray = operationManager.BinaryReading(film.MovieName);
if (myArray != null)
{
this.textStarring.Text = myArray[1];
this.textProduced.Text = myArray[2];
this.textMusic.Text = myArray[3];
this.textYear.Text = myArray[4];
this.textTime.Text = myArray[5];
}
else
{
MessageBox.Show("An error occured");
}
}
This is my reading method :
public string[] BinaryReading(string name)
{
FileStream myStream = new FileStream(#"C:\Users\DaPhunk\Documents\Visual Studio 2010\Projects\YLK\Binary\" + name + ".txt", FileMode.Open);
BinaryReader reader = new BinaryReader(myStream);
string loadString = reader.ReadString();
string[] loadArray = loadString.Split(',');
reader.Close();
myStream.Close();
return loadArray;
}
Now something within these lines is not working. My file is not empty because since it's only a string I can read whats in the file.
My problem is I'm trying to find whats wrong with a break point but as soon as I get past this line :
string loadString = reader.ReadString();
My program starts to run again. How is that possible ? This prevents me from checking what's inside my String[] and what are my values after the method call.
Any idea why ? Thanks in advance.
Update :
I tried to move my breakpoint here
string[] loadArray = loadString.Split(',');
But my program never stops so it never gets past the previous line.
Also this is my Writting method :
foreach (Movie film in TreeBuilder.myMovies)
{
if (film.MovieName == name)
{
FileStream myStream = new FileStream(#"C:\Users\DaPhunk\Documents\Visual Studio 2010\Projects\YLK\Binary\" + film.MovieName + ".txt", FileMode.Create);
BinaryWriter writer = new BinaryWriter(myStream);
writer.Write(film.MovieName + "," + starring + "," + produced + "," + music + "," + year + "," + lenght);
writer.Close();
myStream.Close();
}
}
Your string will be prefixed with a length field. That makes the .txt extension misleading.
Since it 'suddenly started working again' : is it possible you opened (and saved) one of the files with a Text editor?
Also, your current Read and Write methods are not thread-safe, you should enclose the Stream and Reader/Writer objects in using() {} statements.
I am writing a program to function as a testing plugin with a third party program. I have talked with the developer on the other end (don't get me started) and he is using VB 6 to create a batch file and then calls the batch file using a shell command. His batch file is calling my plugin which I have written to output data to a file based on the parameters that I receive via his batch file.
My problem is that when his program calls the batch file via a shell command (again, he is using VB 6), my program executes and the console writelines that I put in place in front of and after the filestream stuff all execute, but the files are not created and therefore his program does not read the file I create (CP07.txt in this case). If I manually run the batch file from Windows explorer everything works as expected. I do have a process monitor capture if that is beneficial. The program is running as the local admin on a Win7 machine (although it is not elevated), UAC is disabled, there is no anti-virus software installed, and it is not writing to a root or system folder.
I appreciate any pointers. Since the ProcMon capture is long (1400+ lines), I have not posted it.
Regards,
S
Here is a sample batchfile from the other program...
Full path to my exe
Full path to the output file
Parameter for my use
Username
Password
C:\SpecifiedDir\myprogram.exe C:\Specified\Directory\CP07.txt parameter username password
I am overwriting the output file parameter as you can see because it did not work initially the other way (I think maybe something to do with the slashes being escaped or something) and I wanted to start with a simple and working program and then clean it up from there.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Plugin
{
class Program
{
static void Main(string[] args)
{
Console.Write("Press any key to begin: ");
Console.Write("Starting...", Console.ReadLine());
//Console.WriteLine("Done");
Console.WriteLine("Number of command line parameters = {0}",args.Length);
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
}
Console.WriteLine("");
TextWriter defaultOutputMethod = Console.Out;
TextWriter defaultErrorOutputMethod = Console.Error;
FileStream fStream;
StreamWriter strWriter;
FileStream fErrorStream;
StreamWriter strErrorWriter;
try
{
fStream = new FileStream("./Redirect.txt", FileMode.OpenOrCreate, FileAccess.Write);
strWriter = new StreamWriter(fStream);
}
catch (Exception e)
{
Console.WriteLine("Cannot open Redirect.txt for writing");
Console.WriteLine(e.Message);
return;
}
try
{
fErrorStream = new FileStream("./RedirectError.txt", FileMode.OpenOrCreate, FileAccess.Write);
strErrorWriter = new StreamWriter(fErrorStream);
}
catch (Exception e)
{
Console.WriteLine("Cannot open RedirectError.txt for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(strWriter);
Console.SetError(strErrorWriter);
Console.WriteLine("Number of command line parameters = {0}", args.Length);
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
}
// Store parameters into variables for reference
string pSuccess = "OK";
string pFail = "FAIL";
string pOutputFile = args[0];
string pLookupType = args[1];
string pUserName = args[2];
string pPassword = args[3];
Console.SetOut(defaultOutputMethod);
// Console.SetError(defaultErrorOutputMethod);
strWriter.Close();
fStream.Close();
// Setup Commnet filestream and stream writer, and assign output to stream if file successfully created
FileStream fCommnetStream;
StreamWriter strCommnetWriter;
string sCommnetOutputFile = #"./CP07.txt";
try
{
fCommnetStream = new FileStream(sCommnetOutputFile, FileMode.OpenOrCreate, FileAccess.Write);
strCommnetWriter = new StreamWriter(fCommnetStream);
}
catch (Exception e)
{
Console.WriteLine("Cannot open " + sCommnetOutputFile + " for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(strCommnetWriter);
// Test Variables to determine output: Success or Failure
string sSuccessPass = "1111";
string sFailPass = "0000";
if (pPassword == sSuccessPass)
{
Console.WriteLine(pSuccess);
}
else if (pPassword == sFailPass)
{
Console.WriteLine(pFail);
}
else
{
Console.WriteLine("OTHER");
}
Console.WriteLine("Output File: <" + pOutputFile + ">");
Console.WriteLine("Lookup Type: <" + pLookupType + ">");
Console.WriteLine("User Name: <" + pUserName + ">");
Console.WriteLine("User Pass: <" + pPassword + ">");
Console.SetOut(defaultOutputMethod);
Console.SetError(defaultErrorOutputMethod);
strCommnetWriter.Close();
fCommnetStream.Close();
strErrorWriter.Close();
fErrorStream.Close();
Console.Write("Press any key to finish: ");
Console.Write("Ending...", Console.ReadLine());
//Console.WriteLine("Done");
}
}
}
I guess the problem is that you are writing into the "current directory", which can be anything when your program is started by a batch file, which itself has been started by another application. It is not impossible that your files are written into the directory where the batch file resides :)