Is there way to read a text file from an assembly by using Reflection in C#? - assemblies

I have a text file inside the assembly say MyAssembly. I am trying to access that text file from the code like this :
Stream stream = Assembly.GetAssembly(typeof(MyClass)).GetFile("data");
where data is data.txt file containing some data and I have added that .txt as Embedded Resources. I have dome reading of the images from the Assebly as embedded resources with code like this :
protected Stream GetLogoImageStream()
{
Assembly current = Assembly.GetExecutingAssembly();
string imageFileNameFormat = "{0}.{1}";
string imageName = "myLogo.GIF";
string assemblyName = current.ManifestModule.Name;
int extensionIndex = assemblyName.LastIndexOf(".dll", StringComparison.CurrentCultureIgnoreCase);
string file = string.Format(imageFileNameFormat, assemblyName.Remove(extensionIndex, 4), imageName);
Stream thisImageStream = current.GetManifestResourceStream(file);
return thisImageStream;
}
However, this approach did not work while reading the .txt file from an the executing assembly. I would really appreciate if anybody can point me to the approach to read .txt file from an assembly. Please dont ask me why I am not reading the file from the drive or the network share. Just say that the requirement is to read the .txt file from the Assembly.
Thank you so much

GetManifestResourceStream is indeed the correct way to read the data. However, when it returns null, that usually means you have specified the wrong name. Specifying the correct name is not as simple as it seems. The rules are:
The VB.NET compiler generates a resource name of <root namespace>.<physical filename>.
The C# compiler generates a resource name of <default namespace>.<folder location>.<physical filename>, where <folder location> is the relative folder path of the file within the project, using dots as path separators.
You can call the Assembly.GetManifestResourceNames method in the debugger to check the actual names generated by the compiler.

Your approach should work. GetManifestResourceStream returns null, if the resource is not found. Try checking the run-time value of your file variable with the actual name of the resource stored in the assembly (you could check it using Reflector).

I really appreciate for everybody's help on this question. I was able to read the file with the code like this :
Assembly a = Assembly.GetExecutingAssembly();
string[] nameList = a.GetManifestResourceNames();
string manifestanme = string.Empty;
if (nameList != null && nameList.Length > 0)
{
foreach (string name in nameList)
{
if (name.IndexOf("c.txt") != -1)
{
manifestanme = name;
break;
}
}
}
Stream stream = a.GetManifestResourceStream(manifestanme);
Thanks and +1 for Christian Hayter for this method : a.GetManifestResourceNames();

Related

What is the path of the Json file in Android at Xamarin.Forms?

I am developing an application for Android using Xamarin.
I have created a JsonData folder in the Android project and created a Setting.json file.
\MyApp\MyApp.Android\JsonData\Setting.json
In the properties, we set the Copy when new.
The following folders in the local environment contain the files.
\MyApp\MyApp.Android\bin\Debug\JsonData\Setting.json
I want to load this file in the actual Android device.
When I do this, it tells me that the file is missing.
Could not find a part of the path "/JsonData/Setting.json."
Try
{
var text = File.ReadAllText("JsonData/Setting.json", Encoding.UTF8);
var setting = JsonConvert.DeserializeObject<Setting>(text);
}
catch(Exception exception)
{
var error = exception.Message;
}
What is the path of the file in Android?
I think you're using File Handling in Xamarin.Forms incorrectly.
From the parameter of function File.ReadAllText, the app will access the file system to getSetting.json from folder JsonData in your android device.
The path of the file on each platform can be determined from a .NET Standard library by using a value of the Environment.SpecialFolder enumeration as the first argument to the Environment.GetFolderPath method. This can then be combined with a filename with the Path.Combine method:
string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "temp.txt");
And you can read the file by code:
string text = File.ReadAllText(fileName);
In addition, from your code,I guess you want to Load your Embedded file( Setting.json) as Resources,right?
In this case,we should make sure the Build Action of your Setting.json is Embedded Resource.
And GetManifestResourceStream is used to access the embedded file using its Resource ID.
You can refer to the following code:
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(LoadResourceText)).Assembly;
Stream stream = assembly.GetManifestResourceStream("YourAppName.JsonData.Setting.json");
string text = "";
using (var reader = new System.IO.StreamReader (stream))
{
text = reader.ReadToEnd ();
}
For more , you can check document : File Handling in Xamarin.Forms.
And you can also check the sample code here: https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/workingwithfiles/ .

