IsolatedStorage in Window Phone 7.5 - c#

I am working with IsolatedStorage in Windows Phone 7.5. I am trying to read some text from a file. But the debugger says the operation is not permitted on IsolatedStorageFileStream. Why?
//Read the file from the specified location.
fileReader = new StreamReader(new IsolatedStorageFileStream("info.dat", FileMode.Open, fileStorage));
//Read the contents of the file (the only line we created).
string textFile = fileReader.ReadLine();
//Write the contents of the file to the MEssageBlock on the page.
MessageBox.Show(textFile);
fileReader.Close();
UPD my new code
object _syncObject = new object();
lock (_syncObject)
{
using (var fileStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (FileStream stream = new FileStream("/info.dat", FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (var reader = new StreamReader(stream))
{
string textFile = reader.ReadLine();
MessageBox.Show(textFile);
}
}
}
}
}

Try this, it works for me: Hope it works for you too
String sb;
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(fileName))
{
StreamReader reader = new StreamReader(new IsolatedStorageFileStream(fileName, FileMode.Open, myIsolatedStorage));
sb = reader.ReadToEnd();
reader.Close();
}
if(!String.IsNullOrEmpty(sb))
{
MessageBox.Show(sb);
}
}
If this doesn't work, then maybe your file doesn't exist.

Normally when I've used isolated storage, I've done something like:
using (var stream = fileStorage.OpenFile("info.dat", FileMode.Open))
{
using (var reader = new StreamReader(stream))
{
...
}
}
... rather than calling the constructor directly on IsolatedStorageFileStream. I can't say for sure whether that'll sort it out, but it's worth a try...

Just a guess:
WP emulator will reset all Isolatd Storage contents when it's closed
if you used FileMode.Open with a path to a non existing file you'll get Operation not permited exception.
You can use fileStorage.FileExists() to check if the file is there or use FileMode.OpenOrCreate.

Related

Modify a file content in C# using the Stream's API

