18

I'm having trouble when creating a StreamWriter object in windows-8, usually I just create an instance just passing a string as a parameter, but in Windows 8 I get an error that indicates that it should recieve a Stream, but I noticed that Stream is an abstract class, Does anybody knows how will be the code to write an xml file?, BTW I'm using .xml because I want to save the serialized object, or does anyone knows how to save to a file a serialized object in Windows 8?.

Any ideas?

Currently using Windows 8 Consumer Preview

Code:

StreamWriter sw = new StreamWriter("person.xml");

Error:

The best overloaded method match for 'System.IO.StreamWriter.StreamWriter(System.IO.Stream)' has some invalid arguments

MilkyWayJoe
  • 9,082
  • 2
  • 38
  • 53
Jorge Montaño
  • 305
  • 1
  • 2
  • 9
  • 1
    This has nothing to do with Windows 8 or any OS. You just need to pass the correct parameter to the constructor. When it says it needs a `Stream` you have to use a class that extends `Stream`. I would suggest that you *google* about `Stream`. The first result I got even shows a video of how to use it (http://www.youtube.com/watch?v=QKGjWMlba9s) – MilkyWayJoe Apr 24 '12 at 02:15
  • 1
    thanks for the quick reply, but in fact I know how to use the StreamWriter class, but in this case I created a Windows Metro Style project and I'm working with XAML, and the StreamWriter class it does not work as it used to work in Windows Form apps, I just get this error, and even that I tried what you proposed (create a class that extends the Stream class), it just implements empty methods and does not have a method that receive as a parameter the path where the stream will be created... – Jorge Montaño Apr 24 '12 at 02:37
  • ..., all that I found in google, just display the way I know about how to create a StreamWriter object, I couldn't find any reference that indicates how to create a StreamWriter or Stream in a Windows Metro project. Does anybody work with Streams in a Windows Metro Project, how will be the code for write a file using StreamWriter? – Jorge Montaño Apr 24 '12 at 02:38
  • 3
    This is one of the fundamental changes in WinRT. You can't just write a file anywhere you want anymore, you have to use isolated storage. And you need to use asynchronous I/O with the await keyword. Can't find a good example and not close to a Win8 machine right now. – Hans Passant Apr 24 '12 at 03:04
  • thanks Hans, I think that is the answer I was expecting, could you please provide me a link where I can find more information about you just answered. Thanks in advance. – Jorge Montaño Apr 24 '12 at 03:21

2 Answers2

27

Instead of StreamWriter you would use something like this:

StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.CreateFileAsync();

using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
    using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
    {
        using (DataWriter dataWriter = new DataWriter(outputStream))
        {
            //TODO: Replace "Bytes" with the type you want to write.
            dataWriter.WriteBytes(bytes);
            await dataWriter.StoreAsync();
            dataWriter.DetachStream();
        }

        await outputStream.FlushAsync();
    }
}

You can look at the StringIOExtensions class in the WinRTXamlToolkit library for sample use.

EDIT*

While all the above should work - they were written before the FileIO class became available in WinRT, which simplifies most of the common scenarios that the above solution solves since you can now just call await FileIO.WriteTextAsync(file, contents) to write text into file and there are also similar methods to read, write or append strings, bytes, lists of strings or IBuffers.

Michael Kohne
  • 11,888
  • 3
  • 47
  • 79
Filip Skakun
  • 31,624
  • 6
  • 74
  • 100
4

You can create a common static method which you can use through out application like this

 private async Task<T> ReadXml<T>(StorageFile xmldata)
    {
        XmlSerializer xmlser = new XmlSerializer(typeof(List<myclass>));
        T data;
        using (var strm = await xmldata.OpenStreamForReadAsync())
        {
            TextReader Reader = new StreamReader(strm);
            data = (T)xmlser.Deserialize(Reader);
        }
        return data;
    }

    private async Task writeXml<T>(T Data, StorageFile file)
    {
        try
        {
            StringWriter sw = new StringWriter();
            XmlSerializer xmlser = new XmlSerializer(typeof(T));
            xmlser.Serialize(sw, Data);

            using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
                {
                    using (DataWriter dataWriter = new DataWriter(outputStream))
                    {
                        dataWriter.WriteString(sw.ToString());
                        await dataWriter.StoreAsync();
                        dataWriter.DetachStream();
                    }

                    await outputStream.FlushAsync();
                }
            }


        }
        catch (Exception e)
        {
            throw new NotImplementedException(e.Message.ToString());

        }

    }

to write xml simply use

 StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("data.xml",CreationCollisionOption.ReplaceExisting);
        await  writeXml(Data,file);

and to read xml use

  StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("data.xml");
      Data =  await  ReadXml<List<myclass>>(file);
Shivam cv
  • 526
  • 5
  • 16