Write and Read from a file - c#

I have been following this tutorial http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj681698%28v=vs.105%29.aspx.
So far is what I was searching for, but the only problem is that when i close and open the app again the file and the text is not saved anymore, so I want to the file be saved forever with the text.
I want to it be saved here http://gyazo.com/82e838cd2385cea7021647a8d39f49a8.png/level/batlevel.txt. So when I can open the app again the text that was write there it will be there
private async void btnWrite_Click(object sender, RoutedEventArgs e)
{
await WriteToFile();
// Update UI.
this.btnWrite.IsEnabled = false;
this.btnRead.IsEnabled = true;
}
private async Task WriteToFile()
{
// Get the text data from the textbox.
byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(this.textBox1.Text.ToCharArray());
// Get the local folder.
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
// Create a new folder name DataFolder.
var dataFolder = await local.CreateFolderAsync("level",
CreationCollisionOption.OpenIfExists);
// Create a new file named DataFile.txt.
var file = await dataFolder.CreateFileAsync("level.txt",
CreationCollisionOption.ReplaceExisting);
// Write the data from the textbox.
using (var s = await file.OpenStreamForWriteAsync())
{
s.Write(fileBytes, 0, fileBytes.Length);
}
}
private async void btnRead_Click(object sender, RoutedEventArgs e)
{
await ReadFile();
// Update UI.
this.btnWrite.IsEnabled = true;
this.btnRead.IsEnabled = false;
}
private async Task ReadFile()
{
// Get the local folder.
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
if (local != null)
{
// Get the DataFolder folder.
var dataFolder = await local.GetFolderAsync("level");
// Get the file.
var file = await dataFolder.OpenStreamForReadAsync("level.txt");
// Read the data.
using (StreamReader streamReader = new StreamReader(file))
{
this.textBlock1.Text = streamReader.ReadToEnd();
}
}
}
}
}

I believe you should be opening your level.txt file with the OpenIfExists option instead of ReplaceExisting :
// Create a new file named DataFile.txt.
var file = await dataFolder.CreateFileAsync( "level.txt", CreationCollisionOption.OpenIfExists );

Related

Is it possible to convert an Image in IFormFile

I'm trying to store a model informations in my Data Base, this informations contain an image, so I created a simple view with some entrys, with a media picker button to pick it and an image witch display the picked one.
This is the button method and the store method:
async void Button_Clicked(System.Object sender, System.EventArgs e)
{
var result = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
{
Title = "Please pick a photo"
});
if (result != null)
{
var stream = await result.OpenReadAsync();
resultImage.Source = ImageSource.FromStream(() => stream);
}
}
public async Task SaveMachine()
{
var machine = new Machine
{
Machine_Name = nom.Text,
Machine_Qr = qr.Text,
Files = resultImage
};
await _rest.AddMachine(machine);
await Shell.Current.GoToAsync("..");
}
But I can't create Files = resultImage because the Files in the model is in IFormFile.