Getting files on iOS

I am creating json files FileSystem.AppDataDirectory, "test"," {Hour}.json "; I can see the files on the device in Xcode.. once I return only one with this Path.Combine(FileSystem.AppDataDirectory, "test",".json") then I can read its content.
However once I need to return all files from the directory and list the path to them in my application
var result = Directory.EnumerateFiles(FileSystem.AppDataDirectory, "test");
The result is empty
this is the path /var/mobile/Containers/Data/Application/02A91048-0016-4E20-A8A6-EB2A89649F1F/Library
which is correct an I see the files the physical. Where am I doing mistake?
I have also tried this
var test = FileSystem.OpenAppPackageFileAsync(FileSystem.AppDataDirectory);
but I am getting unauthorized exception
you are looking for files in the test subfoloder
the signature of EnumerateFiles is
public static System.Collections.Generic.IEnumerable<string> EnumerateFiles (string path, string searchPattern);
so you want to do this
var path = Path.Combine(FileSystem.AppDataDirectory,"test");
var result = Directory.EnumerateFiles(path, "*.json");

Uploading files to Blob & getting error: C:\Program Files (x86)\IIS Express\

I tried to upload file to blob. But I'm getting error like this:
"'C:\Program Files (x86)\IIS
Express\Nominative-Officers-Entry-Form-Stu.docx'."
I don't use HttpPostedFileBase in my code. I just pass object to my controller with files to be uploaded. Lease tell me what I'm doing wrong?
I want to know wt this line means :
"blockBlob.Properties.ContentType = "
This is my code:
public static SaveResponses CreateFile(Blob_Storage_Header docDetails)
{
string storageConnectionString = ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString.ToString();
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("test2");
ICollection<Blob_Storage_Details> BlobStorageDetails = docDetails.Blob_Storage_Details;
if (BlobStorageDetails.Count > 0) {
foreach (Blob_Storage_Details item in BlobStorageDetails)
{
string DocUUID = Guid.NewGuid().ToString();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(DocUUID + item.Blob_Name);
var fileName = Path.GetFileName(item.Blob_Name);
//blockBlob.Properties.ContentType = item.ContentType;
// Create or overwrite the "myblob" blob with contents from a local file.
using (var fileStream = File.OpenRead(fileName))
{
blockBlob.UploadFromStream(fileStream);
}
}
}
SaveResponses saveResponse = new SaveResponses();
saveResponse.saveStatus = "true";
saveResponse.messageType = "success";
saveResponse.message = "File Create message";
return (saveResponse);
}
"'C:\Program Files (x86)\IIS Express\Nominative-Officers-Entry-Form-Stu.docx'."
Based on your code, I ran it on my side, then I got the following error:
Remark: In development environment, you could add “<customErrors mode="Off"/>” within the system.web node in your Web.config file, then you could view the detailed errors.
According to this error, I checked and found the specified file path was not existed.
After some trials, I fixed the issue on my side. Please follow the descriptions below to check your code to see whether it works:
a) Please pay attention to the code “Path.GetFileName”, it returns the file name and extension of the specified path string (e.g. settings.job).
b) Make sure that the filename that is used in “File.OpenRead(fileName)” is an absolute file path and the file is existed in your environment.
"blockBlob.Properties.ContentType = "
Azure Storage Client Library for .NET is based on Storage Service REST API,
From the official document we could find that “blockBlob.Properties.ContentType” represents the MIME content type of the blob, the default type is application/octet-stream.
MIME is a way to identity files on internet according to their nature and format. For example, using the "Content-type" header value defined in a HTTP response, the browser can open the file with the proper extension/plugin. For more details about MIME, please refer to this link: http://www.freeformatter.com/mime-types-list.html

virtual path change

