I'm learning c# console. If we allow user to type file size between 1000 and 25000, how to do this? i wrote following codes but when user typed 1000 bytes, program not stop and txt file bytes go above 1000 bytes.(eg 27000).
// user type file location C://files/files.txt
string randomword; // getting random words
int index;
try
{
Console.WriteLine("Please enter pathname of the file: ");
string pathOfFile = Console.ReadLine();
FileInfo fi = new FileInfo(pathOfFile);
long size = fi.Length;
if (fi.Exists)
{
// Get file size
Console.WriteLine("File Size in Bytes: {0}", size);
Console.WriteLine("Please enter the size of the file (min: 500 / max: 2500 : ");
long fileOfSize = int.Parse(Console.ReadLine());
if (size > fileOfSize)
{
Environment.Exit(0);
}
else
{
for (index = 1; index <= fileOfSize; index )
{
randomword= gettingRandomWord() Environment.NewLine;
File.AppendAllText(pathOfFile, randomword);
}
}
}
}
catch (Exception ex)
{
}
CodePudding user response:
By default, the file is in UTF-8, so a single character can consist of more than one byte written to the file. You are adding together the results of gettingRandomWord()
and Environment.NewLine
into a new string and appending it to the file. This will always be more than one byte on Windows where Environment.NewLine
by itself is two bytes. You are incrementing the index by only one byte each time through the loop.
You would need to get the number of bytes that will be written to the file, and increment the index by that amount each loop iteration. To get the number of bytes that will be added:
var byteCountToBeWritten = System.Text.Encoding.UTF8.GetByteCount(randomword);
As a hint, the last part of the for
expression is optional, so you can increment i
inside the loop. If you don't want to go over the byte count at all, you will need a different stragegy.
CodePudding user response:
I guess an easy way to measure how much has been appended to the file is to use Streams and calculate what has been written.
There are many ways to do this, however I have chosen to use UTF8.GetByteCount
and flush the stream so get the actual count before writing, you can add pepper and salt to taste.
Disclaimer : This example uses C# 7/8 language features. You will need to convert them if you are stuck in the 2010's
try
{
string pathOfFile;
while (true)
{
Console.WriteLine("Please enter pathname of the file: ");
pathOfFile = Console.ReadLine();
if (File.Exists(pathOfFile))
break;
Console.WriteLine($"The file does not exist : {pathOfFile}");
}
var fileInfo = new FileInfo(pathOfFile);
var size = fileInfo.Length;
Console.WriteLine("File Size in Bytes: {0}", size);
if (size > 2500)
{
Console.WriteLine($"Game over. The File is already greater than {2500}b.");
return;
}
int inputSize;
Console.Write("Please enter the size of the file (min: 500 / max: 2500) : ");
while(int.TryParse(Console.ReadLine(), out inputSize) && inputSize is < 500 or > 2500 )
Console.Write("Out of range (min: 500 / max: 2500 : ");
if (size > inputSize)
{
Console.WriteLine($"Game Over. The file is already greater than {inputSize}b. The actual size is {size}b");
return;
}
using var sw = new StreamWriter(new FileStream(pathOfFile, FileMode.Append));
while (sw.BaseStream.Length < inputSize)
{
var randomWord = gettingRandomWord();
var count = Encoding.UTF8.GetByteCount(randomWord Environment.NewLine);
if (sw.BaseStream.Length count > inputSize)
break;
sw.WriteLine(randomWord);
sw.Flush(); // make sure the stream is flushed so we no its exact size
}
Console.WriteLine($"Game over. The file is now {sw.BaseStream.Length}b");
}
catch (Exception ex)
{
// never swallow exceptions
Console.WriteLine($"The application caused an exception : {ex}");
}
Test Output
Please enter pathname of the file:
D:\test.txt
File Size in Bytes: 8
Please enter the size of the file (min: 500 / max: 2500) : 600
Game over. The file is now 591b
Note : I have tidied up your code and made it a little more fault tolerant. However, this was not meant to be the bastion of awesome coding.