I am creating a program which takes passwords and applies an encoding on them onto a file which I have creatively labeled a PASSWORDFILE file. I am a self taught amateur programmer and this is my first time using streams => I'm sorry my code isn't cleaner. When I add a password to my file, the file refuses to open (giving me a "System.IO.IOException: The process cannot access the file '[file path here]' because it is being used by another process."). I have made sure I am closing all my streams yet this error still persists.
To add further confusion:
namespace PasswordSaver
{
[Serializable]
class Password
{
public string ID;
string baseWord;
public Password(string password, string ID)
{
this.ID = ID;
baseWord = password;
}
public virtual string GetPassword()
{
return baseWord;
}
}
[Serializable]
class EncodedPassword : Password
{
EncoderAndDecoder Encoder;
public EncodedPassword(string decodedBasePassword, string ID) : base(decodedBasePassword, ID)
{
Encoder = new EncoderAndDecoder();
}
public override string GetPassword()
{
return Encoder.Encode(base.GetPassword(), out _);
}
}
[Serializable]
class EncodedPasswordWithAddendum : EncodedPassword
{
string addendum;
public EncodedPasswordWithAddendum(string decodedBasePassword, string addendum, string ID) : base(decodedBasePassword, ID)
{
this.addendum = addendum;
}
public override string GetPassword()
{
return base.GetPassword() + addendum;
}
}
}
the error only occurs when I attempt to add an EncodedPassword or EncodedPasswordWithAddendum instances but not a Password instance.
My writing code is
namespace PasswordSaver
{
class PasswordWriter
{
public readonly string saveFilePath;
static string directory = Directory.GetCurrentDirectory();
#region Constructors
public PasswordWriter()
{
saveFilePath = directory + #"\PasswordSaver"
+ ".passwordfile";
}
public PasswordWriter(string saveFilePath)
{
this.saveFilePath = saveFilePath;
}
#endregion
#region Individual Writing Functions
private void WriteBinary(object objectToEncode)
{
WriteBinary(objectToEncode, out _);
}
private void WriteBinary(object objectToEncode, out Exception exception)
{
exception = null;
try
{
IFormatter binaryFormatter = new BinaryFormatter();
Stream fileStream = new FileStream(saveFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
Stream memoryStream = new MemoryStream();
memoryStream.Position = memoryStream.Length;
binaryFormatter.Serialize(memoryStream, objectToEncode);
EncodeFromStream(ref memoryStream, ref fileStream);
fileStream.Close();
memoryStream.Close();
}
catch (Exception e)
{
exception = e;
}
}
#endregion
#region File Read and Writing
public void WriteFile(Password[] passwords)
{
if (File.Exists(saveFilePath))
{
Stream stream = new FileStream(saveFilePath, FileMode.Truncate, FileAccess.Write);
stream.Close();
}
WriteBinary(passwords.Length);
foreach (Password password in passwords)
{
WriteBinary(password);
}
}
public void WriteToFile(Password password)
{
Password[] oldPasswords = ReadFile();
Password[] passwords = new Password[oldPasswords.Length + 1];
for (int i = 0; i < oldPasswords.Length; i++)
{
passwords[i] = oldPasswords[i];
}
passwords[oldPasswords.Length] = password;
WriteFile(passwords);
}
public bool ReplacePassword(string oldPasswordID, Password newPassword)
{
Password[] passwords = ReadFile();
for (int i = 0; i < passwords.Length; i++)
{
if (passwords[i].ID == oldPasswordID)
{
passwords[i] = newPassword;
return true;
}
}
return false;
}
public Password[] ReadFile()
{
Stream fileStream = new FileStream(saveFilePath, FileMode.OpenOrCreate, FileAccess.Read);
IFormatter binaryFormatter = new BinaryFormatter();
Stream memoryStream = new MemoryStream();
DecodeFromStream(ref fileStream, ref memoryStream);
fileStream.Close();
memoryStream.Position = 0;
int length = (int) binaryFormatter.Deserialize(memoryStream);
//Console.WriteLine(length + " is the length");//debug
Password[] passwords = new Password[length];
for (int i = 0; i < length; i++)
{
//Console.WriteLine(memoryStream.Position + " " + memoryStream.Length);//debug
//Console.WriteLine(i);//debug
passwords[i] = (Password)binaryFormatter.Deserialize(memoryStream);
}
memoryStream.Close();
return passwords;
}
#endregion
#region Encode and Decode
private void EncodeFromStream(ref Stream stream, ref Stream newStream)
{
stream.Position = 0;
newStream.Position = newStream.Length;
for (int i = 0; i < stream.Length; i++)
{
int integer = stream.ReadByte();
byte originalByte = (byte)integer;// get a byte off of the line
//Encode byte here
newStream.WriteByte(setOfBits1);
newStream.WriteByte(setOfBits2);
}
}
private void DecodeFromStream(ref Stream stream, ref Stream newStream)
{
newStream.Position = newStream.Length;
stream.Position = 0;
for (int i = 0; i < (stream.Length / 2); i++)// stream.Length / 2 because the program reads two bytes per iteration of the for loop
{
//I decode the bytes here
newStream.WriteByte(originalByte);
}
}
#endregion
public void WriteContentsToFile()
{
Stream stream = new FileStream(saveFilePath + "1", FileMode.OpenOrCreate, FileAccess.ReadWrite);
Stream stream1 = new FileStream(saveFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
this.DecodeFromStream(ref stream1, ref stream);
stream.Close();
stream1.Close();
}
}
}
I have removed the code that encoded and decoded the streams in EncodeFromStream and DecodeFromStream.
any occurrence of new FileStream(saveFilePath + "1", FileMode.OpenOrCreate, FileAccess.ReadWrite) is a where I was writing to a seperate file in a decoded format. To distinguish the two files I changed the file type from PASSWORDFILE to PASSWORDFILE1.
In Conclusion:
I am using the WriteFile or WriteToFile methods with a Password[] that contains an EncodedPassword or EncodedPasswordWithAddendum. then when I try to open the file through a FileStream (usually through the method ReadFile) I get the Exception "System.IO.IOException: The process cannot access the file '[file path here]' because it is being used by another process".
Thank you for your help.
Streams usually contain unamanged resources (the OS Filehandles), so they implement IDisposeable.
While you can always be certain that the GC will clean up disposeable stuff eventually (latest at application closing), usually that is way to late. You have to do it explicitly. And for that I have a one rule regarding IDisposeable stuff:
"Never split up the creation and disposing of a disposeable resource. Create. Use. Dispose. All in the same piece of code, ideally using a using block."
The only exception I ever encountered a logfiles. Nothing else is remotely worth the trouble and headaches of keeping something disposeable open. Especially not performance.
As the using block uses a try...finally, you can be certain it will run. Compiler and runtime make certain finally blocks always run, even on function return, jump via goto or Exception cases.
Related
I need to pass a stream to a couple of functions in another class, but its throwing an error
Cannot access a closed stream
Here's the code:
first method:
Here it opens a file with File.Open method and then creates a memorystream object and it copies FileStream to MemoryStream. then sets Position to 0 (i set position to 0, because i was that in a solution, but not helping tho). Then it creates an object of class DocxConvert and call the Converto method by passing MemoryStream to it.
using (var stream = File.Open(tempPath2, FileMode.Open))
{
using(var ms = new MemoryStream())
{
stream.CopyTo(ms);
ms.Position = 0;
using (var docx = new DocxConvert())
{
return docx.Converto(ms);
}
}
}
DocxConvert Class:
It takes stream and then calls copyStream method by passing the accepted stream.
copyStream method in DocxConvert Class: it should copy the accepted stream to another stream called _memoryStream which is a class property.
public class DocxConvert
{
private MemoryStream _memoryStream = new MemoryStream();
public bool Converto(Stream stream)
{
try
{
copyStream(stream);
//more code
}
catch (IOException ex)
{
Debug.WriteLine(ex);
}
return true;
}
private void copyStream(Stream stream)
{
stream.CopyTo(_memoryStream); //here it throws the error
}
}
p.s. I search for this error here before posting, but non of the topics helped me.
SOLVED by restarting PC, the code it ok.
I am not aware about your question .But here in the code bellow no excepion
private void button1_Click(object sender, EventArgs e)
{
string tempPath2 = Application.StartupPath + "//" + "test.txt";
using (var stream = File.Open(tempPath2, FileMode.Open))
{
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
ms.Position = 0;
var docx = new DocxConvert();
var isok = docx.Converto(ms);
}
}
}
The bellow is the calss defined where _memorystream is defined at top
MemoryStream _memoryStream = new MemoryStream();
public bool Converto(Stream stream)
{
try
{
copyStream(stream);
//more code
}
catch (IOException ex)
{
// Debug.WriteLine(ex);
}
return true;
}
private void copyStream(Stream stream)
{
try
{
stream.CopyTo(_memoryStream);
}
catch (Exception)
{
}
}
I am trying to write some json text. But I get an Exception like
The process cannot access the file C:\blah blah\SystemInActivity.json because it is being used by an other process. But then second time when I run the app after json file is created and then when I write I dont get an exception. Please help.
class ApplicationSettingsViewModel
{
ApplicationSettingsModel model;
MemoryMappedFile mmf = null;
public string FullPath = string.Empty;
//This is not a singleton class but I guess it has to be one but its ok for demonstration.
public ApplicationSettingsViewModel()
{
model = new ApplicationSettingsModel();
CreateFileWithoutMemoryMap();
//MemoryMapped();
}
public string GetDriectory()
{
return Path.GetDirectoryName(FullPath);
}
private void CreateFileWithoutMemoryMap()
{
var info = Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "/" + model.Data.Settings.OrcaUISpecificSettings.TimeOutFolder);
string path = Path.Combine(info.FullName + #"\" + model.Data.Settings.OrcaUISpecificSettings.File);
//mmf = MemoryMappedFile.CreateFromFile(path, FileMode.CreateNew, "MyMemoryFile", 1024 * 1024, MemoryMappedFileAccess.ReadWrite);
FullPath = path;
if (!File.Exists(path))
{
File.Create(path);
}
}
public void WriteToFile(string json)
{
try
{
FileStream fileStream = File.Open(FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); //This line giving Exception
fileStream.SetLength(0);
fileStream.Close(); // This flushes the content, too.
using (StreamWriter sw = new StreamWriter(FullPath))
{
sw.Write(json);
}
}
catch (Exception ex)
{
}
}
In the constructor of the MainWindow I am calling the write method
private ApplicationSettingsViewModel AppViewModel;
public MainWindow()
{
InitializeComponent();
//MessageBox.Show("App Started");
AppViewModel = new ApplicationSettingsViewModel();
WriteToFile("Active");
}
public void WriteToFile(string status)
{
var root = new Root();
string jsonString = string.Empty;
root.AllApplications.Add(new DataToWrite() { AppName = "DevOrca", Status = status });
try
{
jsonString = JsonConvert.SerializeObject(root, Formatting.Indented);
}
catch (Exception ex)
{
MessageBox.Show(jsonString);
MessageBox.Show("Exception");
}
mutex.WaitOne();
//Serialize Contents and write
AppViewModel.WriteToFile(jsonString);
//var access = AppViewModel.GetAccessor();
//byte[] bytes = Encoding.ASCII.GetBytes(jsonString);
//access.Write(bytes, 0, bytes.Length);
mutex.ReleaseMutex();
}
File.Create() method opens FileStream to create a file and you need to close it, something like this:
File.Create(path).Close();
I'm trying to make betting program in C#, storing the user's data in a txt file. I have no problem reading the data from it. However, I can't manage to overwrite it.
From what I've tested, if I call the StreamWriter part alone the overwriting happens just fine. When I put the same code after the StreamReader part, the code will reach the Console.WriteLine("reached"); line and ignore everything after it (username is never written in the console). No error is detected and compilation won't stop either.
Here's the class code:
class Dinero
{
private List<string> data;
private string path = #"C:\Users\yy\Documents\Visual Studio 2015\Projects\ErikaBot\ErikaBot\img\bank_data.txt";
...
some other methods here
...
public void thing(string username, int money)
{
FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
data = new List<string>();
using (StreamReader sr = new StreamReader(fs))
{
string a = sr.ReadLine();
for (int i = 0; a != null; i++)
{
if (a != username)
{
data.Add(a);
}
else i++;
a = sr.ReadLine();
}
}
string b = Convert.ToString(money);
Console.WriteLine("reached");
using (StreamWriter tw = new StreamWriter(fs))
{
Console.WriteLine(username);
if (data != null)
{
for (int i = 0; i < data.Count; i++)
{
tw.WriteLine(data.ElementAt(i));
}
}
string money2 = Convert.ToString(money);
tw.WriteLine(username);
tw.WriteLine(money2);
}
}
}
By disposing StreamReader you also dispose the FileStream.
Either repeat the filestream initialisation before the using statement for StreamWriter or put the latter in the using statement for StreamReader.
I wrote one app using C# to read data from a serial port and show the data on a textbox in hex string format. Finally, I saved all data to a binary file. If data is big (maybe > 20mb) it throws an out of memory error. How can I solve this? Here is my code:
private void btn_Save_Click(object sender, EventArgs e)
{
SaveFileDialog save_log = new SaveFileDialog();
save_log.DefaultExt = ".bin";
save_log.Filter = "Binary File (*.bin)|*.bin";
// Determine if the user selected a file name from the saveFileDialog.
if (save_log.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
save_log.FileName.Length > 0)
{
try
{
string hexString = Content.Text.ToString();
FileStream stream = new FileStream(save_log.FileName, FileMode.Create, FileAccess.ReadWrite);
stream.Write(Hex_to_ByteArray(hexString), 0, Hex_to_ByteArray(hexString).Length);
stream.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private byte[] Hex_to_ByteArray(string s)
{
s = s.Replace(" ", "");
byte[] buffer = new byte[s.Length / 2];
for (int i = 0; i < s.Length; i += 2)
{
buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
}
return buffer;
}
You're creating the byte array twice. Also, the .Replace over such a long string doesn't help. You can avoid all this:
try
{
var stream = new FileStream(
save_log.FileName,
FileMode.Create,
FileAccess.ReadWrite);
WriteHexStringToFile(Content.Text, stream);
stream.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
private void WriteHexStringToFile(string hexString, FileStream stream)
{
var twoCharacterBuffer = new StringBuilder();
var oneByte = new byte[1];
foreach (var character in hexString.Where(c => c != ' '))
{
twoCharacterBuffer.Append(character);
if (twoCharacterBuffer.Length == 2)
{
oneByte[0] = (byte)Convert.ToByte(twoCharacterBuffer.ToString(), 16);
stream.Write(oneByte, 0, 1);
twoCharacterBuffer.Clear();
}
}
}
Also, take a look at Encoding and/or BinaryFormatter which might do all of this for you.
Update:
First of all, please note that your whole idea of storing megabytes of data in a string is a nonsense, and you shouldn't do that. You should process your data in smaller parts. Because of this nonsense I'm unable to provide you with a working demo (on IDEONE for example), because of resource limitations of online compilers. I've tested the code on my machine, and as you can see I can even process 50 MB strings - but it all depends on the amount of memory you have available. If you do such things, then on every machine it will be easy to reach the limit of available memory. And the methods you ask about in this particular question are irrelevant - the problem is because you fill your memory with tons of data in your Content.Text string. When memory is almost full, the OutOfMemoryException can occur at almost any place in your code.
You can view the whole picture in your browser to see all the details.
Use IEnumerable. That will avoid the large byte array.
I don't know what is in Content.Text. If it's a byte array, maybe you can change
static internal IEnumerable<byte>Hex_to_Byte(string s)
into
static internal IEnumerable<byte>Hex_to_Byte(byte[] bytes)
and modify the code a bit
FileStream stream = new FileStream(save_log.FileName, FileMode.Create, FileAccess.ReadWrite);
foreach( byte b in Hex_to_Byte(hexString) )
stream.WriteByte(b);
stream.Close();
static internal IEnumerable<byte>Hex_to_Byte(string s)
{
bool haveFirstByte = false;
int firstByteValue = 0;
foreach( char c in s)
{
if( char.IsWhiteSpace(c))
continue;
if( !haveFirstByte)
{
haveFirstByte = true;
firstByteValue = GetHexValue(c) << 4;
}
else
{
haveFirstByte = false;
yield return unchecked((byte)(firstByteValue + GetHexValue(c)));
}
}
}
static string hexChars = "0123456789ABCDEF";
static int GetHexValue(char c)
{
int v = hexChars.IndexOf(char.ToUpper(c));
if (v < 0)
throw new ArgumentOutOfRangeException("c", string.Format("not a hex char: {0}"));
return v;
}
I need to read csv file twice. but after first reading:
using (var csvReader = new StreamReader(file.InputStream))
{
fileFullText += csvReader.ReadToEnd();
file.InputStream.Seek(0, SeekOrigin.Begin);
csvReader.Close();
}
using file in enother function:
public static List<string> ParceCsv(HttpPostedFileBase file)
{
//file.InputStream.Seek(0, SeekOrigin.Begin);
using (var csvReader = new StreamReader(file.InputStream))
{
// csvReader.DiscardBufferedData();
// csvReader.BaseStream.Seek(0, SeekOrigin.Begin);
string inputLine = "";
var values = new List<string>();
while ((inputLine = csvReader.ReadLine()) != null)
{
values.Add(inputLine.Trim().Replace(",", "").Replace(" ", ""));
}
csvReader.Close();
return values;
}
}
The file.Length is 0.
Can anybody help?
The reason is that SteramReader's Dispose() method also closes the underlying stream; In your case file.InputStream. The using statement calls Dispose() implicitly. Try to replace using with disposes of both your StreamReaded-s after you finished both read operations. As I remember some stream classes have a bool option to leave underlying stream open after dispose.
.NET 4.5 fixed this issue by introducing leaveOpen parameter in SteamReader constructor. See: MSDN
public StreamReader(
Stream stream,
Encoding encoding,
bool detectEncodingFromByteOrderMarks,
int bufferSize,
bool leaveOpen
)
One more thing. You do not need to close SteramReader yourself (the line with csvReader.Close();) when you wrap it in using statement, thus Dispose() and Close() are the same in case of StreamReader.
if your using HttpPostedFileBase you need to clone it first,
use the code this git here
or just add this as a class in your namespace:
public static class HttpPostedFileBaseExtensions
{
public static Byte[] ToByteArray(this HttpPostedFileBase value)
{
if (value == null)
return null;
var array = new Byte[value.ContentLength];
value.InputStream.Position = 0;
value.InputStream.Read(array, 0, value.ContentLength);
return array;
}
}
now you can read the HttpPostedFileBase like so:
private static void doSomeStuff(HttpPostedFileBase file)
{
try
{
using (var reader = new MemoryStream(file.ToByteArray()))
{
// do some stuff... say read it to xml
using (var xmlTextReader = new XmlTextReader(reader))
{
}
}
}
catch (Exception ex)
{
throw ex;
}
}
after using this you can still write in your main code:
file.SaveAs(path);
and it will save it to the file.