I get the following exception when I try to delete a directory in Isolated Storage in Windows Phone 7:
An error occurred while accessing IsolatedStorage.
there is no inner exception.
using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
{
isf.DeleteDirectory(dir.TrimEnd('/'));
}
Notes:
putting it in a try-catch will hide the exception but still directory is not deleted!
before calling this I delete all files inside that using DeleteFile() so the problem can not be related to existing files inside the directory.
trimming the directory name is to make sure it's a valid directory name.
Any idea?
Thanks.
Ok, problem solved, problem was that files were not being deleted correctly. The reason I was confused is that IsolatedStorageFile class does not warn you when you are deleting an invalid file. here is the correct code and some notes:
public static void DeleteDirectoryRecursive(this IsolatedStorageFile isf, string dir)
{
foreach (var file in isf.GetFileNames(dir))
{
isf.DeleteFile(dir + file);
}
foreach (var subdir in isf.GetDirectoryNames(dir))
{
isf.DeleteDirectoryRecursive(dir + subdir + "\\");
}
isf.DeleteDirectory(dir.TrimEnd('\\'));
}
Notes:
there is no difference between '\' and '/' in file paths
trimEnd() is required when DeleteDirectory otherwise exception "path must be a valid file name" is thrown.
GetFileNames() and GetDirectoryNames() return only the name part not the full path. so in order to use each result you need to combine it with the directory (DeleteFile() in this example)
According to your code and your description, you would be recreating the IsolatedStorageFile access on every iteration?
You should post all the code, since the error isn't related to what you told so far. As for a working example, see this blog post. If that fails with your directory name, you're clearly doing something wrong.
Also, I believe it uses backslashes, not forward-slashes for paths, so your Trim() would be rather useless either way.
`public static void DeleteDirectoryRecursive(string directory, IsolatedStorageFile store)
{
if (!store.DirectoryExists(directory))
return;
var pattern = Path.Combine(directory, "*");
foreach (var file in store.GetFileNames(pattern))
{
store.DeleteFile(Path.Combine(directory, file));
}
foreach (var folder in store.GetDirectoryNames(pattern))
{
DeleteDirectoryRecursive(Path.Combine(directory, folder), store);
}
store.DeleteDirectory(directory);
}`
Thanks to valipour, I solved the problem
foreach (var file in isf.GetFileNames(dir))
{
isf.DeleteFile(dir + file);
}
In my case the variable dir is "images". In order to get all file names in "images" directory, you should use isf.GetFileNames("images/*")
Grabbed Valipour's version and make it work. Added some checks to improve stability + fixed some names. This works for me on Lumia 920.
private void DeleteDirectoryRecursive(string dir)
{
if (String.IsNullOrEmpty(dir)) return;
try
{
using (var isoFiles = IsolatedStorageFile.GetUserStoreForApplication())
{
foreach (var file in isoFiles.GetFileNames(dir + "\\*"))
{
var filename = dir + "/" + file;
if (isoFiles.FileExists(filename))
isoFiles.DeleteFile(filename);
}
foreach (var subdir in isoFiles.GetDirectoryNames(dir))
{
var dirname = dir + subdir + "\\";
if (isoFiles.DirectoryExists(dirname))
DeleteDirectoryRecursive(dirname);
}
var currentDirname = dir.TrimEnd('\\');
if (isoFiles.DirectoryExists(currentDirname))
isoFiles.DeleteDirectory(currentDirname);
}
}
catch (Exception e)
{
throw;
}
}
Related
I have some Images in a folder. The images can be easily transferred from the First to the Second folder. So far, everything seems to be ok, but how to pass an image from the First directory to the Second directory which is identical to the image that already exists in the Second folder? In simple terms: How to update or overwrite the files in this Second folder? Many thanks in advance for your help!
string pathName = #"C:\Users\Desktop\Images\Second\";
foreach (var file in Directory.EnumerateFiles(#"C:\Users\Desktop\Images\"))
{
if (!Directory.Exists(pathName))
{
Directory.CreateDirectory(pathName);
}
string destFile = Path.Combine(pathName, Path.GetFileName(file));
if (!File.Exists(destFile))
{
File.Move(file, destFile);
}
}
UPDATE:
I forgot, that method Move has third parameter bool overwrite. You can use it
File.Move(file, destFile, true);
You will find more info here
You can use File.OpenRead, File.OpenWrite and stream.CopyTo methods for this task
if (!File.Exists(destFile))
{
File.Move(file, destFile);
}
else
{
using (var sourceStream = File.OpenRead(file))
using (var desStream = File.OpenWrite(destFile))
sourceStream.CopyTo(desStream);
}
The move method can have a third parameter a boolean to override
Move(String, String, Boolean)
Moves a specified file to a new location, providing the options to specify a new file name and to overwrite the destination file if it already exists.
Check https://learn.microsoft.com/en-us/dotnet/api/system.io.file.move?view=net-5.0
Or You can use File.replace() if the File exist in destination to save a backup of the deleted file.
public static void Replace (string sourceFileName, string destinationFileName, string? destinationBackupFileName);
it will be like this
string pathName = #"C:\Users\Desktop\Images\Second\";
foreach (var file in Directory.EnumerateFiles(#"C:\Users\Desktop\Images\"))
{
if (!Directory.Exists(pathName))
{
Directory.CreateDirectory(pathName);
}
string destFile = Path.Combine(pathName, Path.GetFileName(file));
string backupFile = 'Some place to backup the deleted image'.
if (!File.Exists(destFile))
{
File.Move(file, destFile);
}
else
{
File.Replace(file, destFile, backupFile);
}
}
you can check https://learn.microsoft.com/en-us/dotnet/api/system.io.file.replace?view=net-5.0 for documentations
I have the following lines of code that work for creating a zip using ZipFile.CreateFromDirectory(selectedFile, zipPath)
if (selectedFolder == string.Empty)
{
Console.WriteLine("Invalid folder, try again");
}
else
{
Console.WriteLine("\nSelect zipfile name: ");
var zipName = Console.ReadLine();
// Also available: extractToDirectory
var zipPath = #"C:\Users\User\Documents\Dev\" + zipName + ".zip";
ZipFile.CreateFromDirectory(selectedFolder, zipPath);
However, the following code which should for all intents and purposes do the same thing except for multiple files being archived into a single zip folder refuses to work:
public static void CreateZipFile(string folderToCreateZip, IEnumerable<string> files)
{
var zipPath = folderToCreateZip + "\\test6.zip";
// Create a new ZIP in this location
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
{
foreach (var file in files)
{
// Add entry for files
zip.CreateEntryFromFile(file, zipPath, CompressionLevel.Optimal);
}
}
// Dispose of zip object after files have been zipped
//zip.Dispose();
}
var zip == ZipArchive zip
I've tried disabling read-only mode on the folders where the zip should get created, but I don't think this matters since the prior function with CreateFromDirectory() works fine. I've also tried creating a ZIP on desktop, but I get the same error.
This is the exception I'm getting:
As a note, I noticed that it does initially create the zip despite this error, just that it cannot add anything to it unlike CreateFromDirectory() can due to the folder either being in use, no permissions to that area or the folder already existing. Is there a way I can get CreateEntryFromFile() working or an alternative that would work for multiple files?
I had the same problem. The solution was post the full path name at the destinationArchiveFileName parameter (and also a write alowed path). For example c:\my apps folder\my app\my temp\zipfile.zip
I have some folders and these folders have some text files and i need delete these files but i catch an error with my code!
var dateFolder = Directory.GetDirectories(#"data\stdate").Select(Path.GetDirectoryName).ToArray();
foreach (var dateFile in dateFolder)
{
var stDates =
Directory.GetFiles(#"data\stdate\" + dateFile + "date").Select(Path.GetFileName).ToArray();
foreach (var date in stDates)
{
File.Delete(#"data\stdate\" + dateFile + "date\\" + date);
}
Directory.Delete(#"data\stdate\" + dateFile + "date");
}
try this:
Directory.Delete("Path", true); //true: It will delete directory by given path, also folders and files in it.
System.IO.DirectoryInfo di = new DirectoryInfo(#"data\stdate");
//This for delete all file in "data\stdate"
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
//***************************For delete file in folder
//This for delete all Subfolder and his files in "data\stdate"
foreach (DirectoryInfo dir in di.GetDirectories())
{
dir.Delete(true);
}
//*************************
//This for delete the parent folder "stdate"
di.Delete();
i delete my original folder and i create it again!
if (!isDateEmpty)
{
Directory.Delete(#"data\stdate", true);
Directory.CreateDirectory(#"data\stdate");
}
I suggest that you use system environment variables, see here:
https://en.wikipedia.org/wiki/Environment_variable
The reason being, like you found out: sometimes the executable is not running in the directory you expected when you compiled the program.
EX:
String query = "%SystemDrive%";
str = Environment.ExpandEnvironmentVariables(query);
Delete(str, true);
That way it guarantees a predictable path as opposed to a relative one.
ZipFile.CreateFromDirectory(source_dir, target_dir) will throw exception and stop the zipping when any file in the directory is being accessed. how can I make it do the zipping for the rest of the files ??
Killing the processes are not allowed, they are vital.
Thanks
Resolved:
Here is how I get this around.
Split the task into 2 phase.
(Note only use the Zipfile and ZipArchive from System.IO.Compression)
Step 1. create a dummy zip file; (this must not hit access issue)
Step 2. Scan and Add files to the dummy zip file
Additional: Keep the original directory hierarchy by adding folder into the dummy zip file
Here is the Step 2, only copy the file when hit exception.
private void UpdateBallFile(String source_dir, String target_zipfile)
{
using (ZipArchive archive = ZipFile.Open(target_zipfile + suffix, ZipArchiveMode.Update))
{
foreach (String subdir in Directory.GetDirectories(source_dir, "*.*", SearchOption.AllDirectories))
{
String relatedPath = subdir.Replace(source_dir, String.Empty);
String entry = relatedPath.Replace("\\", "/").Substring(1);
foreach (String file in Directory.GetFiles(subdir))
{
if (File.Exists(file))
{
FileInfo info = new FileInfo(file);
try
{
archive.CreateEntryFromFile(file, entry+"/"+info.Name);
}
catch
{
try
{
String copied_item = Path.Combine(#"c:\", info.Name);
File.Copy(file, copied_item, true);
archive.CreateEntryFromFile(copied_item, entry + "/" + info.Name);
File.Delete(copied_item);
}
catch (Exception ex)
{
UpdateLog(String.Format("Fails to zip: {0}, {1} ", file, ex.Message));
}
}
}
}
}
}
}
I am new to C# and this community, Please let me know if you have better idea.
Thanks
You can add each file to your zip by checking the accessibility, so you can code like this:
ZipFile myzip = new ZipFile("myzipFile");
foreach (string file in Directory.GetFiles(#"D:\sample"))
{
try
{
var stream = File.Open(file, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
stream.Dispose();
myzip.AddFile(file);// add file to zip only if it is accessible. else it will throw some exception
//hence it wont added to the zipped folder.
}
catch
{ }
}
myzip.Save(#"D:\sample\myfile.zip");// this zip file contains only file that have access
Hope that this is actually you ware looking;
An easy solution would be preparing a kind of copy/temp folder in the User/AppData/Local directory, where all readable files are in. You will than zip this folder, because you can be sure that the data are not used. After the zip-process you have to delete the folder. Not the optimum but it should work. Another solution would be using some other zip component...
In my application there is a situation like this.Before creating a file, my application search for files in a directory under a particular filename. If any file/files found, then it should read each files contents and write these contents(of each file) to a new file. I have googled many and tried some like this:
string temp_file_format = "ScriptLog_" + DateTime.Now.ToString("dd_MM_yyyy_HH");
string[] files = Directory.GetFiles(path,temp_file_format);
foreach (FileAccess finfo in files)
{
string text = File.ReadAllText(finfo);
}
and
System.IO.DirectoryInfo dir = new DirectoryInfo(path);
System.IO.FileInfo[] files = dir.GetFiles(temp_file_format);
foreach (FileInfo finfo in files)
{
finfo.OpenRead();
}
But all these failed..Can anyone show me an alternative for this?
Is there anything wrong in my temp_file_format string?
It will be nice if I could prepend these contents to the new file. Else also, no worries..
any help would be really appreciated..
This is a compete working implementation that does all of that
without reading everything in memory at one time (which doesn't work for large files)
without keeping any files open for more than the required time
using System.IO;
using System.Linq;
public static class Program {
public static void Main()
{
var all = Directory.GetFiles("/tmp", "*.cpp")
.SelectMany(File.ReadAllLines);
using (var w = new StreamWriter("/tmp/output.txt"))
foreach(var line in all)
w.WriteLine(line);
}
}
I tested it on mono 2.10, and it should work on any .NET 4.0+ (for File.ReadAllLines which is a lazy linewise enumerable)
Here's a short snippet that reads all the files and out puts them to the path outputPath
var lines = from file in Directory.GetFiles(path,temp_file_format)
from line in File.ReadAllLines(file)
select line;
File.WriteAllLines(outputPath, content);
The problem you are having with your code is not really related to reading files but simply trying to use an object as a type it's not. Directory.GetFiles returns an array of string and File.ReadXXX and File.OpenRead expects the path as a string. So you simply need to pass each of the strings returned as the path argument to the appropriate method. The above is one such example. Hope it helps both solve your problem and explain the actually issue with your code
try this:
foreach (FileInfo finfo in files)
{
try
{
using (StreamReader sr = new StreamReader("finfo "))
{
String line = sr.ReadToEnd();
Console.WriteLine(line);
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
using (var output = File.Create(outputPath))
{
foreach (var file in Directory.GetFiles(InputPath,temp_file_format))
{
using (var input = File.OpenRead(file))
{
input.CopyTo(output);
}
}
}