Clicked Item not playing song and giving error `The system cannot find the file specified'

I am trying to play a song from my listview in UWP. However when I click on the song (listview item) to play it I get the follwing error:
System.IO.FileNotFoundException: 'The system cannot find the file specified. (Exception from HRESULT: 0x80070002)'
This is my code:
private async Task InitFolderAsync()
{
StorageFolder musicLib = KnownFolders.MusicLibrary;
var files = await musicLib.GetFilesAsync();
foreach (var file in files)
{
StorageItemThumbnail currentThumb = await file.GetThumbnailAsync(ThumbnailMode.MusicView, 50, ThumbnailOptions.UseCurrentScale);
var albumCover = new BitmapImage();
albumCover.SetSource(currentThumb);
var musicProperties = await file.Properties.GetMusicPropertiesAsync();
var musicname = musicProperties.Title;
var musicdur = musicProperties.Duration;
var artist = musicProperties.Artist;
if (artist == "")
{
artist = "Unknown";
}
var album = musicProperties.Album;
if (album == "")
{
album = "Unknown";
}
MusicList.Add(new MusicLib
{
FileName = musicname,
Artist = artist,
Album = album,
Duration = musicdur,
AlbumCover = albumCover,
MusicPath = file.Path
});
}
}
private async void SongClicked(object sender, ItemClickEventArgs e)
{
var file = await KnownFolders.MusicLibrary.GetFileAsync(e.ClickedItem.ToString());
if (file != null)
{
var stream = await file.OpenReadAsync();
mediaElement.SetSource(stream, file.ContentType);
mediaElement.Play();
}
}
private async void objMediaPlayer_MediaEnded(object sender, RoutedEventArgs e)
{
// If the end of the ListView is reached and the last song was played stop.
if ((AudioFilesLV.SelectedIndex + 1) == AudioFilesLV.Items.Count)
{
mediaElement.Stop();
}
else
{
// This line you should try to change. When the last song was not played
//-> select next one and play them.
AudioFilesLV.SelectedIndex = AudioFilesLV.SelectedIndex + 1;
var file = await KnownFolders.MusicLibrary.GetFileAsync(AudioFilesLV.SelectedItem.ToString());
if (file != null)
{
var stream = await file.OpenReadAsync();
mediaElement.SetSource(stream, file.ContentType);
mediaElement.Play();
}
}
}
So basically after you click on the song to play it should then automatically go to the next song and play it. I haven't got to that stage yet as it does not want to play the song I clicked.
Thanks
Try to cast e.ClickedItem to a MusicLib and then pass its MusicPath to the GetFileAsync method:
private async void SongClicked(object sender, ItemClickEventArgs e)
{
var clickedItem = e.ClickedItem as MusicLib;
if (clickedItem != null)
{
var file = await KnownFolders.MusicLibrary.GetFileAsync(clickedItem.MusicPath);
if (file != null)
{
var stream = await file.OpenReadAsync();
mediaElement.SetSource(stream, file.ContentType);
mediaElement.Play();
}
}
}

Resumable download Google Drive API

I am using the Google Drive API to download files from Google Drive, it works fine, but I want to do more pause and resume functionality.
I read the instructions page of Google and found support for partial downloads (https://developers.google.com/drive/api/v3/manage-downloads), they said "You can specify the portion of the file you want to dowload by using a byte range with the Range header", but I don't know how to do it, who can help me?
This is my code:
string fileId;
string path;
long bytes;
private void DownloadWorker_DoWork(object sender, DoWorkEventArgs e)
{
DriveService ds = GetService();
var request = ds.Files.Get(fileId);
using (var stream = new MemoryStream())
{
request.MediaDownloader.ProgressChanged += (Google.Apis.Download.IDownloadProgress progress) =>
{
switch (progress.Status)
{
case Google.Apis.Download.DownloadStatus.Downloading:
{
bytes = progress.BytesDownloaded;
GoogleDrive.ReportProgress((int)bytes);
break;
}
case Google.Apis.Download.DownloadStatus.Completed:
{
SaveStream(stream);
break;
}
case Google.Apis.Download.DownloadStatus.Failed:
{
break;
}
}
};
request.Download(stream);
}
}
private void DownloadWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
}
private void DownloadWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
private void SaveStream(MemoryStream stream)
{
long exlength = 0;
if (System.IO.File.Exists(path))
{
var fileInfo = new FileInfo(path);
exlength = fileInfo.Length;
}
var fileMode = exlength > 0 ? FileMode.Append : FileMode.Create;
using (FileStream file = new FileStream(path, fileMode, FileAccess.Write))
{
stream.WriteTo(file);
}
}
private void Button1_Click(object sender, EventArgs e)
{
fileId = "1P2KckTacknNDsONttlzL4GPLSLldzCbA";
path = "D:\\Data.zip";
GoogleDrive.RunWorkerAsync();
}
There is already an answer similar to what you want to achieve here [1] but with an export request. Basically, after you get the request (and before you send it) you need to set the Range header as stated in the link you posted. For your case it would be like this:
DriveService ds = GetService();
var request = ds.Files.Get(fileId);
//Set the range header
request.Headers.Range = new RangeHeaderValue(from, to);
//More codeā€¦
//Send the request
request.Download(stream);
[1] C# - Downloading from Google Drive in byte chunks

Call file from another method

Newbie question here. I have this file picker:
public async void PickImage()
{
FileOpenPicker ImagePicker = new FileOpenPicker();
...
StorageFile file = await ImagePicker.PickSingleFileAsync(); //
...
}
And I want to use the file set by this image picker in another method. Something like this:
private async void CreateButton_Click(object sender, RoutedEventArgs e)
{
... the one from PickImage()
v
StorageFile copyImage = await file.CopyAsync(DateTimeFolder, "image", NameCollisionOption.ReplaceExisting);
...
}
It is obviously not working like this. How can I do it?
Ok, based on the answers I got, this is what I came up with:
public async Task<StorageFile> PickImage()
{
FileOpenPicker ImagePicker = new FileOpenPicker();
ImagePicker.FileTypeFilter.Add(".jpg");
ImagePicker.FileTypeFilter.Add(".jpeg");
ImagePicker.FileTypeFilter.Add(".png");
ImagePicker.ViewMode = PickerViewMode.Thumbnail;
ImagePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
StorageFile file = await ImagePicker.PickSingleFileAsync();
if (file != null)
{
IRandomAccessStream imageStream = await file.OpenAsync(FileAccessMode.Read);
var bmpImage = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
bmpImage.DecodePixelHeight = 150;
bmpImage.DecodePixelWidth = 310;
bmpImage.SetSource(imageStream);
ImagePreview.Source = bmpImage;
}
return file;
}
////
private async void CreateButton_Click(object sender, RoutedEventArgs e)
{
...
string DateTimeNow = DateTime.Now.ToString("HHmmssddMMyyyy");
StorageFolder docs = KnownFolders.DocumentsLibrary;
StorageFolder myDir = await docs.CreateFolderAsync("My Dir", Windows.Storage.CreationCollisionOption.OpenIfExists);
StorageFolder DateTimeFolder = await myDir.CreateFolderAsync(DateTimeNow);
//StorageFile image = await PickImage();
StorageFile copyImage = await PickImage().CopyAsync(DateTimeFolder, "image", NameCollisionOption.ReplaceExisting);
...
}
But the last line gives me an error:
'System.Threading.Tasks.Task' does not contain a definition for 'CopyAsync' and no extension method 'CopyAsync' accepting a first argument of type 'System.Threading.Tasks.Task' could be found (are you missing a using directive or an assembly reference?)
You need to either set a field in the class or return the StorageFile. I would suggest changing PickImage() to return the StorageFile so you're code would instead look like this;
public async StorageFile PickImage()
{
FileOpenPicker ImagePicker = new FileOpenPicker();
...
return await ImagePicker.PickSingleFileAsync(); //
...
}
private async void CreateButton_Click(object sender, RoutedEventArgs e)
{
StorageFile pickedFile = await PickImage();
StorageFile copyImage = await file.CopyAsync(DateTimeFolder, "image", NameCollisionOption.ReplaceExisting);
...
}
Or something to that effect. I'm slightly confused by the second line in your CreateButton_Click method because I thought you wanted to operate on the file from PickImage but instead you're creating a new file. If you want the StorageFile to persist just make it a field on the form class and set it in PickImage
As pointed by Andre in the comments, your PickImage should return the file, so you could do the following:
public async StorageFile PickImage()
{
FileOpenPicker ImagePicker = new FileOpenPicker();
...
StorageFile file = await ImagePicker.PickSingleFileAsync(); //
...
return file;
}
private async void CreateButton_Click(object sender, RoutedEventArgs e)
{
...
StorageFile copyImage = await this.PickImage().CopyAsync(DateTimeFolder, "image", NameCollisionOption.ReplaceExisting);
...
}
Depending on the location of the two methods, there are two solutions:
If the methods are located in the same class file, you can declare StorageFile file as a local variable in the class file. In that way, you can reach it from the CreateButton_click function
If cross threading is involved (methods are working in separate threads), you need to use delegates and invoke them. Detailed information is available here through an example.

Windows 8 c# save a camera's picture on local storage

I'm new to C# and I want to create an application metro who can take picture and save themself in localstorage. I know, i need to use isolated storage but i really don't understand how to use it for image. I saw a lot of examples for string but not for picture.
If anyone know how to do it ? Actually i take a picture and i ask the user to record it where he wants. But I want an auto record after the user take the picture. This my code for the moment :
private async void Camera_Clicked(object sender, TappedRoutedEventArgs e)
{
CameraCaptureUI camera = new CameraCaptureUI();
camera.PhotoSettings.CroppedAspectRatio = new Size(16, 9);
StorageFile photo = await camera.
CaptureFileAsync(CameraCaptureUIMode.Photo);
if (photo != null)
{
BitmapImage bmp = new BitmapImage();
IRandomAccessStream stream = await photo.
OpenAsync(FileAccessMode.Read);
bmp.SetSource(stream);
ImageSource.Source = bmp;
ImageSource.Visibility = Visibility.Visible;
appSettings[photoKey] = photo.Path;
FileSavePicker savePicker = new FileSavePicker();
savePicker.FileTypeChoices.Add
("jpeg image", new List<string>() { ".jpeg" });
savePicker.SuggestedFileName = "New picture";
StorageFile ff = await savePicker.PickSaveFileAsync();
if (ff != null)
{
await photo.MoveAndReplaceAsync(ff);
}
}
}
All what you need to do is to replace File Picker logic with retrieving of StorageFile object in Local folder, for example like this:
private async void Camera_Clicked(object sender, TappedRoutedEventArgs e)
{
CameraCaptureUI camera = new CameraCaptureUI();
camera.PhotoSettings.CroppedAspectRatio = new Size(16, 9);
StorageFile photo = await camera.
CaptureFileAsync(CameraCaptureUIMode.Photo);
if (photo != null)
{
var targetFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("some_file_name.jpg");
if (targetFile != null)
{
await photo.MoveAndReplaceAsync(targetFile);
}
}
}

Categories