I want to change Virtual Path(The path is out of project means local system or Server.) of the file Which is save on the folder in asp.net.
Code is
DataTable dtFiles =
GetFilesInDirectory(HttpContext.Current.Server.MapPath(UPLOADFOLDER));
gv.DataSource = dtFiles;
gv.DataBind();
if (dtFiles != null && dtFiles.Rows.Count > 0)
{
double totalSize = Convert.ToDouble(dtFiles.Compute("SUM(Size)", ""));
if (totalSize > 0) lblTotalSize.Text = CalculateFileSize(totalSize);
}
private static string UPLOADFOLDER = "D:/Uploads";
And the error show "D:/Uploads is not a valid virtual path.".
If you want to get the files in a directory and you know the full path, then you don't need to use Server.MapPath(). Just use the path.
Incidentally, the path delimiter is incorrect in your code. The string "D:/Uploads" should be #"D:\Uploads" (note the leading # sign to denote a string that should be treated literally and not escaped).
Of course. You're telling your server to map path that is completely off the IIS. How is it supposed to do? If you're using a web application, try to avoid such ideas completely. Even though it is possible, it isn't a good idea because of security issues you can run into.

Convert CSV file or Excel spreadsheet to RESX File

I am looking for a solution or recommendation to a problem I am having. I have a bunch of ASPX pages that will be localized and have a bunch of text that needs to be supported in 6 languages.
The people doing the translation will not have access to Visual Studio and the likely easiest tool is Excel. If we use Excel or even export to CSV, we need to be able to import to move to .resx files. So, what is the best method for this?
I am aware of this question, Convert a Visual Studio resource file to a text file? already and the use of Resx Editor but an easier solution would be preferred.
I'm not sure how comprehensive an answer you're looking for, but if you're really just using [string, string] pairs for your localization, and you're just looking for a quick way to load resource (.resx) files with the results of your translations, then the following will work as a fairly quick, low-tech solution.
The thing to remember is that .resx files are just XML documents, so it should be possible to manually load your data into the resource from an external piece of code. The following example worked for me in VS2005 and VS2008:
namespace SampleResourceImport
{
class Program
{
static void Main(string[] args)
{
XmlDocument doc = new XmlDocument();
string filePath = #"[file path to your resx file]";
doc.Load(filePath);
XmlElement root = doc.DocumentElement;
XmlElement datum = null;
XmlElement value = null;
XmlAttribute datumName = null;
XmlAttribute datumSpace = doc.CreateAttribute("xml:space");
datumSpace.Value = "preserve";
// The following mocks the actual retrieval of your localized text
// from a CSV or ?? document...
// CSV parsers are common enough that it shouldn't be too difficult
// to find one if that's the direction you go.
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("Label1", "First Name");
d.Add("Label2", "Last Name");
d.Add("Label3", "Date of Birth");
foreach (KeyValuePair<string, string> pair in d)
{
datum = doc.CreateElement("data");
datumName = doc.CreateAttribute("name");
datumName.Value = pair.Key;
value = doc.CreateElement("value");
value.InnerText = pair.Value;
datum.Attributes.Append(datumName);
datum.Attributes.Append(datumSpace);
datum.AppendChild(value);
root.AppendChild(datum);
}
doc.Save(filePath);
}
}
}
Obviously, the preceding method won't generate the code-behind for your resource, however opening the resource file in Visual Studio and toggling the accessibility modifier for the resource will (re)generate the static properties for you.
If you're looking for a completely XML-based solution (vs. CSV or Excel interop), you could also instruct your translators to store their translated content in Excel, saved as XML, then use XPath to retrieve your localization info. The only caveat being the file sizes tend to become pretty bloated.
Best of luck.
I ran into similar problem and realized that the simplest way to create a .resx file from excel file is using a concatenate function of excel to generate "<"data">".."<"/data">" node for the .resx file and then manually copying the generated rows to the .resx file in any text editor. So lets say that you have "Name" in column A of an excel document and "value" in Column B of the excel document. Using following formula in Column C
=CONCATENATE("<data name=","""",A14,""" xml:space=""preserve"">","<value>", B14, "</value>", "</data>")
you will get the data node for resource. You can then copy this formula to all the rows and then copy the contents of Column C in your .resx file.
If it's in csv here's a quick Ruby script to generate the data elements.
require 'csv'
require 'builder'
file = ARGV[0]
builder = Builder::XmlMarkup.new(:indent => 2)
CSV.foreach(file) do |row|
builder.data(:name => row[0], "xml:space" => :preserve) {|d| d.value(row[1]) }
end
File.open(file + ".xml", 'w') { |f| f.write(builder.target!) }

Resources