Dynamic resource from MemoryStream with ResourceWriter - c#

I'm developing an app with C# and WPF;
I'm creating a resource to a MemoryStream.
var ms = new MemoryStream();
var rWriter = new ResourceWriter(ms);
rWriter.AddResource("key1", "value1");
rWriter.AddResource("key2", "value2");
rWriter.AddResource("key3", "value3");
rWriter.Generate();
rWriter.Close();
Everything works fine untill here but, I don't know how to use this Resource?
Can you help me with using ?

Once you have read the resource into the stream you need to add it to the MergedDictionaries in order to make it available in the application. An example of this might look like this:
var resourceInfo = skinAssembly.GetManifestResourceInfo(resourceName);
if (resourceInfo.ResourceLocation != ResourceLocation.ContainedInAnotherAssembly)
{
var resourceStream = skinAssembly.GetManifestResourceStream(resourceName);
using (var resourceReader = new ResourceReader(resourceStream))
{
foreach (DictionaryEntry entry in resourceReader)
{
if (IsRelevantResource(entry, bamlResourceName))
{
skinBamlStreams.Add(entry.Value as Stream);
}
}
}
}
The code above was taken from my demo application which you can see the full source code for on GitHub.
protected override sealed void LoadResources()
{
var skinResolver = PreLoadResources();
try
{
var skinBamlStreams = skinResolver.GetSkinBamlStreams(_fullName, _resourceName);
foreach (var resourceStream in skinBamlStreams)
{
var skinResource = BamlHelper.LoadBaml<ResourceDictionary>(resourceStream);
if (skinResource != null)
{
Resources.Add(skinResource);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
PostLoadResources();
}
}

Related

Tesseract not reading single value and some values

private void GetOCRValue(Bitmap image)
{
string ocrValue = "";
try
{
using (var engine = new TesseractEngine(Application.StartupPath + "\\tessdata", "eng", EngineMode.Default))
{
using (var imager = new System.Drawing.Bitmap(image))
{
using (var pix = PixConverter.ToPix(imager))
{
using (var page = engine.Process(pix))
{
ocrValue = page.GetText();
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
I'm trying to retrieve values from a bitmap.But Tesseract not returning the single number values and some other numbers like "13".I'm using Tesseract 3.3.0 Nuget package.How can I resolve this problem?

How to create zip file in memory?

I have to create a zip file from set of urls. and it should have a proper folder structure.
So i tried like
public async Task<byte[]> CreateZip(Guid ownerId)
{
try
{
string startPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "zipFolder");//base folder
if (Directory.Exists(startPath))
{
DeleteAllFiles(startPath);
Directory.Delete(startPath);
}
Directory.CreateDirectory(startPath);
string zipPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{ownerId.ToString()}"); //folder based on ownerid
if (Directory.Exists(zipPath))
{
DeleteAllFiles(zipPath);
Directory.Delete(zipPath);
}
Directory.CreateDirectory(zipPath);
var attachemnts = await ReadByOwnerId(ownerId);
attachemnts.Data.ForEach(i =>
{
var fileLocalPath = $"{startPath}\\{i.Category}";
if (!Directory.Exists(fileLocalPath))
{
Directory.CreateDirectory(fileLocalPath);
}
using (var client = new WebClient())
{
client.DownloadFile(i.Url, $"{fileLocalPath}//{i.Flags ?? ""}_{i.FileName}");
}
});
var zipFilename = $"{zipPath}//result.zip";
if (File.Exists(zipFilename))
{
File.Delete(zipFilename);
}
ZipFile.CreateFromDirectory(startPath, zipFilename, CompressionLevel.Fastest, true);
var result = System.IO.File.ReadAllBytes(zipFilename);
return result;
}
catch (Exception ex)
{
var a = ex;
return null;
}
}
currently im writing all files in my base directory(may be not a good idea).corrently i have to manually delete all folders and files to avoid exception/unwanted files. Can everything be written in memory?
What changes required to write all files and folder structure in memory?
No you can't. Not with the built in Dotnet any way.
As per my comment I would recommend storing the files in a custom location based on a Guid or similar. Eg:
"/xxxx-xxxx-xxxx-xxxx/Folder-To-Zip/....".
This would ensure you could handle multiple requests with the same files or similar file / folder names.
Then you just have to cleanup and delete the folder again afterwards so you don't run out of space.
Hope the below code does the job.
public async Task<byte[]> CreateZip(Guid ownerId)
{
try
{
string startPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}_zipFolder");//folder to add
Directory.CreateDirectory(startPath);
var attachemnts = await ReadByOwnerId(ownerId);
attachemnts.Data = filterDuplicateAttachments(attachemnts.Data);
//filtering youtube urls
attachemnts.Data = attachemnts.Data.Where(i => !i.Flags.Equals("YoutubeUrl", StringComparison.OrdinalIgnoreCase)).ToList();
attachemnts.Data.ForEach(i =>
{
var fileLocalPath = $"{startPath}\\{i.Category}";
if (!Directory.Exists(fileLocalPath))
{
Directory.CreateDirectory(fileLocalPath);
}
using (var client = new WebClient())
{
client.DownloadFile(i.Url, $"{fileLocalPath}//{i.Flags ?? ""}_{i.FileName}");
}
});
using (var ms = new MemoryStream())
{
using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
System.IO.DirectoryInfo di = new DirectoryInfo(startPath);
var allFiles = di.GetFiles("",SearchOption.AllDirectories);
foreach (var attachment in allFiles)
{
var file = File.OpenRead(attachment.FullName);
var type = attachemnts.Data.Where(i => $"{ i.Flags ?? ""}_{ i.FileName}".Equals(attachment.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
var entry = zipArchive.CreateEntry($"{type.Category}/{attachment.Name}", CompressionLevel.Fastest);
using (var entryStream = entry.Open())
{
file.CopyTo(entryStream);
}
}
}
var result = ms.ToArray();
return result;
}
}
catch (Exception ex)
{
var a = ex;
return null;
}
}

NAudio code holds lock on input file

My code below holds a lock on the input file preventing me from working with it later:
public static void ToWave_WMF(string source, string destination)
{
using (var reader = new MediaFoundationReader(source))
using (var rateSampler = new MediaFoundationResampler(reader, new WaveFormat(DefaultEncoding.SampleRate, reader.WaveFormat.Channels)))
using (var channelSampler = new MediaFoundationResampler(rateSampler, new WaveFormat(rateSampler.WaveFormat.SampleRate, DefaultEncoding.Channels)))
{
WaveFileWriter.CreateWaveFile(destination, channelSampler);
}
}
public static string BuildWavFile(string userFileLocation)
{
var sampleList = new List<ISampleProvider>();
try
{
// Add input file
var waveFile = AudioHelpers.ToWave_WMF(userFileLocation);
sampleList.Add(new AudioFileReader(waveFile));
WaveFileWriter.CreateWaveFile16(sirenWaveFile, new ConcatenatingSampleProvider(sampleList));
}
finally
{
foreach (var sample in sampleList)
{
((AudioFileReader)sample).Dispose();
}
}
return sirenWaveFile;
}
Am I using resources wrong? Why is this lock being held? If I delete the file after toWave_WMF() there is no issue. If I use sampleList.Add(new AudioFileReader(userFileLocation)); I also dont have any issues deleting the userFile.

System.UnauthorizedAccessException: Access is denied. Windows Phone while using files

i'm getting a "System.UnauthorizedAccessException: Access is denied. " message when im trying to save a list on the Windows Phone.
Scenario:
When clicked on the FavoriteButton, the system will check if the item is already a favorite.
The next step is to call the Load method. This will return a list with favorites.
When the item is favorite I will remove it from the list, otherwise i will add it.
Final step is to save the new list with my Save method.
When executing this code i get the following exception:
System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED
I've looked around and saw that it could be the manifest capabilities. So i have checked them all just to be sure. After trying again I still get the exception!
What must i do? code below:
private async void favoriteClicked(object sender, EventArgs e)
{
if (_progressIndicator.IsVisible == false)
{
try
{
Boolean isFavorite = Settings.GetValueOrDefault<Boolean>(currentArtist.id, false);
ArtistSaving favorite = new ArtistSaving(currentArtist.id, currentArtist.name, currentArtist.shortBio);
artistList = await Task.Run(() => Utils.Load<ArtistSaving>());
if (isFavorite == true)
{
artistList.Remove(favorite);
displayDeletePopup();
Settings.AddOrUpdateValue(currentArtist.id, false);
await Task.Run(() => Utils.Save<ArtistSaving>(artistList));
}
else
{
artistList.Add(favorite);
displayXamlPopup();
Settings.AddOrUpdateValue(currentArtist.id, true);
await Task.Run(() => Utils.Save<ArtistSaving>(artistList));
}
}
catch (ArgumentException ex)
{
}
}
}
Favorite button click
public static async Task<ObservableCollection<T>> Load<T>()
{
// Create a new folder name DataFolder.
var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(JSONFILENAME,
CreationCollisionOption.OpenIfExists);
var jsonSerializer = new DataContractJsonSerializer(typeof(ObservableCollection<T>));
var myStream = await file.OpenStreamForReadAsync();
ObservableCollection<T> myObj = (ObservableCollection<T>)jsonSerializer.ReadObject(myStream);
if (myObj == null)
{
return new ObservableCollection<T>();
}
return myObj;
}
This is the Load method
public static async void Save<T>(ObservableCollection<T> obj)
{
var serializer = new DataContractJsonSerializer(typeof(ObservableCollection<T>));
using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(
JSONFILENAME, CreationCollisionOption.ReplaceExisting))
{
serializer.WriteObject(stream, obj);
}
}
and this was the Save method
EDIT -- SOLUTION
public static async Task<ObservableCollection<T>> Load<T>()
{
ObservableCollection<T> myObj = null;
// Create a new folder name DataFolder.
var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(JSONFILENAME,
CreationCollisionOption.OpenIfExists);
var jsonSerializer = new DataContractJsonSerializer(typeof(ObservableCollection<T>));
using (var myStream = await file.OpenStreamForReadAsync())
{
myObj = (ObservableCollection<T>)jsonSerializer.ReadObject(myStream);
if (myObj == null)
{
return new ObservableCollection<T>();
}
return myObj;
}
}
Most likely the file is still locked from when you read from it. Modify your Load method like this to release the file lock:
using (var myStream = await file.OpenStreamForReadAsync())
{
ObservableCollection<T> myObj = (ObservableCollection<T>)jsonSerializer.ReadObject(myStream);
}

Modifying existing resource file programmatically

I am using the following code to generate resource file programmatically.
ResXResourceWriter resxWtr = new ResXResourceWriter(#"C:\CarResources.resx");
resxWtr.AddResource("Title", "Classic American Cars");
resxWtr.Generate();
resxWtr.Close();
Now, i want to modify the resource file crated from above code. If i use the same code, the existing resource file gets replaced. Please help me modify it without loosing the existing contents.
Best Regards,
Ankit
public static void AddOrUpdateResource(string key, string value)
{
var resx = new List<DictionaryEntry>();
using (var reader = new ResXResourceReader(resourceFilepath))
{
resx = reader.Cast<DictionaryEntry>().ToList();
var existingResource = resx.Where(r => r.Key.ToString() == key).FirstOrDefault();
if (existingResource.Key == null && existingResource.Value == null) // NEW!
{
resx.Add(new DictionaryEntry() { Key = key, Value = value });
}
else // MODIFIED RESOURCE!
{
var modifiedResx = new DictionaryEntry() { Key = existingResource.Key, Value = value };
resx.Remove(existingResource); // REMOVING RESOURCE!
resx.Add(modifiedResx); // AND THEN ADDING RESOURCE!
}
}
using (var writer = new ResXResourceWriter(ResxPathEn))
{
resx.ForEach(r =>
{
// Again Adding all resource to generate with final items
writer.AddResource(r.Key.ToString(), r.Value.ToString());
});
writer.Generate();
}
}
I had the same problem this resolve it:
This will append to your existing .resx file
var reader = new ResXResourceReader(#"C:\CarResources.resx");//same fileName
var node = reader.GetEnumerator();
var writer = new ResXResourceWriter(#"C:\CarResources.resx");//same fileName(not new)
while (node.MoveNext())
{
writer.AddResource(node.Key.ToString(), node.Value.ToString());
}
var newNode = new ResXDataNode("Title", "Classic American Cars");
writer.AddResource(newNode);
writer.Generate();
writer.Close();
Here is a function that would help you modify the resource file.
public static void UpdateResourceFile(Hashtable data, String path)
{
Hashtable resourceEntries = new Hashtable();
//Get existing resources
ResXResourceReader reader = new ResXResourceReader(path);
if (reader != null)
{
IDictionaryEnumerator id = reader.GetEnumerator();
foreach (DictionaryEntry d in reader)
{
if (d.Value == null)
resourceEntries.Add(d.Key.ToString(), "");
else
resourceEntries.Add(d.Key.ToString(), d.Value.ToString());
}
reader.Close();
}
//Modify resources here...
foreach (String key in data.Keys)
{
if (!resourceEntries.ContainsKey(key))
{
String value = data[key].ToString();
if (value == null) value = "";
resourceEntries.Add(key, value);
}
}
//Write the combined resource file
ResXResourceWriter resourceWriter = new ResXResourceWriter(path);
foreach (String key in resourceEntries.Keys)
{
resourceWriter.AddResource(key, resourceEntries[key]);
}
resourceWriter.Generate();
resourceWriter.Close();
}
Reference link here

Categories

Resources