I have a .json file who handles the user's roles and I have wrote a Repository who's responsible of adding/removing roles to users. The pb is that when I modify the file I want to be sure that no one access it except me.
Here's (roughly) the code I use:
using (var fileStream = new FileStream(_rolesFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
using (var streamReader = new StreamReader(fileStream))
using (var streamWriter = new StreamWriter(fileStream))
{
var oldContent = streamReader.ReadToEnd();
var contentObject = Deserialize(oldContent);
Modify(contentObject)
var newContent = Serialize(contentObject);
fileStream.Seek(0, SeekOrigin.Begin);
streamWriter.Write(newContent);
}
The pb with this solution is that if newContent is a string shorter that oldContent some characters will be remaining in the file.
A solution I found is to add the following code:
using (var fileStream = new FileStream(_rolesFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
using (var streamReader = new StreamReader(fileStream))
using (var streamWriter = new StreamWriter(fileStream))
{
//...
var newContent = Serialize(contentObject);
var endPosition = fileStream.Position;
fileStream.Seek(0, SeekOrigin.Begin);
streamWriter.Write(newContent);
streamWriter.Flush();
while (fileStream.Position < endPosition)
{
streamWriter.WriteLine();
streamWriter.Flush();
}
}
It works well but does not look very clean to me. Are there any better solution who ensure that I keep the control of the file ?
Thanks in advance,
Thomas
You can do fileStream.SetLength(fileStream.Position) to truncate the remaining part of the file. This assumes that the FileStream is left correctly positioned by the StreamWriter after use, but that's an assumption your current code seems to be making too.
(This is a safer assumption than the corresponding usage of StreamReader where internal buffering may mean that the underlying stream's position is further advanced than the latest data returned by a call to a Read method)

C# Bitmap Invalid Parameter

Here is what I am trying to do: Take a folder full of images, perform an optimization on them, and store them in the same file.
I get the error:
System.ArgumentException
Message = Parameter is not valid.
From line:
using (var bitmap = new Bitmap(image))
I think this has something to do with the file being open, and blocking access but I'm not sure. I know for a fact that the filepath I'm using is correct, and that it is a folder filled with images. Can anyone help me?
string[] folder = Directory.GetFiles(GetSourceDirectory());
Parallel.ForEach(folder, (file) =>
{
using (var fileStream = File.Open(file, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
var image = fileStream.Name;
Console.WriteLine(image);
Console.ReadLine();
using (var bitmap = new Bitmap(image))
{
using (var quantized = quantizer.QuantizeImage(bitmap, 1, 1))
{
var blob = container.GetBlockBlobReference(fileStream.Name);
try
{
quantized.Save(fileStream, ImageFormat.Png);
}
catch (ArgumentException e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
Console.WriteLine();
throw;
}
blob.UploadFromStreamAsync(fileStream).Wait();
}
}
}
});
This is because you are using the filestream to read and write at the same time.
If you change the File.Open to
using (var fileStream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
it will allow you to do
using (var bitmap = new Bitmap(image))
But then obviously you will come unstuck later when you try to write using the fileStream variable.
So I think you will have to change it so you don't have the nested using statements.
FileStream.Name gives you the file name only, like "image.jpg", have you tried using (var bitmap = new Bitmap(fileStream))?

Read file that's already used by another process

I have a C# app that tries to read a log file which is being written to by another app. When I try to read the file, I get IOException
"The process cannot access the file ... because it is being used by
another process."
What I tried using so far are the following, but none of them fix the problem
var log = File.ReadAllText(logPath);
var stream = new FileStream(logPath, FileMode.Open);
using (var stream = File.Open(logPath, FileMode.Open))
{
}
try this:
FileStream logFileStream = new FileStream("c:\test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader logFileReader = new StreamReader(logFileStream);
while (!logFileReader.EndOfStream)
{
string line = logFileReader.ReadLine();
// Your code here
}
// Clean up
logFileReader.Close();
logFileStream.Close();
edited with MethodMan's suggestions
using(FileStream logFileStream = new FileStream(#"c:\test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using(StreamReader logFileReader = new StreamReader(logFileStream))
{
string text = logFileReader.ReadToEnd();
// Your code..
}
}
You can do nothing, if the "another app" does not use Share.Read while creating/opening the file.

Can't access file which has been used by some other process

Hi I am having a button in my WPF application which extracts set of files from a zip. I need to work with a file in the extracted folder. But after extraction if i access that file i keep getting an exception stating that "File has been used by other process, can't access" like that.
I used Stream.flush(), Stream.Close(), Stream.Dispose(). None of them is usefull.
var zipFilePath = #"C:\Output.zip";
var tempFolderPath = #"C:\Unzipped";
using (Package package = ZipPackage.Open(zipFilePath, FileMode.Open, FileAccess.Read))
{
foreach (PackagePart part in package.GetParts())
{
var target = Path.GetFullPath(Path.Combine(tempFolderPath, part.Uri.OriginalString.TrimStart('/')));
var targetDir = target.Remove(target.LastIndexOf('\\'));
if (!Directory.Exists(targetDir))
Directory.CreateDirectory(targetDir);
MemoryStream memoryStream = new MemoryStream();
using (Stream source = part.GetStream(FileMode.Open, FileAccess.Read))
// using (Stream source = new FileStream(, FileMode.Open))
{
source.CopyTo(File.OpenWrite(target));
// CopyStreamTo(source, memoryStream);
}
}
}
MessageBox.Show("Extracted in a folder");
myclass obj=new myclass(#"C:\Unzipped\Something.xml");
// Something.xml has been used by some other process
Extraction works fine. But after extraction when i access file in C:\Unzipped\something.xml i keep getting this error."The process cannot access the file 'C:\Unzipped\Something.xml' because it is being used by another process."
How can i solve it??
You should dispose IDisposable resources by wrapping them in using statements:
using (Package package = ZipPackage.Open(zipFilePath, FileMode.Open, FileAccess.Read))
{
foreach (PackagePart part in package.GetParts())
{
var target = Path.GetFullPath(Path.Combine(tempFolderPath, part.Uri.OriginalString.TrimStart('/')));
var targetDir = target.Remove(target.LastIndexOf('\\'));
if (!Directory.Exists(targetDir))
{
Directory.CreateDirectory(targetDir);
}
using (Stream source = part.GetStream(FileMode.Open, FileAccess.Read))
using (Stream targetFileStream = File.OpenWrite(target))
{
source.CopyTo(targetFileStream);
}
}
}

How can I read a text file without locking it?

I have a windows service writes its log in a text file in a simple format.
Now, I'm going to create a small application to read the service's log and shows both the existing log and the added one as live view.
The problem is that the service locks the text file for adding the new lines and at the same time the viewer application locks the file for reading.
The Service Code:
void WriteInLog(string logFilePath, data)
{
File.AppendAllText(logFilePath,
string.Format("{0} : {1}\r\n", DateTime.Now, data));
}
The viewer Code:
int index = 0;
private void Form1_Load(object sender, EventArgs e)
{
try
{
using (StreamReader sr = new StreamReader(logFilePath))
{
while (sr.Peek() >= 0) // reading the old data
{
AddLineToGrid(sr.ReadLine());
index++;
}
sr.Close();
}
timer1.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
using (StreamReader sr = new StreamReader(logFilePath))
{
// skipping the old data, it has read in the Form1_Load event handler
for (int i = 0; i < index ; i++)
sr.ReadLine();
while (sr.Peek() >= 0) // reading the live data if exists
{
string str = sr.ReadLine();
if (str != null)
{
AddLineToGrid(str);
index++;
}
}
sr.Close();
}
}
Is there any problem in my code in reading and writing way?
How to solve the problem?
You need to make sure that both the service and the reader open the log file non-exclusively. Try this:
For the service - the writer in your example - use a FileStream instance created as follows:
var outStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Write, FileShare.ReadWrite);
For the reader use the same but change the file access:
var inStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite);
Also, since FileStream implements IDisposable make sure that in both cases you consider using a using statement, for example for the writer:
using(var outStream = ...)
{
// using outStream here
...
}
Good luck!
Explicit set up the sharing mode while reading the text file.
using (FileStream fs = new FileStream(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (sr.Peek() >= 0) // reading the old data
{
AddLineToGrid(sr.ReadLine());
index++;
}
}
}
new StreamReader(File.Open(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
-> this doesn't lock the file.
The problem is when you are writing to the log you are exclusively locking the file down so your StreamReader won't be allowed to open it at all.
You need to try open the file in readonly mode.
using (FileStream fs = new FileStream("myLogFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (!fs.EndOfStream)
{
string line = fs.ReadLine();
// Your code here
}
}
}
I remember doing the same thing a couple of years ago. After some google queries i found this:
FileStream fs = new FileStream(#”c:\test.txt”,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite);
i.e. use the FileShare.ReadWrite attribute on FileStream().
(found on Balaji Ramesh's blog)
Have you tried copying the file, then reading it?
Just update the copy whenever big changes are made.
This method will help you to fastest read a text file and without locking it.
private string ReadFileAndFetchStringInSingleLine(string file)
{
StringBuilder sb;
try
{
sb = new StringBuilder();
using (FileStream fs = File.Open(file, FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
string str;
while ((str = sr.ReadLine()) != null)
{
sb.Append(str);
}
}
}
}
return sb.ToString();
}
catch (Exception ex)
{
return "";
}
}
Hope this method will help you.

Categories