Got a bit of a strange issue with a bit of code in Xamarin Forms:
public void GetSettings()
{
var assembly = typeof(SettingsPage).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("FishBike_GPS.config.txt");
try
{
using (var reader = new System.IO.StreamReader(stream)) //load current settings from the config text file
{
configText = reader.ReadToEnd();
}
CurrentRentalSetting = Int32.Parse(configText);
stream.Dispose();
}
catch
{
configText = "Error reading file!";
}
}
public void SetSettings()
{
var assembly = typeof(SettingsPage).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("FishBike_GPS.config.txt");
try
{
using (var streamWriter = new System.IO.StreamWriter(stream)) //save current settings from the config text file
{
streamWriter.WriteLine("test");
}
stream.Dispose();
}
catch
{
configText = "Error writing to file!";
infoLabel2.Text = configText;
}
}
The read function using streamreader works perfectly fine and reads the file displaying it ect, however although I'm using the same setup for the stream the streamwriter does not. Any help would be appreciated thanks.
Related
I need to save the information from an input page into a JSON File and output the information onto another page reading from the JSON File. I've tried many things and what seemed to work for me is using the specialfolder localapplication data.
Now, I don't quite understand how I can output the information and also check if the data is even put in correctly.
I previously used StreamReader to output the information on the JSON file and then put it on a ListView but this doesn't work if I have the file in the specialfolder. It says "stream cant be null". The commented out code is the code I tried in previous attempts.
Code:
ListPageVM (Read Page)
private ObservableCollection<MainModel> data;
public ObservableCollection<MainModel> Data
{
get { return data; }
set { data = value; OnPropertyChanged(); }
}
public ListPageVM()
{
var assembly = typeof(ListPageVM).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream(Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "eintraege.json"/"SaveUp.Resources.eintraege.json"/));
//var file = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "eintraege.json");
using (var reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
List<MainModel> dataList = JsonConvert.DeserializeObject<List<MainModel>>(json);
data = new ObservableCollection<MainModel>(dataList);
}
}
MainPageVM (Write Page)
public Command Einfügen
{
get
{
return new Command(() =>
{
// Data ins Json
_mainModels.Add(DModel);
Datum = DateTime.Now.ToString("dd.mm.yyyy");
//var assembly = typeof(ListPageVM).GetTypeInfo().Assembly;
//FileStream stream = new FileStream("SaveUp.Resources.eintraege.json", FileMode.OpenOrCreate, FileAccess.Write);
var file = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "eintraege.json");
//Stream stream = assembly.GetManifestResourceStream("SaveUp.Resources.eintraege.json");
if (!File.Exists(file))
{
File.Create(file);
}
using (var writer = File.AppendText(file))
{
string data = JsonConvert.SerializeObject(_mainModels);
writer.WriteLine(data);
}
});
}
}
you are trying to read and write resources, not files. That won't work. Instead do this
var path = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "eintraege.json");
File.WriteAllText(path, myjson);
to read the data back
var json = File.ReadAllText(path);
In my scenario, I have an use case where I must received a compressed file, do some validations and then find a specific file within the archive that I'll have to handle through a third-party library. I'm having some trouble getting such library to read the file though. This is what I came up with so far:
public async Task ShapeIt(ZipArchive archive)
{
foreach (var entry in archive.Entries)
{
if (Path.GetExtension(entry.FullName).Equals(".shp"))
{
var stream = entry.Open();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
ms.Position = 0;
var fileName = Path.GetTempFileName();
try
{
using var fileStream = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write,
FileShare.ReadWrite);
var bytes = new byte[ms.Length];
ms.Read(bytes, 0, (int)ms.Length);
fileStream.Write(bytes, 0, bytes.Length);
fileStream.Flush();
fileStream.Close();
var featureSource = new ShapeFileFeatureSource(fileName); // Class from 3rd-party
featureSource.Open();
// Do my stuff with the shapefile
}
finally
{
File.Delete(fileName);
}
}
}
}
Take notice that I'm using the "old way" of copying streams as Stream.CopyTo and Stream.CopyToAsync were creating empty files, explicitly calling fileStream.Close() looks like the only way to get the bytes into the file somehow, but that's beyond my point. Regardless, after closing the stream, upon calling featureSource.Open() my application throws
"The process cannot access the file 'C:\\Users\\me\\AppData\\Local\\Temp\\tmpE926.tmp' because it is
being used by another process."
tmpE926.tmp being different every time, obviously. Also take notice that I'm creating a file because the constructor for ShapeFileFeatureSource demands not a stream, not a byte array, but a path.
A much shorter implementation
public async Task ShapeIt(ZipArchive archive)
{
foreach (var entry in archive.Entries)
{
var tempFile = Path.GetTempFileName();
try
{
entry.ExtractToFile(tempFile, true);
if (Path.GetExtension(entry.FullName).Equals(".shp"))
{
var featureSource = new ShapeFileFeatureSource(tempFile);
featureSource.Open();
var type = featureSource.GetShapeFileType();
}
}
finally
{
File.Delete(tempFile);
}
}
}
will actually amount to the same error. I honestly don't think the problem lies within this library, but rather I'm the one screwing it up somehow. Does anyone have any ideas or should I contact the vendor's (unresponsive) tech support?
Edit: Just in case, this is such library Install-Package ThinkGeo.UI.WebApi but you have to subscribe to evaluate in order to use it.
I could not find package for .NET Core with such classes, so I reproduced it through .NET Framework Nuget package. My answer mostly demonstrates how to deal with streams. It would be hard to tell what is wrong with your code, without having access to library you have
using DotSpatial.Data;
using System.IO;
using System.IO.Compression;
namespace ConsoleApp12
{
class Program
{
static void Main(string[] args)
{
using (var fs = File.OpenRead(#"C:\Users\jjjjjjjjjjjj\Downloads\1270055001_mb_2011_vic_shape.zip"))
using (var zipFile = new ZipArchive(fs))
{
foreach (var entry in zipFile.Entries)
{
if (entry.FullName.EndsWith(".shp"))
{
var tempFile = Path.GetTempFileName();
try
{
using (var entryStream = entry.Open())
using (var newFileStream = File.OpenWrite(tempFile))
{
entryStream.CopyTo(newFileStream);
}
var featureSource = ShapefileFeatureSource.Open(tempFile);
var type = featureSource.ShapeType;
}
finally
{
File.Delete(tempFile);
}
}
}
}
}
}
}
UPD: installed trial version of ThinkGeo library, instead of unauthorized exception it gives me FileNotFoundException with given stacktrace
at ThinkGeo.Core.ValidatorHelper.CheckFileIsExist(String pathFilename)
at ThinkGeo.Core.ShapeFileIndex.xh8=(FileAccess readWriteMode)
^^^^^^^^^^^^^^^^^^^^^^^^^ Are we supposed to have index?
at ThinkGeo.Core.ShapeFile.xh8=(FileAccess readWriteMode)
at ThinkGeo.Core.ShapeFileFeatureSource.WjE=()
at ThinkGeo.Core.ShapeFileFeatureSource.OpenCore()
at ThinkGeo.Core.FeatureSource.Open()
at ConsoleApp20.Program.Main(String[] args) in
C:\Users\jjjjjjjjjjjj\source\repos\ConsoleApp20\ConsoleApp20\Program.cs:line 45
ShapeFileIndex ? So I thought I should dig into this way
var featureSource = new ShapeFileFeatureSource(tempFile);
featureSource.RequireIndex = false; // no luck
featureSource.Open();
I tried to find any reference to the idx file it wants, it has property IndexFilePathName, but unfortunately, I am out of luck. (Also tried different folder, so it is not 'Temp' folder issue)
This code morphed for a couple of days until I reached out to tech support, they tinkered with it a bit and came up with this:
public async Task ProcessFile(IFormFile file)
{
if (!Path.GetExtension(file.FileName).Equals(".zip"))
throw new System.Exception("File should be compressed in '.zip' format");
var filePaths = new List<string>();
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
using (var archive = new ZipArchive(stream, ZipArchiveMode.Read, false))
{
var replaceList = new Dictionary<string, string>();
foreach (ZipArchiveEntry entry in archive.Entries)
{
var tempPath = Path.GetTempFileName();
string key = Path.GetFileNameWithoutExtension(entry.FullName);
string value = Path.GetFileNameWithoutExtension(tempPath);
if (replaceList.ContainsKey(key))
{
value = replaceList[key];
}
else
{
replaceList.Add(key, value);
}
string unzippedPath = Path.Combine(Path.GetDirectoryName(tempPath), value + Path.GetExtension(entry.FullName));
entry.ExtractToFile(unzippedPath, true);
filePaths.Add(unzippedPath);
}
foreach (var unzippedPath in filePaths)
{
if (Path.GetExtension(unzippedPath).Equals(".shp"))
{
// Successfully doing third-party library stuff
}
}
foreach (var unzippedPath in filePaths)
{
if (File.Exists(unzippedPath))
{
File.Delete(unzippedPath);
}
}
}
}
}
It works. I'm happy.
I'm trying to remove specific line from file on IsolatedStorage but I'm still receiving the "Stream was not writeable" from following method:
public async static void RemoveFavoriteFromFile(int id)
{
string favoriteFilename = Globals.FavoriteFilepath;
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
var folder = await local.GetFolderAsync("DataFolder");
var file = await folder.OpenStreamForReadAsync(Globals.FavoriteFilepath);
using (StreamReader sr = new StreamReader(file))
{
using (StreamWriter sw = new StreamWriter(file))
{
string line = null;
while ((line = sr.ReadLine()) != null)
{
if (String.Compare(line, id.ToString()) == 0)
continue;
sw.WriteLine(line);
}
}
}
}
on line using (StreamWriter sw = new StreamWriter(file))
Could anybody help me please?
Thanks in advance
EDIT: I would mainly ask you to advice me how to remove specific line from existing file, no matter what I created already. Main issue for me in meaning of understanding is that how to write/edit a file which I firstly need to read for finding the specific line.
Reading and writing to the same file at the same time is always a bad idea.
Either write to a swap file "filename_swap.txt". After it has finished writing the entire file, delete the original file and rename the "filename_swap.txt" to the original file (basically replacing it).
Or you can read the entire file into a buffer, close the file. Make your changes to said buffer then open the file again for writing. This time, write the entire content of the modified buffer.
So lets modularize your program
using System.Threading.Tasks;
// read the specific file into a string buffer
private async Task<string> ReadFileIntoBuffer(string fileName)
{
string buffer = ""; // our buffer
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder; // local folder
var folder = await local.GetFolderAsync("DataFolder"); // sub folder
// open the file for reading
using (Stream s = await folder.OpenStreamForReadAsync(fileName))
{
using (StreamReader sr = new StreamReader(s))
{
buffer = await sr.ReadToEndAsync();
}
}
// return the buffer
return buffer;
}
// write the string buffer to a specific file
private async Task<bool> WriteBufferToFile(string fileName, string buffer)
{
try
{
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder; // local folder
var folder = await local.GetFolderAsync("DataFolder"); // sub folder
// open the file for writing
using (Stream s = await folder.OpenStreamForWriteAsync(fileName, CreationCollisionOption.ReplaceExisting))
{
using (StreamWriter sw = new StreamWriter(s))
{
await sw.WriteAsync(buffer);
}
}
}
catch (Exception ex)
{
string error_message = ex.Message;
return false;
}
return true;
}
// New Delete Lines function based off your old one
private string DeleteLines(string input_buffer, int id)
{
string output_buffer = "";
using (StringReader sr = new StringReader(input_buffer))
{
while (true)
{
string line = sr.ReadLine();
if (line != null)
{
if (String.Compare(line, id.ToString()) == 0)
{
}
else
{
// add it to the output_buffer plus the newline
output_buffer += (line + "\n");
}
}
else
{
break;
}
}
}
return output_buffer;
}
If you have trouble understanding a problem it generally a good idea to break it into smaller parts and debug from there.
Hi i'm stucked in a problem, i created a txt file that i put on the app. I'm trying to read from it the content that i write on it before. With that code:
public async Task WriteDataToFileAsync(string fileName, string content)
{
byte[] data = Encoding.Unicode.GetBytes(content);
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(fileName,CreationCollisionOption.ReplaceExisting);
using (var s = await file.OpenStreamForWriteAsync())
{
await s.WriteAsync(data, 0, data.Length);
}
}
public async Task<string> ReadFileContentsAsync(string fileName)
{
var folder = ApplicationData.Current.LocalFolder;
try
{
var file = await folder.OpenStreamForReadAsync(fileName);
using (var streamReader = new StreamReader(file))
{
return streamReader.ReadToEnd();
}
}
catch (Exception)
{
MessageBox.Show("Error");
return string.Empty;
}
}
private async void functionWhereNeedReeding()
{
string contents = await this.ReadFileContentsAsync("myimportedfile.txt");
MessageBox.Show(contents);
}
Give me all times the message of error and i can't understand where is my mistake. Hoping that you'll help me. For sure contents is still empty.
I created a helper function in my WP 7 project recently, to read a text file included in the project. You can try to use it, the function also working in WP 8 project :
public static class FileHelper
{
public static string ReadFile(string filePath)
{
var ResrouceStream = Application.GetResourceStream(new Uri(filePath, UriKind.Relative));
if (ResrouceStream != null)
{
Stream myFileStream = ResrouceStream.Stream;
if (myFileStream.CanRead)
{
StreamReader myStreamReader = new StreamReader(myFileStream);
return myStreamReader.ReadToEnd();
}
}
return "";
}
}
Then I can use that function this way (in this example the file resides under Assets folder) :
var textFileContent = FileHelper.ReadFile(#"Assets\MyTextFile.txt");
I've noticed that if I persist an object back into file using a Datacontractserializer, if the length of the new xml is shorter than the xml originally present in the file the remnants of the original xml outwith the length of the new xml will remain in the file and will break the xml.
Does anyone have a good solution to fix this?
Here's the code I am using to persist the object:
/// <summary>
/// Flushes the current instance of the given type to the datastore.
/// </summary>
private void Flush()
{
try
{
string directory = Path.GetDirectoryName(this.fileName);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
FileStream stream = null;
try
{
stream = new FileStream(this.fileName, FileMode.OpenOrCreate);
for (int i = 0; i < 3; i++)
{
try
{
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream, new System.Text.UTF8Encoding(false)))
{
stream = null;
// The serializer is initialized upstream.
this.serializer.WriteObject(writer, this.objectValue);
}
break;
}
catch (IOException)
{
Thread.Sleep(200);
}
}
}
finally
{
if (stream != null)
{
stream.Dispose();
}
}
}
catch
{
// TODO: Localize this
throw;
//throw new IOException(String.Format(CultureInfo.CurrentCulture, "Unable to save persistable object to file {0}", this.fileName));
}
}
It's because of how you are opening your stream with:
stream = new FileStream(this.fileName, FileMode.OpenOrCreate);
Try using:
stream = new FileStream(this.fileName, FileMode.Create);
See FileMode documentation.
I believe this is due to using FileMode.OpenOrCreate. If the file already exits, I think the file is being opened and parts of the data are being overwritten from the start byte. If you change to using FileMode.Create it forces any existing files to be overwritten.